blob: 9e81149969fe9e63a9a3518e0f4e696589863794 [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);
700 if (mDataStore.getCurrentKeyboardLayout(inputDevice.getDescriptor()) == null) {
701 missingLayoutForExternalKeyboard = true;
702 if (i < numFullKeyboardsAdded) {
703 missingLayoutForExternalKeyboardAdded = true;
704 }
705 }
706 }
707 }
708 if (missingLayoutForExternalKeyboard) {
709 if (missingLayoutForExternalKeyboardAdded) {
710 showMissingKeyboardLayoutNotification();
711 }
712 } else if (mKeyboardLayoutNotificationShown) {
713 hideMissingKeyboardLayoutNotification();
714 }
715 }
716 mTempFullKeyboards.clear();
717 }
718
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800719 @Override // Binder call & native callback
Jason Gerecked5220742014-03-10 09:47:59 -0700720 public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
721 int surfaceRotation) {
Jason Gerecked6396d62014-01-27 18:30:37 -0800722 if (inputDeviceDescriptor == null) {
723 throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
724 }
725
726 synchronized (mDataStore) {
Jason Gerecked5220742014-03-10 09:47:59 -0700727 return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
Jason Gerecked6396d62014-01-27 18:30:37 -0800728 }
729 }
730
731 @Override // Binder call
Jason Gerecked5220742014-03-10 09:47:59 -0700732 public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
Jason Gerecked6396d62014-01-27 18:30:37 -0800733 TouchCalibration calibration) {
734 if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
735 "setTouchCalibrationForInputDevice()")) {
736 throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
737 }
738 if (inputDeviceDescriptor == null) {
739 throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
740 }
741 if (calibration == null) {
742 throw new IllegalArgumentException("calibration must not be null");
743 }
Jason Gerecked5220742014-03-10 09:47:59 -0700744 if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
745 throw new IllegalArgumentException("surfaceRotation value out of bounds");
746 }
Jason Gerecked6396d62014-01-27 18:30:37 -0800747
748 synchronized (mDataStore) {
749 try {
Jason Gerecked5220742014-03-10 09:47:59 -0700750 if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
751 calibration)) {
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800752 nativeReloadCalibration(mPtr);
753 }
Jason Gerecked6396d62014-01-27 18:30:37 -0800754 } finally {
755 mDataStore.saveIfNeeded();
756 }
757 }
758 }
759
Jeff Browncf39bdf2012-05-18 14:41:19 -0700760 // Must be called on handler.
761 private void showMissingKeyboardLayoutNotification() {
762 if (!mKeyboardLayoutNotificationShown) {
763 if (mKeyboardLayoutIntent == null) {
764 final Intent intent = new Intent("android.settings.INPUT_METHOD_SETTINGS");
765 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
766 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
767 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700768 mKeyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
769 intent, 0, null, UserHandle.CURRENT);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700770 }
771
772 Resources r = mContext.getResources();
773 Notification notification = new Notification.Builder(mContext)
774 .setContentTitle(r.getString(
775 R.string.select_keyboard_layout_notification_title))
776 .setContentText(r.getString(
777 R.string.select_keyboard_layout_notification_message))
778 .setContentIntent(mKeyboardLayoutIntent)
779 .setSmallIcon(R.drawable.ic_settings_language)
780 .setPriority(Notification.PRIORITY_LOW)
Selim Cinek255dd042014-08-19 22:29:02 +0200781 .setColor(mContext.getResources().getColor(
782 com.android.internal.R.color.system_notification_accent_color))
Jeff Browncf39bdf2012-05-18 14:41:19 -0700783 .build();
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700784 mNotificationManager.notifyAsUser(null,
785 R.string.select_keyboard_layout_notification_title,
786 notification, UserHandle.ALL);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700787 mKeyboardLayoutNotificationShown = true;
788 }
789 }
790
791 // Must be called on handler.
792 private void hideMissingKeyboardLayoutNotification() {
793 if (mKeyboardLayoutNotificationShown) {
794 mKeyboardLayoutNotificationShown = false;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700795 mNotificationManager.cancelAsUser(null,
796 R.string.select_keyboard_layout_notification_title,
797 UserHandle.ALL);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700798 }
799 }
800
801 // Must be called on handler.
802 private void updateKeyboardLayouts() {
803 // Scan all input devices state for keyboard layouts that have been uninstalled.
804 final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
805 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
806 @Override
807 public void visitKeyboardLayout(Resources resources,
808 String descriptor, String label, String collection, int keyboardLayoutResId) {
809 availableKeyboardLayouts.add(descriptor);
810 }
811 });
812 synchronized (mDataStore) {
813 try {
814 mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
815 } finally {
816 mDataStore.saveIfNeeded();
817 }
818 }
819
820 // Reload keyboard layouts.
821 reloadKeyboardLayouts();
822 }
823
Jeff Browncf39bdf2012-05-18 14:41:19 -0700824 private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices,
825 String descriptor) {
826 final int numDevices = inputDevices.length;
827 for (int i = 0; i < numDevices; i++) {
828 final InputDevice inputDevice = inputDevices[i];
829 if (inputDevice.getDescriptor().equals(descriptor)) {
830 return true;
831 }
832 }
833 return false;
Jeff Brown8d608662010-08-30 03:02:23 -0700834 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700835
836 @Override // Binder call
837 public KeyboardLayout[] getKeyboardLayouts() {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700838 final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
839 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
840 @Override
841 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700842 String descriptor, String label, String collection, int keyboardLayoutResId) {
843 list.add(new KeyboardLayout(descriptor, label, collection));
Jeff Brown6ec6f792012-04-17 16:52:41 -0700844 }
845 });
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700846 return list.toArray(new KeyboardLayout[list.size()]);
847 }
848
849 @Override // Binder call
850 public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
851 if (keyboardLayoutDescriptor == null) {
852 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
853 }
854
Jeff Brown6ec6f792012-04-17 16:52:41 -0700855 final KeyboardLayout[] result = new KeyboardLayout[1];
856 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
857 @Override
858 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700859 String descriptor, String label, String collection, int keyboardLayoutResId) {
860 result[0] = new KeyboardLayout(descriptor, label, collection);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700861 }
862 });
863 if (result[0] == null) {
864 Log.w(TAG, "Could not get keyboard layout with descriptor '"
865 + keyboardLayoutDescriptor + "'.");
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700866 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700867 return result[0];
868 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700869
Jeff Brown6ec6f792012-04-17 16:52:41 -0700870 private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700871 final PackageManager pm = mContext.getPackageManager();
Jeff Brown6ec6f792012-04-17 16:52:41 -0700872 Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
873 for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
874 PackageManager.GET_META_DATA)) {
875 visitKeyboardLayoutsInPackage(pm, resolveInfo.activityInfo, null, visitor);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700876 }
877 }
878
Jeff Brown6ec6f792012-04-17 16:52:41 -0700879 private void visitKeyboardLayout(String keyboardLayoutDescriptor,
880 KeyboardLayoutVisitor visitor) {
881 KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor);
882 if (d != null) {
883 final PackageManager pm = mContext.getPackageManager();
884 try {
885 ActivityInfo receiver = pm.getReceiverInfo(
886 new ComponentName(d.packageName, d.receiverName),
887 PackageManager.GET_META_DATA);
888 visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, visitor);
889 } catch (NameNotFoundException ex) {
890 }
891 }
892 }
893
894 private void visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver,
895 String keyboardName, KeyboardLayoutVisitor visitor) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700896 Bundle metaData = receiver.metaData;
897 if (metaData == null) {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700898 return;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700899 }
900
901 int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS);
902 if (configResId == 0) {
903 Log.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
904 + "' on receiver " + receiver.packageName + "/" + receiver.name);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700905 return;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700906 }
907
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700908 CharSequence receiverLabel = receiver.loadLabel(pm);
909 String collection = receiverLabel != null ? receiverLabel.toString() : "";
910
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700911 try {
912 Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
913 XmlResourceParser parser = resources.getXml(configResId);
914 try {
915 XmlUtils.beginDocument(parser, "keyboard-layouts");
916
917 for (;;) {
918 XmlUtils.nextElement(parser);
919 String element = parser.getName();
920 if (element == null) {
921 break;
922 }
923 if (element.equals("keyboard-layout")) {
924 TypedArray a = resources.obtainAttributes(
925 parser, com.android.internal.R.styleable.KeyboardLayout);
926 try {
927 String name = a.getString(
928 com.android.internal.R.styleable.KeyboardLayout_name);
929 String label = a.getString(
930 com.android.internal.R.styleable.KeyboardLayout_label);
Jeff Brown2f095762012-05-10 21:29:33 -0700931 int keyboardLayoutResId = a.getResourceId(
932 com.android.internal.R.styleable.KeyboardLayout_keyboardLayout,
933 0);
934 if (name == null || label == null || keyboardLayoutResId == 0) {
935 Log.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700936 + "attributes in keyboard layout "
937 + "resource from receiver "
938 + receiver.packageName + "/" + receiver.name);
939 } else {
940 String descriptor = KeyboardLayoutDescriptor.format(
941 receiver.packageName, receiver.name, name);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700942 if (keyboardName == null || name.equals(keyboardName)) {
943 visitor.visitKeyboardLayout(resources, descriptor,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700944 label, collection, keyboardLayoutResId);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700945 }
946 }
947 } finally {
948 a.recycle();
949 }
950 } else {
951 Log.w(TAG, "Skipping unrecognized element '" + element
952 + "' in keyboard layout resource from receiver "
953 + receiver.packageName + "/" + receiver.name);
954 }
955 }
956 } finally {
957 parser.close();
958 }
959 } catch (Exception ex) {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700960 Log.w(TAG, "Could not parse keyboard layout resource from receiver "
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700961 + receiver.packageName + "/" + receiver.name, ex);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700962 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700963 }
964
RoboErikfb290df2013-12-16 11:27:55 -0800965 /**
966 * Builds a layout descriptor for the vendor/product. This returns the
967 * descriptor for ids that aren't useful (such as the default 0, 0).
968 */
969 private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
970 if (identifier == null || identifier.getDescriptor() == null) {
971 throw new IllegalArgumentException("identifier and descriptor must not be null");
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700972 }
973
RoboErikfb290df2013-12-16 11:27:55 -0800974 if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
975 return identifier.getDescriptor();
976 }
977 StringBuilder bob = new StringBuilder();
978 bob.append("vendor:").append(identifier.getVendorId());
979 bob.append(",product:").append(identifier.getProductId());
980 return bob.toString();
981 }
982
983 @Override // Binder call
984 public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
985
986 String key = getLayoutDescriptor(identifier);
Jeff Browna3bc5652012-04-17 11:42:25 -0700987 synchronized (mDataStore) {
RoboErikfb290df2013-12-16 11:27:55 -0800988 String layout = null;
989 // try loading it using the layout descriptor if we have it
990 layout = mDataStore.getCurrentKeyboardLayout(key);
991 if (layout == null && !key.equals(identifier.getDescriptor())) {
992 // if it doesn't exist fall back to the device descriptor
993 layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
994 }
995 if (DEBUG) {
996 Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got "
997 + layout);
998 }
999 return layout;
Jeff Browna3bc5652012-04-17 11:42:25 -07001000 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001001 }
1002
1003 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001004 public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001005 String keyboardLayoutDescriptor) {
1006 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001007 "setCurrentKeyboardLayoutForInputDevice()")) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001008 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1009 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001010 if (keyboardLayoutDescriptor == null) {
1011 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1012 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001013
RoboErikfb290df2013-12-16 11:27:55 -08001014 String key = getLayoutDescriptor(identifier);
Jeff Browna3bc5652012-04-17 11:42:25 -07001015 synchronized (mDataStore) {
1016 try {
RoboErikfb290df2013-12-16 11:27:55 -08001017 if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
1018 if (DEBUG) {
1019 Slog.d(TAG, "Saved keyboard layout using " + key);
1020 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001021 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1022 }
Jeff Browna3bc5652012-04-17 11:42:25 -07001023 } finally {
1024 mDataStore.saveIfNeeded();
1025 }
1026 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001027 }
Jeff Brown6ec6f792012-04-17 16:52:41 -07001028
Jeff Browncf39bdf2012-05-18 14:41:19 -07001029 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001030 public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
1031 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001032 synchronized (mDataStore) {
RoboErikfb290df2013-12-16 11:27:55 -08001033 String[] layouts = mDataStore.getKeyboardLayouts(key);
1034 if ((layouts == null || layouts.length == 0)
1035 && !key.equals(identifier.getDescriptor())) {
1036 layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
1037 }
1038 return layouts;
Jeff Browncf39bdf2012-05-18 14:41:19 -07001039 }
1040 }
1041
1042 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001043 public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001044 String keyboardLayoutDescriptor) {
1045 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1046 "addKeyboardLayoutForInputDevice()")) {
1047 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1048 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001049 if (keyboardLayoutDescriptor == null) {
1050 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1051 }
1052
RoboErikfb290df2013-12-16 11:27:55 -08001053 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001054 synchronized (mDataStore) {
1055 try {
RoboErikfb290df2013-12-16 11:27:55 -08001056 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1057 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1058 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1059 }
1060 if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
Jeff Browncf39bdf2012-05-18 14:41:19 -07001061 && !Objects.equal(oldLayout,
RoboErikfb290df2013-12-16 11:27:55 -08001062 mDataStore.getCurrentKeyboardLayout(key))) {
Jeff Browncf39bdf2012-05-18 14:41:19 -07001063 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1064 }
1065 } finally {
1066 mDataStore.saveIfNeeded();
Jeff Brown6ec6f792012-04-17 16:52:41 -07001067 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001068 }
1069 }
1070
1071 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001072 public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001073 String keyboardLayoutDescriptor) {
1074 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1075 "removeKeyboardLayoutForInputDevice()")) {
1076 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1077 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001078 if (keyboardLayoutDescriptor == null) {
1079 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1080 }
1081
RoboErikfb290df2013-12-16 11:27:55 -08001082 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001083 synchronized (mDataStore) {
1084 try {
RoboErikfb290df2013-12-16 11:27:55 -08001085 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1086 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1087 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1088 }
1089 boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
1090 if (!key.equals(identifier.getDescriptor())) {
1091 // We need to remove from both places to ensure it is gone
1092 removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
1093 keyboardLayoutDescriptor);
1094 }
1095 if (removed && !Objects.equal(oldLayout,
1096 mDataStore.getCurrentKeyboardLayout(key))) {
Jeff Browncf39bdf2012-05-18 14:41:19 -07001097 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1098 }
1099 } finally {
1100 mDataStore.saveIfNeeded();
1101 }
1102 }
1103 }
1104
1105 public void switchKeyboardLayout(int deviceId, int direction) {
1106 mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
1107 }
1108
1109 // Must be called on handler.
1110 private void handleSwitchKeyboardLayout(int deviceId, int direction) {
1111 final InputDevice device = getInputDevice(deviceId);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001112 if (device != null) {
1113 final boolean changed;
1114 final String keyboardLayoutDescriptor;
RoboErikfb290df2013-12-16 11:27:55 -08001115
1116 String key = getLayoutDescriptor(device.getIdentifier());
Jeff Browncf39bdf2012-05-18 14:41:19 -07001117 synchronized (mDataStore) {
1118 try {
RoboErikfb290df2013-12-16 11:27:55 -08001119 changed = mDataStore.switchKeyboardLayout(key, direction);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001120 keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
RoboErikfb290df2013-12-16 11:27:55 -08001121 key);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001122 } finally {
1123 mDataStore.saveIfNeeded();
1124 }
1125 }
1126
1127 if (changed) {
1128 if (mSwitchedKeyboardLayoutToast != null) {
1129 mSwitchedKeyboardLayoutToast.cancel();
1130 mSwitchedKeyboardLayoutToast = null;
1131 }
1132 if (keyboardLayoutDescriptor != null) {
1133 KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
1134 if (keyboardLayout != null) {
1135 mSwitchedKeyboardLayoutToast = Toast.makeText(
1136 mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
1137 mSwitchedKeyboardLayoutToast.show();
1138 }
1139 }
1140
1141 reloadKeyboardLayouts();
1142 }
Jeff Brown6ec6f792012-04-17 16:52:41 -07001143 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001144 }
1145
Jeff Brown9302c872011-07-13 22:51:29 -07001146 public void setInputWindows(InputWindowHandle[] windowHandles) {
Jeff Brown4532e612012-04-05 14:27:12 -07001147 nativeSetInputWindows(mPtr, windowHandles);
Jeff Brown349703e2010-06-22 01:27:15 -07001148 }
RoboErikfb290df2013-12-16 11:27:55 -08001149
Jeff Brown9302c872011-07-13 22:51:29 -07001150 public void setFocusedApplication(InputApplicationHandle application) {
Jeff Brown4532e612012-04-05 14:27:12 -07001151 nativeSetFocusedApplication(mPtr, application);
Jeff Brown349703e2010-06-22 01:27:15 -07001152 }
RoboErikfb290df2013-12-16 11:27:55 -08001153
Jeff Brown349703e2010-06-22 01:27:15 -07001154 public void setInputDispatchMode(boolean enabled, boolean frozen) {
Jeff Brown4532e612012-04-05 14:27:12 -07001155 nativeSetInputDispatchMode(mPtr, enabled, frozen);
Jeff Brown349703e2010-06-22 01:27:15 -07001156 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001157
1158 public void setSystemUiVisibility(int visibility) {
Jeff Brown4532e612012-04-05 14:27:12 -07001159 nativeSetSystemUiVisibility(mPtr, visibility);
Jeff Brown05dc66a2011-03-02 14:41:58 -08001160 }
1161
Jeff Browne6504122010-09-27 14:52:15 -07001162 /**
1163 * Atomically transfers touch focus from one window to another as identified by
1164 * their input channels. It is possible for multiple windows to have
1165 * touch focus if they support split touch dispatch
1166 * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
1167 * method only transfers touch focus of the specified window without affecting
1168 * other windows that may also have touch focus at the same time.
1169 * @param fromChannel The channel of a window that currently has touch focus.
1170 * @param toChannel The channel of the window that should receive touch focus in
1171 * place of the first.
1172 * @return True if the transfer was successful. False if the window with the
1173 * specified channel did not actually have touch focus at the time of the request.
1174 */
1175 public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
1176 if (fromChannel == null) {
1177 throw new IllegalArgumentException("fromChannel must not be null.");
1178 }
1179 if (toChannel == null) {
1180 throw new IllegalArgumentException("toChannel must not be null.");
1181 }
Jeff Brown4532e612012-04-05 14:27:12 -07001182 return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
Jeff Browne6504122010-09-27 14:52:15 -07001183 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001184
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001185 @Override // Binder call
Jeff Brownac143512012-04-05 18:57:33 -07001186 public void tryPointerSpeed(int speed) {
1187 if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
1188 "tryPointerSpeed()")) {
1189 throw new SecurityException("Requires SET_POINTER_SPEED permission");
1190 }
1191
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001192 if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) {
1193 throw new IllegalArgumentException("speed out of range");
1194 }
1195
Jeff Brownac143512012-04-05 18:57:33 -07001196 setPointerSpeedUnchecked(speed);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001197 }
1198
1199 public void updatePointerSpeedFromSettings() {
Jeff Brownac143512012-04-05 18:57:33 -07001200 int speed = getPointerSpeedSetting();
1201 setPointerSpeedUnchecked(speed);
1202 }
1203
1204 private void setPointerSpeedUnchecked(int speed) {
1205 speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
1206 InputManager.MAX_POINTER_SPEED);
1207 nativeSetPointerSpeed(mPtr, speed);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001208 }
1209
1210 private void registerPointerSpeedSettingObserver() {
1211 mContext.getContentResolver().registerContentObserver(
1212 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
Jeff Brown4532e612012-04-05 14:27:12 -07001213 new ContentObserver(mHandler) {
Jeff Brown1a84fd12011-06-02 01:26:32 -07001214 @Override
1215 public void onChange(boolean selfChange) {
1216 updatePointerSpeedFromSettings();
1217 }
Jeff Brownd4935962012-09-25 13:27:20 -07001218 }, UserHandle.USER_ALL);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001219 }
1220
Jeff Brownac143512012-04-05 18:57:33 -07001221 private int getPointerSpeedSetting() {
1222 int speed = InputManager.DEFAULT_POINTER_SPEED;
Jeff Brown1a84fd12011-06-02 01:26:32 -07001223 try {
Jeff Brownd4935962012-09-25 13:27:20 -07001224 speed = Settings.System.getIntForUser(mContext.getContentResolver(),
1225 Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001226 } catch (SettingNotFoundException snfe) {
1227 }
1228 return speed;
1229 }
1230
Jeff Browndaf4a122011-08-26 17:14:14 -07001231 public void updateShowTouchesFromSettings() {
1232 int setting = getShowTouchesSetting(0);
Jeff Brown4532e612012-04-05 14:27:12 -07001233 nativeSetShowTouches(mPtr, setting != 0);
Jeff Browndaf4a122011-08-26 17:14:14 -07001234 }
1235
1236 private void registerShowTouchesSettingObserver() {
1237 mContext.getContentResolver().registerContentObserver(
1238 Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
Jeff Brown4532e612012-04-05 14:27:12 -07001239 new ContentObserver(mHandler) {
Jeff Browndaf4a122011-08-26 17:14:14 -07001240 @Override
1241 public void onChange(boolean selfChange) {
1242 updateShowTouchesFromSettings();
1243 }
Jeff Brownd4935962012-09-25 13:27:20 -07001244 }, UserHandle.USER_ALL);
Jeff Browndaf4a122011-08-26 17:14:14 -07001245 }
1246
1247 private int getShowTouchesSetting(int defaultValue) {
1248 int result = defaultValue;
1249 try {
Jeff Brownd4935962012-09-25 13:27:20 -07001250 result = Settings.System.getIntForUser(mContext.getContentResolver(),
1251 Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
Jeff Browndaf4a122011-08-26 17:14:14 -07001252 } catch (SettingNotFoundException snfe) {
1253 }
1254 return result;
1255 }
1256
Jeff Browna47425a2012-04-13 04:09:27 -07001257 // Binder call
1258 @Override
1259 public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {
1260 if (repeat >= pattern.length) {
1261 throw new ArrayIndexOutOfBoundsException();
1262 }
1263
1264 VibratorToken v;
1265 synchronized (mVibratorLock) {
1266 v = mVibratorTokens.get(token);
1267 if (v == null) {
1268 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);
1269 try {
1270 token.linkToDeath(v, 0);
1271 } catch (RemoteException ex) {
1272 // give up
1273 throw new RuntimeException(ex);
1274 }
1275 mVibratorTokens.put(token, v);
1276 }
1277 }
1278
1279 synchronized (v) {
1280 v.mVibrating = true;
1281 nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue);
1282 }
1283 }
1284
1285 // Binder call
1286 @Override
1287 public void cancelVibrate(int deviceId, IBinder token) {
1288 VibratorToken v;
1289 synchronized (mVibratorLock) {
1290 v = mVibratorTokens.get(token);
1291 if (v == null || v.mDeviceId != deviceId) {
1292 return; // nothing to cancel
1293 }
1294 }
1295
1296 cancelVibrateIfNeeded(v);
1297 }
1298
1299 void onVibratorTokenDied(VibratorToken v) {
1300 synchronized (mVibratorLock) {
1301 mVibratorTokens.remove(v.mToken);
1302 }
1303
1304 cancelVibrateIfNeeded(v);
1305 }
1306
1307 private void cancelVibrateIfNeeded(VibratorToken v) {
1308 synchronized (v) {
1309 if (v.mVibrating) {
1310 nativeCancelVibrate(mPtr, v.mDeviceId, v.mTokenValue);
1311 v.mVibrating = false;
1312 }
1313 }
1314 }
1315
Jeff Brown4532e612012-04-05 14:27:12 -07001316 @Override
1317 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Browna3bc5652012-04-17 11:42:25 -07001318 if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
Jeff Brown4532e612012-04-05 14:27:12 -07001319 != PackageManager.PERMISSION_GRANTED) {
1320 pw.println("Permission Denial: can't dump InputManager from from pid="
1321 + Binder.getCallingPid()
1322 + ", uid=" + Binder.getCallingUid());
1323 return;
1324 }
1325
1326 pw.println("INPUT MANAGER (dumpsys input)\n");
1327 String dumpStr = nativeDump(mPtr);
Jeff Browne33348b2010-07-15 23:54:05 -07001328 if (dumpStr != null) {
1329 pw.println(dumpStr);
1330 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001331 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001332
Jeff Brownac143512012-04-05 18:57:33 -07001333 private boolean checkCallingPermission(String permission, String func) {
1334 // Quick check: if the calling permission is me, it's all okay.
1335 if (Binder.getCallingPid() == Process.myPid()) {
1336 return true;
1337 }
1338
1339 if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
1340 return true;
1341 }
1342 String msg = "Permission Denial: " + func + " from pid="
1343 + Binder.getCallingPid()
1344 + ", uid=" + Binder.getCallingUid()
1345 + " requires " + permission;
1346 Slog.w(TAG, msg);
1347 return false;
1348 }
1349
Jeff Brown4532e612012-04-05 14:27:12 -07001350 // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001351 @Override
Jeff Brown89ef0722011-08-10 16:25:21 -07001352 public void monitor() {
1353 synchronized (mInputFilterLock) { }
Jeff Brown4532e612012-04-05 14:27:12 -07001354 nativeMonitor(mPtr);
Jeff Brown89ef0722011-08-10 16:25:21 -07001355 }
1356
Jeff Brown4532e612012-04-05 14:27:12 -07001357 // Native callback.
1358 private void notifyConfigurationChanged(long whenNanos) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001359 mWindowManagerCallbacks.notifyConfigurationChanged();
Jeff Brown4532e612012-04-05 14:27:12 -07001360 }
1361
1362 // Native callback.
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001363 private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
1364 synchronized (mInputDevicesLock) {
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001365 if (!mInputDevicesChangedPending) {
1366 mInputDevicesChangedPending = true;
Jeff Browncf39bdf2012-05-18 14:41:19 -07001367 mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED,
1368 mInputDevices).sendToTarget();
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001369 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001370
1371 mInputDevices = inputDevices;
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001372 }
1373 }
1374
1375 // Native callback.
Jeff Brownbcc046a2012-09-27 20:46:43 -07001376 private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
1377 if (DEBUG) {
1378 Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
1379 + ", mask=" + Integer.toHexString(switchMask));
1380 }
1381
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001382 if ((switchMask & SW_LID_BIT) != 0) {
1383 final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
Jeff Brownbcc046a2012-09-27 20:46:43 -07001384 mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
Jeff Brown53384282012-08-20 20:16:01 -07001385 }
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001386
Michael Wright3818c922014-09-02 13:59:07 -07001387 if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
1388 final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) == 0);
1389 mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
1390 }
1391
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001392 if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
1393 mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
1394 switchMask);
1395 }
Jeff Brown4532e612012-04-05 14:27:12 -07001396 }
1397
1398 // Native callback.
1399 private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001400 mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
Jeff Brown4532e612012-04-05 14:27:12 -07001401 }
1402
1403 // Native callback.
1404 private long notifyANR(InputApplicationHandle inputApplicationHandle,
Jeff Brownbd181bb2013-09-10 16:44:24 -07001405 InputWindowHandle inputWindowHandle, String reason) {
1406 return mWindowManagerCallbacks.notifyANR(
1407 inputApplicationHandle, inputWindowHandle, reason);
Jeff Brown4532e612012-04-05 14:27:12 -07001408 }
1409
1410 // Native callback.
1411 final boolean filterInputEvent(InputEvent event, int policyFlags) {
1412 synchronized (mInputFilterLock) {
1413 if (mInputFilter != null) {
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001414 try {
1415 mInputFilter.filterInputEvent(event, policyFlags);
1416 } catch (RemoteException e) {
1417 /* ignore */
1418 }
Jeff Brown4532e612012-04-05 14:27:12 -07001419 return false;
1420 }
1421 }
1422 event.recycle();
1423 return true;
1424 }
1425
1426 // Native callback.
Jeff Brown037c33e2014-04-09 00:31:55 -07001427 private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1428 return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001429 }
1430
1431 // Native callback.
Jeff Brown037c33e2014-04-09 00:31:55 -07001432 private int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
1433 return mWindowManagerCallbacks.interceptWakeMotionBeforeQueueing(
Jeff Brown26875502014-01-30 21:47:47 -08001434 whenNanos, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001435 }
1436
1437 // Native callback.
1438 private long interceptKeyBeforeDispatching(InputWindowHandle focus,
1439 KeyEvent event, int policyFlags) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001440 return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001441 }
1442
1443 // Native callback.
1444 private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1445 KeyEvent event, int policyFlags) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001446 return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001447 }
1448
1449 // Native callback.
1450 private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
1451 return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
1452 injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
1453 }
1454
1455 // Native callback.
1456 private int getVirtualKeyQuietTimeMillis() {
1457 return mContext.getResources().getInteger(
1458 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
1459 }
1460
1461 // Native callback.
1462 private String[] getExcludedDeviceNames() {
1463 ArrayList<String> names = new ArrayList<String>();
1464
1465 // Read partner-provided list of excluded input devices
1466 XmlPullParser parser = null;
1467 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
1468 File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
1469 FileReader confreader = null;
1470 try {
1471 confreader = new FileReader(confFile);
1472 parser = Xml.newPullParser();
1473 parser.setInput(confreader);
1474 XmlUtils.beginDocument(parser, "devices");
1475
1476 while (true) {
1477 XmlUtils.nextElement(parser);
1478 if (!"device".equals(parser.getName())) {
1479 break;
1480 }
1481 String name = parser.getAttributeValue(null, "name");
1482 if (name != null) {
1483 names.add(name);
1484 }
1485 }
1486 } catch (FileNotFoundException e) {
1487 // It's ok if the file does not exist.
1488 } catch (Exception e) {
1489 Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
1490 } finally {
1491 try { if (confreader != null) confreader.close(); } catch (IOException e) { }
1492 }
1493
1494 return names.toArray(new String[names.size()]);
1495 }
1496
1497 // Native callback.
1498 private int getKeyRepeatTimeout() {
1499 return ViewConfiguration.getKeyRepeatTimeout();
1500 }
1501
1502 // Native callback.
1503 private int getKeyRepeatDelay() {
1504 return ViewConfiguration.getKeyRepeatDelay();
1505 }
1506
1507 // Native callback.
1508 private int getHoverTapTimeout() {
1509 return ViewConfiguration.getHoverTapTimeout();
1510 }
1511
1512 // Native callback.
1513 private int getHoverTapSlop() {
1514 return ViewConfiguration.getHoverTapSlop();
1515 }
1516
1517 // Native callback.
1518 private int getDoubleTapTimeout() {
1519 return ViewConfiguration.getDoubleTapTimeout();
1520 }
1521
1522 // Native callback.
1523 private int getLongPressTimeout() {
1524 return ViewConfiguration.getLongPressTimeout();
1525 }
1526
1527 // Native callback.
1528 private int getPointerLayer() {
Jeff Browna9d131c2012-09-20 16:48:17 -07001529 return mWindowManagerCallbacks.getPointerLayer();
Jeff Brown4532e612012-04-05 14:27:12 -07001530 }
1531
1532 // Native callback.
1533 private PointerIcon getPointerIcon() {
1534 return PointerIcon.getDefaultIcon(mContext);
1535 }
1536
Jeff Brown6ec6f792012-04-17 16:52:41 -07001537 // Native callback.
RoboErikfb290df2013-12-16 11:27:55 -08001538 private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
Jeff Brown6ec6f792012-04-17 16:52:41 -07001539 if (!mSystemReady) {
1540 return null;
1541 }
1542
RoboErikfb290df2013-12-16 11:27:55 -08001543 String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
Jeff Brown6ec6f792012-04-17 16:52:41 -07001544 if (keyboardLayoutDescriptor == null) {
1545 return null;
1546 }
1547
1548 final String[] result = new String[2];
1549 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
1550 @Override
1551 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -07001552 String descriptor, String label, String collection, int keyboardLayoutResId) {
Jeff Brown6ec6f792012-04-17 16:52:41 -07001553 try {
1554 result[0] = descriptor;
1555 result[1] = Streams.readFully(new InputStreamReader(
Jeff Brown2f095762012-05-10 21:29:33 -07001556 resources.openRawResource(keyboardLayoutResId)));
Jeff Brown6ec6f792012-04-17 16:52:41 -07001557 } catch (IOException ex) {
1558 } catch (NotFoundException ex) {
1559 }
1560 }
1561 });
1562 if (result[0] == null) {
1563 Log.w(TAG, "Could not get keyboard layout with descriptor '"
1564 + keyboardLayoutDescriptor + "'.");
1565 return null;
1566 }
1567 return result;
1568 }
1569
Jeff Brown5bbd4b42012-04-20 19:28:00 -07001570 // Native callback.
1571 private String getDeviceAlias(String uniqueId) {
Matthew Xie96313142012-06-29 16:57:31 -07001572 if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
1573 // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
1574 return null;
Jeff Brown5bbd4b42012-04-20 19:28:00 -07001575 }
1576 return null;
1577 }
1578
Jeff Brown4532e612012-04-05 14:27:12 -07001579 /**
1580 * Callback interface implemented by the Window Manager.
1581 */
Jeff Browna9d131c2012-09-20 16:48:17 -07001582 public interface WindowManagerCallbacks {
Jeff Brown4532e612012-04-05 14:27:12 -07001583 public void notifyConfigurationChanged();
1584
1585 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
1586
Michael Wright3818c922014-09-02 13:59:07 -07001587 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
1588
Jeff Brown4532e612012-04-05 14:27:12 -07001589 public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
1590
1591 public long notifyANR(InputApplicationHandle inputApplicationHandle,
Jeff Brownbd181bb2013-09-10 16:44:24 -07001592 InputWindowHandle inputWindowHandle, String reason);
Jeff Brown4532e612012-04-05 14:27:12 -07001593
Jeff Brown037c33e2014-04-09 00:31:55 -07001594 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001595
Jeff Brown037c33e2014-04-09 00:31:55 -07001596 public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001597
1598 public long interceptKeyBeforeDispatching(InputWindowHandle focus,
1599 KeyEvent event, int policyFlags);
1600
1601 public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1602 KeyEvent event, int policyFlags);
1603
1604 public int getPointerLayer();
1605 }
1606
1607 /**
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001608 * Callback interface implemented by WiredAccessoryObserver.
1609 */
1610 public interface WiredAccessoryCallbacks {
1611 public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
Eric Laurent4a5eeb92014-05-06 10:49:04 -07001612 public void systemReady();
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001613 }
1614
1615 /**
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001616 * Private handler for the input manager.
1617 */
1618 private final class InputManagerHandler extends Handler {
Jeff Browna9d131c2012-09-20 16:48:17 -07001619 public InputManagerHandler(Looper looper) {
1620 super(looper, null, true /*async*/);
Jeff Browna2910d02012-08-25 12:29:46 -07001621 }
1622
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001623 @Override
1624 public void handleMessage(Message msg) {
1625 switch (msg.what) {
1626 case MSG_DELIVER_INPUT_DEVICES_CHANGED:
Jeff Browncf39bdf2012-05-18 14:41:19 -07001627 deliverInputDevicesChanged((InputDevice[])msg.obj);
1628 break;
1629 case MSG_SWITCH_KEYBOARD_LAYOUT:
1630 handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
1631 break;
1632 case MSG_RELOAD_KEYBOARD_LAYOUTS:
1633 reloadKeyboardLayouts();
1634 break;
1635 case MSG_UPDATE_KEYBOARD_LAYOUTS:
1636 updateKeyboardLayouts();
1637 break;
1638 case MSG_RELOAD_DEVICE_ALIASES:
1639 reloadDeviceAliases();
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001640 break;
1641 }
1642 }
1643 }
1644
1645 /**
Jeff Brown4532e612012-04-05 14:27:12 -07001646 * Hosting interface for input filters to call back into the input manager.
1647 */
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001648 private final class InputFilterHost extends IInputFilterHost.Stub {
Jeff Brown0029c662011-03-30 02:25:18 -07001649 private boolean mDisconnected;
1650
1651 public void disconnectLocked() {
1652 mDisconnected = true;
1653 }
1654
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001655 @Override
Jeff Brown0029c662011-03-30 02:25:18 -07001656 public void sendInputEvent(InputEvent event, int policyFlags) {
1657 if (event == null) {
1658 throw new IllegalArgumentException("event must not be null");
1659 }
1660
1661 synchronized (mInputFilterLock) {
1662 if (!mDisconnected) {
Jeff Brownca9bc702014-02-11 14:32:56 -08001663 nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
Jeff Brownac143512012-04-05 18:57:33 -07001664 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
Jeff Brown0029c662011-03-30 02:25:18 -07001665 policyFlags | WindowManagerPolicy.FLAG_FILTERED);
1666 }
1667 }
1668 }
1669 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001670
1671 private static final class KeyboardLayoutDescriptor {
1672 public String packageName;
1673 public String receiverName;
1674 public String keyboardLayoutName;
1675
1676 public static String format(String packageName,
1677 String receiverName, String keyboardName) {
1678 return packageName + "/" + receiverName + "/" + keyboardName;
1679 }
1680
1681 public static KeyboardLayoutDescriptor parse(String descriptor) {
1682 int pos = descriptor.indexOf('/');
1683 if (pos < 0 || pos + 1 == descriptor.length()) {
1684 return null;
1685 }
1686 int pos2 = descriptor.indexOf('/', pos + 1);
1687 if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
1688 return null;
1689 }
1690
1691 KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
1692 result.packageName = descriptor.substring(0, pos);
1693 result.receiverName = descriptor.substring(pos + 1, pos2);
1694 result.keyboardLayoutName = descriptor.substring(pos2 + 1);
1695 return result;
1696 }
1697 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001698
Jeff Brown6ec6f792012-04-17 16:52:41 -07001699 private interface KeyboardLayoutVisitor {
1700 void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -07001701 String descriptor, String label, String collection, int keyboardLayoutResId);
Jeff Brown6ec6f792012-04-17 16:52:41 -07001702 }
1703
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001704 private final class InputDevicesChangedListenerRecord implements DeathRecipient {
1705 private final int mPid;
1706 private final IInputDevicesChangedListener mListener;
1707
1708 public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
1709 mPid = pid;
1710 mListener = listener;
1711 }
1712
1713 @Override
1714 public void binderDied() {
1715 if (DEBUG) {
1716 Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
1717 }
1718 onInputDevicesChangedListenerDied(mPid);
1719 }
1720
1721 public void notifyInputDevicesChanged(int[] info) {
1722 try {
1723 mListener.onInputDevicesChanged(info);
1724 } catch (RemoteException ex) {
1725 Slog.w(TAG, "Failed to notify process "
1726 + mPid + " that input devices changed, assuming it died.", ex);
1727 binderDied();
1728 }
1729 }
1730 }
Jeff Browna47425a2012-04-13 04:09:27 -07001731
1732 private final class VibratorToken implements DeathRecipient {
1733 public final int mDeviceId;
1734 public final IBinder mToken;
1735 public final int mTokenValue;
1736
1737 public boolean mVibrating;
1738
1739 public VibratorToken(int deviceId, IBinder token, int tokenValue) {
1740 mDeviceId = deviceId;
1741 mToken = token;
1742 mTokenValue = tokenValue;
1743 }
1744
1745 @Override
1746 public void binderDied() {
1747 if (DEBUG) {
1748 Slog.d(TAG, "Vibrator token died.");
1749 }
1750 onVibratorTokenDied(this);
1751 }
1752 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001753
1754 private final class LocalService extends InputManagerInternal {
1755 @Override
1756 public void setDisplayViewports(
1757 DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
1758 setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
1759 }
Jeff Brownca9bc702014-02-11 14:32:56 -08001760
1761 @Override
1762 public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
1763 return injectInputEventInternal(event, displayId, mode);
1764 }
Jeff Brown037c33e2014-04-09 00:31:55 -07001765
1766 @Override
1767 public void setInteractive(boolean interactive) {
1768 nativeSetInteractive(mPtr, interactive);
1769 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001770 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001771}