blob: 15dcd44c3b0b87cab457b66bd94b3268242acee9 [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;
Michael Wright8ebac232014-09-18 18:29:49 -070040import android.content.pm.ApplicationInfo;
Jeff Brown349703e2010-06-22 01:27:15 -070041import android.content.pm.PackageManager;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070042import android.content.pm.ResolveInfo;
43import android.content.pm.PackageManager.NameNotFoundException;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070044import android.content.res.Resources;
Jeff Brown6ec6f792012-04-17 16:52:41 -070045import android.content.res.Resources.NotFoundException;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070046import android.content.res.TypedArray;
47import android.content.res.XmlResourceParser;
Jeff Brown1a84fd12011-06-02 01:26:32 -070048import android.database.ContentObserver;
Jeff Brown4ccb8232014-01-16 22:16:42 -080049import android.hardware.display.DisplayViewport;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070050import android.hardware.input.IInputDevicesChangedListener;
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -070051import android.hardware.input.IInputManager;
RoboErikfb290df2013-12-16 11:27:55 -080052import android.hardware.input.InputDeviceIdentifier;
Jeff Brownac143512012-04-05 18:57:33 -070053import android.hardware.input.InputManager;
Jeff Brown4ccb8232014-01-16 22:16:42 -080054import android.hardware.input.InputManagerInternal;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070055import android.hardware.input.KeyboardLayout;
Jason Gerecked6396d62014-01-27 18:30:37 -080056import android.hardware.input.TouchCalibration;
Jeff Brown4532e612012-04-05 14:27:12 -070057import android.os.Binder;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070058import android.os.Bundle;
Jeff Brown46b9ac02010-04-22 18:58:52 -070059import android.os.Environment;
Jeff Brown4532e612012-04-05 14:27:12 -070060import android.os.Handler;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070061import android.os.IBinder;
Jeff Browna9d131c2012-09-20 16:48:17 -070062import android.os.Looper;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070063import android.os.Message;
Jeff Brown05dc66a2011-03-02 14:41:58 -080064import android.os.MessageQueue;
Jeff Brownac143512012-04-05 18:57:33 -070065import android.os.Process;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070066import android.os.RemoteException;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -070067import android.os.UserHandle;
Jeff Brown1a84fd12011-06-02 01:26:32 -070068import android.provider.Settings;
69import android.provider.Settings.SettingNotFoundException;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070070import android.util.Log;
Jeff Brown46b9ac02010-04-22 18:58:52 -070071import android.util.Slog;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070072import android.util.SparseArray;
Jeff Brown46b9ac02010-04-22 18:58:52 -070073import android.util.Xml;
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -070074import android.view.IInputFilter;
75import android.view.IInputFilterHost;
Jeff Brown46b9ac02010-04-22 18:58:52 -070076import android.view.InputChannel;
Jeff Brown8d608662010-08-30 03:02:23 -070077import android.view.InputDevice;
Jeff Brown6ec402b2010-07-28 15:48:59 -070078import android.view.InputEvent;
Jeff Brown1f245102010-11-18 20:53:46 -080079import android.view.KeyEvent;
Jeff Brown2352b972011-04-12 22:39:53 -070080import android.view.PointerIcon;
Jason Gerecked5220742014-03-10 09:47:59 -070081import android.view.Surface;
Jeff Browna4547672011-03-02 21:38:11 -080082import android.view.ViewConfiguration;
Jeff Brown0029c662011-03-30 02:25:18 -070083import android.view.WindowManagerPolicy;
Jeff Browncf39bdf2012-05-18 14:41:19 -070084import android.widget.Toast;
Jeff Brown46b9ac02010-04-22 18:58:52 -070085
Jeff Brown46b9ac02010-04-22 18:58:52 -070086import java.io.File;
Jeff Brown4532e612012-04-05 14:27:12 -070087import java.io.FileDescriptor;
Jeff Brown46b9ac02010-04-22 18:58:52 -070088import java.io.FileNotFoundException;
89import java.io.FileReader;
90import java.io.IOException;
Jeff Brown6ec6f792012-04-17 16:52:41 -070091import java.io.InputStreamReader;
Jeff Brown46b9ac02010-04-22 18:58:52 -070092import java.io.PrintWriter;
93import java.util.ArrayList;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070094import java.util.HashMap;
Jeff Browncf39bdf2012-05-18 14:41:19 -070095import java.util.HashSet;
Jeff Browna3bc5652012-04-17 11:42:25 -070096
Jeff Brown6ec6f792012-04-17 16:52:41 -070097import libcore.io.Streams;
Jeff Browna3bc5652012-04-17 11:42:25 -070098import libcore.util.Objects;
Jeff Brown46b9ac02010-04-22 18:58:52 -070099
100/*
101 * Wraps the C++ InputManager and provides its callbacks.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700102 */
Jeff Brownd728bf52012-09-08 18:05:28 -0700103public class InputManagerService extends IInputManager.Stub
Jeff Brown4ccb8232014-01-16 22:16:42 -0800104 implements Watchdog.Monitor {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700105 static final String TAG = "InputManager";
Jeff Brown1b9ba572012-05-21 10:54:18 -0700106 static final boolean DEBUG = false;
Jeff Brownb6997262010-10-08 22:31:17 -0700107
Jeff Brown4532e612012-04-05 14:27:12 -0700108 private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
109
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700110 private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
Jeff Browncf39bdf2012-05-18 14:41:19 -0700111 private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
112 private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
113 private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
114 private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700115
Jeff Brown4532e612012-04-05 14:27:12 -0700116 // Pointer to native input manager service object.
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000117 private final long mPtr;
Jeff Brown4532e612012-04-05 14:27:12 -0700118
Jeff Brown46b9ac02010-04-22 18:58:52 -0700119 private final Context mContext;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700120 private final InputManagerHandler mHandler;
Jeff Browna9d131c2012-09-20 16:48:17 -0700121
122 private WindowManagerCallbacks mWindowManagerCallbacks;
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700123 private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
Jeff Brown6ec6f792012-04-17 16:52:41 -0700124 private boolean mSystemReady;
Jeff Browncf39bdf2012-05-18 14:41:19 -0700125 private NotificationManager mNotificationManager;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700126
Jeff Browna3bc5652012-04-17 11:42:25 -0700127 // Persistent data store. Must be locked each time during use.
128 private final PersistentDataStore mDataStore = new PersistentDataStore();
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700129
130 // List of currently registered input devices changed listeners by process id.
131 private Object mInputDevicesLock = new Object();
132 private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock
133 private InputDevice[] mInputDevices = new InputDevice[0];
134 private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
135 new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock
136 private final ArrayList<InputDevicesChangedListenerRecord>
137 mTempInputDevicesChangedListenersToNotify =
138 new ArrayList<InputDevicesChangedListenerRecord>(); // handler thread only
Jeff Browncf39bdf2012-05-18 14:41:19 -0700139 private final ArrayList<InputDevice>
140 mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only
141 private boolean mKeyboardLayoutNotificationShown;
142 private PendingIntent mKeyboardLayoutIntent;
143 private Toast mSwitchedKeyboardLayoutToast;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700144
Jeff Browna47425a2012-04-13 04:09:27 -0700145 // State for vibrator tokens.
146 private Object mVibratorLock = new Object();
147 private HashMap<IBinder, VibratorToken> mVibratorTokens =
148 new HashMap<IBinder, VibratorToken>();
149 private int mNextVibratorTokenValue;
150
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700151 // State for the currently installed input filter.
152 final Object mInputFilterLock = new Object();
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700153 IInputFilter mInputFilter; // guarded by mInputFilterLock
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700154 InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
Jeff Brown1a84fd12011-06-02 01:26:32 -0700155
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000156 private static native long nativeInit(InputManagerService service,
Jeff Brown4532e612012-04-05 14:27:12 -0700157 Context context, MessageQueue messageQueue);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000158 private static native void nativeStart(long ptr);
159 private static native void nativeSetDisplayViewport(long ptr, boolean external,
Jeff Brownd728bf52012-09-08 18:05:28 -0700160 int displayId, int rotation,
161 int logicalLeft, int logicalTop, int logicalRight, int logicalBottom,
Jeff Brown83d616a2012-09-09 20:33:43 -0700162 int physicalLeft, int physicalTop, int physicalRight, int physicalBottom,
163 int deviceWidth, int deviceHeight);
Jeff Brownd728bf52012-09-08 18:05:28 -0700164
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000165 private static native int nativeGetScanCodeState(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700166 int deviceId, int sourceMask, int scanCode);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000167 private static native int nativeGetKeyCodeState(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700168 int deviceId, int sourceMask, int keyCode);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000169 private static native int nativeGetSwitchState(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700170 int deviceId, int sourceMask, int sw);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000171 private static native boolean nativeHasKeys(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700172 int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000173 private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
Jeff Brown928e0542011-01-10 11:17:36 -0800174 InputWindowHandle inputWindowHandle, boolean monitor);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000175 private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
176 private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
Jeff Brownca9bc702014-02-11 14:32:56 -0800177 private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
Jeff Brown0029c662011-03-30 02:25:18 -0700178 int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
179 int policyFlags);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000180 private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
181 private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
182 private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
183 private static native void nativeSetFocusedApplication(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700184 InputApplicationHandle application);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000185 private static native boolean nativeTransferTouchFocus(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700186 InputChannel fromChannel, InputChannel toChannel);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000187 private static native void nativeSetPointerSpeed(long ptr, int speed);
188 private static native void nativeSetShowTouches(long ptr, boolean enabled);
Jeff Brown037c33e2014-04-09 00:31:55 -0700189 private static native void nativeSetInteractive(long ptr, boolean interactive);
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800190 private static native void nativeReloadCalibration(long ptr);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000191 private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
Jeff Browna47425a2012-04-13 04:09:27 -0700192 int repeat, int token);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000193 private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
194 private static native void nativeReloadKeyboardLayouts(long ptr);
195 private static native void nativeReloadDeviceAliases(long ptr);
196 private static native String nativeDump(long ptr);
197 private static native void nativeMonitor(long ptr);
Jeff Brown4532e612012-04-05 14:27:12 -0700198
Jeff Brownac143512012-04-05 18:57:33 -0700199 // Input event injection constants defined in InputDispatcher.h.
200 private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
201 private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
202 private static final int INPUT_EVENT_INJECTION_FAILED = 2;
203 private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
204
205 // Maximum number of milliseconds to wait for input event injection.
206 private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
207
Jeff Brown6d0fec22010-07-23 21:28:06 -0700208 // Key states (may be returned by queries about the current state of a
209 // particular key code, scan code or switch).
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700210
Jeff Brown6d0fec22010-07-23 21:28:06 -0700211 /** The key state is unknown or the requested key itself is not supported. */
212 public static final int KEY_STATE_UNKNOWN = -1;
213
214 /** The key is up. /*/
215 public static final int KEY_STATE_UP = 0;
216
217 /** The key is down. */
218 public static final int KEY_STATE_DOWN = 1;
219
220 /** The key is down but is a virtual key press that is being emulated by the system. */
221 public static final int KEY_STATE_VIRTUAL = 2;
222
Jeff Brownc458ce92012-04-30 14:58:40 -0700223 /** Scan code: Mouse / trackball button. */
224 public static final int BTN_MOUSE = 0x110;
225
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700226 // Switch code values must match bionic/libc/kernel/common/linux/input.h
Jeff Brownc458ce92012-04-30 14:58:40 -0700227 /** Switch code: Lid switch. When set, lid is shut. */
228 public static final int SW_LID = 0x00;
229
230 /** Switch code: Keypad slide. When set, keyboard is exposed. */
231 public static final int SW_KEYPAD_SLIDE = 0x0a;
232
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700233 /** Switch code: Headphone. When set, headphone is inserted. */
234 public static final int SW_HEADPHONE_INSERT = 0x02;
235
236 /** Switch code: Microphone. When set, microphone is inserted. */
237 public static final int SW_MICROPHONE_INSERT = 0x04;
238
Jon Eklund43cc8bb2014-07-28 16:07:24 -0500239 /** Switch code: Line out. When set, Line out (hi-Z) is inserted. */
240 public static final int SW_LINEOUT_INSERT = 0x06;
241
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700242 /** Switch code: Headphone/Microphone Jack. When set, something is inserted. */
243 public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
244
Michael Wright3818c922014-09-02 13:59:07 -0700245 /** Switch code: Camera lens cover. When set the lens is covered. */
246 public static final int SW_CAMERA_LENS_COVER = 0x09;
247
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700248 public static final int SW_LID_BIT = 1 << SW_LID;
249 public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
250 public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
251 public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
Jon Eklund43cc8bb2014-07-28 16:07:24 -0500252 public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT;
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700253 public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
254 public static final int SW_JACK_BITS =
Jon Eklund43cc8bb2014-07-28 16:07:24 -0500255 SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
Michael Wright3818c922014-09-02 13:59:07 -0700256 public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700257
258 /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
259 final boolean mUseDevInputEventForAudioJack;
260
Jeff Brown4ccb8232014-01-16 22:16:42 -0800261 public InputManagerService(Context context) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700262 this.mContext = context;
Jeff Brown4ccb8232014-01-16 22:16:42 -0800263 this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
Jeff Brown05dc66a2011-03-02 14:41:58 -0800264
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700265 mUseDevInputEventForAudioJack =
266 context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
267 Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
268 + mUseDevInputEventForAudioJack);
Jeff Brown4532e612012-04-05 14:27:12 -0700269 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
Jeff Brown4ccb8232014-01-16 22:16:42 -0800270
271 LocalServices.addService(InputManagerInternal.class, new LocalService());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700272 }
Jeff Brown1a84fd12011-06-02 01:26:32 -0700273
Jeff Browna9d131c2012-09-20 16:48:17 -0700274 public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
275 mWindowManagerCallbacks = callbacks;
276 }
277
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700278 public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) {
279 mWiredAccessoryCallbacks = callbacks;
280 }
281
Jeff Brown46b9ac02010-04-22 18:58:52 -0700282 public void start() {
283 Slog.i(TAG, "Starting input manager");
Jeff Brown4532e612012-04-05 14:27:12 -0700284 nativeStart(mPtr);
285
286 // Add ourself to the Watchdog monitors.
287 Watchdog.getInstance().addMonitor(this);
Jeff Brown1a84fd12011-06-02 01:26:32 -0700288
289 registerPointerSpeedSettingObserver();
Jeff Browndaf4a122011-08-26 17:14:14 -0700290 registerShowTouchesSettingObserver();
291
Jeff Brownd4935962012-09-25 13:27:20 -0700292 mContext.registerReceiver(new BroadcastReceiver() {
293 @Override
294 public void onReceive(Context context, Intent intent) {
295 updatePointerSpeedFromSettings();
296 updateShowTouchesFromSettings();
297 }
298 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
299
Jeff Brown1a84fd12011-06-02 01:26:32 -0700300 updatePointerSpeedFromSettings();
Jeff Browndaf4a122011-08-26 17:14:14 -0700301 updateShowTouchesFromSettings();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700302 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700303
Matthew Xie96313142012-06-29 16:57:31 -0700304 // TODO(BT) Pass in paramter for bluetooth system
Svetoslav Ganova0027152013-06-25 14:59:53 -0700305 public void systemRunning() {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700306 if (DEBUG) {
307 Slog.d(TAG, "System ready.");
308 }
Jeff Browncf39bdf2012-05-18 14:41:19 -0700309 mNotificationManager = (NotificationManager)mContext.getSystemService(
310 Context.NOTIFICATION_SERVICE);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700311 mSystemReady = true;
Jeff Brown6ec6f792012-04-17 16:52:41 -0700312
313 IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
314 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
315 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
Jeff Brown69b07162013-11-07 00:30:16 -0800316 filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700317 filter.addDataScheme("package");
318 mContext.registerReceiver(new BroadcastReceiver() {
319 @Override
320 public void onReceive(Context context, Intent intent) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700321 updateKeyboardLayouts();
Jeff Brown6ec6f792012-04-17 16:52:41 -0700322 }
323 }, filter, null, mHandler);
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700324
325 filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
326 mContext.registerReceiver(new BroadcastReceiver() {
327 @Override
328 public void onReceive(Context context, Intent intent) {
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700329 reloadDeviceAliases();
330 }
331 }, filter, null, mHandler);
332
Jeff Browncf39bdf2012-05-18 14:41:19 -0700333 mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
334 mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700335
336 if (mWiredAccessoryCallbacks != null) {
337 mWiredAccessoryCallbacks.systemReady();
338 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700339 }
340
341 private void reloadKeyboardLayouts() {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700342 if (DEBUG) {
343 Slog.d(TAG, "Reloading keyboard layouts.");
344 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700345 nativeReloadKeyboardLayouts(mPtr);
346 }
347
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700348 private void reloadDeviceAliases() {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700349 if (DEBUG) {
350 Slog.d(TAG, "Reloading device names.");
351 }
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700352 nativeReloadDeviceAliases(mPtr);
353 }
354
Jeff Brown4ccb8232014-01-16 22:16:42 -0800355 private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
Jeff Brownd728bf52012-09-08 18:05:28 -0700356 DisplayViewport externalTouchViewport) {
357 if (defaultViewport.valid) {
358 setDisplayViewport(false, defaultViewport);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700359 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700360
361 if (externalTouchViewport.valid) {
362 setDisplayViewport(true, externalTouchViewport);
363 } else if (defaultViewport.valid) {
364 setDisplayViewport(true, defaultViewport);
Jeff Brownb6997262010-10-08 22:31:17 -0700365 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700366 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700367
Jeff Brownd728bf52012-09-08 18:05:28 -0700368 private void setDisplayViewport(boolean external, DisplayViewport viewport) {
369 nativeSetDisplayViewport(mPtr, external,
370 viewport.displayId, viewport.orientation,
371 viewport.logicalFrame.left, viewport.logicalFrame.top,
372 viewport.logicalFrame.right, viewport.logicalFrame.bottom,
373 viewport.physicalFrame.left, viewport.physicalFrame.top,
Jeff Brown83d616a2012-09-09 20:33:43 -0700374 viewport.physicalFrame.right, viewport.physicalFrame.bottom,
375 viewport.deviceWidth, viewport.deviceHeight);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700376 }
Jeff Brownac143512012-04-05 18:57:33 -0700377
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 /**
379 * Gets the current state of a key or button by key code.
380 * @param deviceId The input device id, or -1 to consult all devices.
381 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
382 * consider all input sources. An input device is consulted if at least one of its
383 * non-class input source bits matches the specified source mask.
384 * @param keyCode The key code to check.
385 * @return The key state.
386 */
387 public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700388 return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700389 }
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700390
Jeff Brown6d0fec22010-07-23 21:28:06 -0700391 /**
392 * Gets the current state of a key or button by scan code.
393 * @param deviceId The input device id, or -1 to consult all devices.
394 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
395 * consider all input sources. An input device is consulted if at least one of its
396 * non-class input source bits matches the specified source mask.
397 * @param scanCode The scan code to check.
398 * @return The key state.
399 */
400 public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700401 return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700402 }
RoboErikfb290df2013-12-16 11:27:55 -0800403
Jeff Brown6d0fec22010-07-23 21:28:06 -0700404 /**
405 * Gets the current state of a switch by switch code.
406 * @param deviceId The input device id, or -1 to consult all devices.
407 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
408 * consider all input sources. An input device is consulted if at least one of its
409 * non-class input source bits matches the specified source mask.
410 * @param switchCode The switch code to check.
411 * @return The switch state.
412 */
413 public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700414 return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700415 }
416
Jeff Brown6d0fec22010-07-23 21:28:06 -0700417 /**
418 * Determines whether the specified key codes are supported by a particular device.
419 * @param deviceId The input device id, or -1 to consult all devices.
420 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
421 * consider all input sources. An input device is consulted if at least one of its
422 * non-class input source bits matches the specified source mask.
423 * @param keyCodes The array of key codes to check.
424 * @param keyExists An array at least as large as keyCodes whose entries will be set
425 * to true or false based on the presence or absence of support for the corresponding
426 * key codes.
427 * @return True if the lookup was successful, false otherwise.
428 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700429 @Override // Binder call
Jeff Brown6d0fec22010-07-23 21:28:06 -0700430 public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700431 if (keyCodes == null) {
432 throw new IllegalArgumentException("keyCodes must not be null.");
433 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700434 if (keyExists == null || keyExists.length < keyCodes.length) {
435 throw new IllegalArgumentException("keyExists must not be null and must be at "
436 + "least as large as keyCodes.");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700437 }
RoboErikfb290df2013-12-16 11:27:55 -0800438
Jeff Brown4532e612012-04-05 14:27:12 -0700439 return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700440 }
RoboErikfb290df2013-12-16 11:27:55 -0800441
Jeff Browna41ca772010-08-11 14:46:32 -0700442 /**
443 * Creates an input channel that will receive all input from the input dispatcher.
444 * @param inputChannelName The input channel name.
445 * @return The input channel.
446 */
447 public InputChannel monitorInput(String inputChannelName) {
448 if (inputChannelName == null) {
449 throw new IllegalArgumentException("inputChannelName must not be null.");
450 }
RoboErikfb290df2013-12-16 11:27:55 -0800451
Jeff Browna41ca772010-08-11 14:46:32 -0700452 InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
Jeff Brown4532e612012-04-05 14:27:12 -0700453 nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
Jeff Browna41ca772010-08-11 14:46:32 -0700454 inputChannels[0].dispose(); // don't need to retain the Java object reference
455 return inputChannels[1];
456 }
457
458 /**
459 * Registers an input channel so that it can be used as an input event target.
460 * @param inputChannel The input channel to register.
Jeff Brown928e0542011-01-10 11:17:36 -0800461 * @param inputWindowHandle The handle of the input window associated with the
462 * input channel, or null if none.
Jeff Browna41ca772010-08-11 14:46:32 -0700463 */
Jeff Brown928e0542011-01-10 11:17:36 -0800464 public void registerInputChannel(InputChannel inputChannel,
465 InputWindowHandle inputWindowHandle) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700466 if (inputChannel == null) {
467 throw new IllegalArgumentException("inputChannel must not be null.");
468 }
RoboErikfb290df2013-12-16 11:27:55 -0800469
Jeff Brown4532e612012-04-05 14:27:12 -0700470 nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700471 }
RoboErikfb290df2013-12-16 11:27:55 -0800472
Jeff Browna41ca772010-08-11 14:46:32 -0700473 /**
474 * Unregisters an input channel.
475 * @param inputChannel The input channel to unregister.
476 */
Jeff Brown46b9ac02010-04-22 18:58:52 -0700477 public void unregisterInputChannel(InputChannel inputChannel) {
478 if (inputChannel == null) {
479 throw new IllegalArgumentException("inputChannel must not be null.");
480 }
RoboErikfb290df2013-12-16 11:27:55 -0800481
Jeff Brown4532e612012-04-05 14:27:12 -0700482 nativeUnregisterInputChannel(mPtr, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700483 }
Jeff Brown0029c662011-03-30 02:25:18 -0700484
485 /**
486 * Sets an input filter that will receive all input events before they are dispatched.
487 * The input filter may then reinterpret input events or inject new ones.
488 *
489 * To ensure consistency, the input dispatcher automatically drops all events
490 * in progress whenever an input filter is installed or uninstalled. After an input
491 * filter is uninstalled, it can no longer send input events unless it is reinstalled.
492 * Any events it attempts to send after it has been uninstalled will be dropped.
493 *
494 * @param filter The input filter, or null to remove the current filter.
495 */
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700496 public void setInputFilter(IInputFilter filter) {
Jeff Brown0029c662011-03-30 02:25:18 -0700497 synchronized (mInputFilterLock) {
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700498 final IInputFilter oldFilter = mInputFilter;
Jeff Brown0029c662011-03-30 02:25:18 -0700499 if (oldFilter == filter) {
500 return; // nothing to do
501 }
502
503 if (oldFilter != null) {
504 mInputFilter = null;
505 mInputFilterHost.disconnectLocked();
506 mInputFilterHost = null;
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700507 try {
508 oldFilter.uninstall();
509 } catch (RemoteException re) {
510 /* ignore */
511 }
Jeff Brown0029c662011-03-30 02:25:18 -0700512 }
513
514 if (filter != null) {
515 mInputFilter = filter;
516 mInputFilterHost = new InputFilterHost();
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700517 try {
518 filter.install(mInputFilterHost);
519 } catch (RemoteException re) {
520 /* ignore */
521 }
Jeff Brown0029c662011-03-30 02:25:18 -0700522 }
523
Jeff Brown4532e612012-04-05 14:27:12 -0700524 nativeSetInputFilterEnabled(mPtr, filter != null);
Jeff Brown0029c662011-03-30 02:25:18 -0700525 }
526 }
527
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700528 @Override // Binder call
Jeff Brownac143512012-04-05 18:57:33 -0700529 public boolean injectInputEvent(InputEvent event, int mode) {
Jeff Brownca9bc702014-02-11 14:32:56 -0800530 return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
531 }
532
533 private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700534 if (event == null) {
535 throw new IllegalArgumentException("event must not be null");
536 }
Jeff Brownac143512012-04-05 18:57:33 -0700537 if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
538 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
539 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
540 throw new IllegalArgumentException("mode is invalid");
Jeff Brown7fbdc842010-06-17 20:52:56 -0700541 }
Jeff Brown6ec402b2010-07-28 15:48:59 -0700542
Jeff Brownac143512012-04-05 18:57:33 -0700543 final int pid = Binder.getCallingPid();
544 final int uid = Binder.getCallingUid();
545 final long ident = Binder.clearCallingIdentity();
546 final int result;
547 try {
Jeff Brownca9bc702014-02-11 14:32:56 -0800548 result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,
Jeff Brownac143512012-04-05 18:57:33 -0700549 INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
550 } finally {
551 Binder.restoreCallingIdentity(ident);
552 }
553 switch (result) {
554 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
555 Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
556 throw new SecurityException(
557 "Injecting to another application requires INJECT_EVENTS permission");
558 case INPUT_EVENT_INJECTION_SUCCEEDED:
559 return true;
560 case INPUT_EVENT_INJECTION_TIMED_OUT:
561 Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
562 return false;
563 case INPUT_EVENT_INJECTION_FAILED:
564 default:
565 Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
566 return false;
567 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700568 }
Jeff Brown0029c662011-03-30 02:25:18 -0700569
Jeff Brown8d608662010-08-30 03:02:23 -0700570 /**
571 * Gets information about the input device with the specified id.
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700572 * @param deviceId The device id.
Jeff Brown8d608662010-08-30 03:02:23 -0700573 * @return The input device or null if not found.
574 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700575 @Override // Binder call
Jeff Brown8d608662010-08-30 03:02:23 -0700576 public InputDevice getInputDevice(int deviceId) {
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700577 synchronized (mInputDevicesLock) {
578 final int count = mInputDevices.length;
579 for (int i = 0; i < count; i++) {
580 final InputDevice inputDevice = mInputDevices[i];
581 if (inputDevice.getId() == deviceId) {
582 return inputDevice;
583 }
584 }
585 }
586 return null;
Jeff Brown8d608662010-08-30 03:02:23 -0700587 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700588
Jeff Brown8d608662010-08-30 03:02:23 -0700589 /**
590 * Gets the ids of all input devices in the system.
591 * @return The input device ids.
592 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700593 @Override // Binder call
Jeff Brown8d608662010-08-30 03:02:23 -0700594 public int[] getInputDeviceIds() {
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700595 synchronized (mInputDevicesLock) {
596 final int count = mInputDevices.length;
597 int[] ids = new int[count];
598 for (int i = 0; i < count; i++) {
599 ids[i] = mInputDevices[i].getId();
600 }
601 return ids;
602 }
603 }
604
Jeff Browndaa37532012-05-01 15:54:03 -0700605 /**
606 * Gets all input devices in the system.
607 * @return The array of input devices.
608 */
609 public InputDevice[] getInputDevices() {
610 synchronized (mInputDevicesLock) {
611 return mInputDevices;
612 }
613 }
614
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700615 @Override // Binder call
616 public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
617 if (listener == null) {
618 throw new IllegalArgumentException("listener must not be null");
619 }
620
621 synchronized (mInputDevicesLock) {
622 int callingPid = Binder.getCallingPid();
623 if (mInputDevicesChangedListeners.get(callingPid) != null) {
624 throw new SecurityException("The calling process has already "
625 + "registered an InputDevicesChangedListener.");
626 }
627
628 InputDevicesChangedListenerRecord record =
629 new InputDevicesChangedListenerRecord(callingPid, listener);
630 try {
631 IBinder binder = listener.asBinder();
632 binder.linkToDeath(record, 0);
633 } catch (RemoteException ex) {
634 // give up
635 throw new RuntimeException(ex);
636 }
637
638 mInputDevicesChangedListeners.put(callingPid, record);
639 }
640 }
641
642 private void onInputDevicesChangedListenerDied(int pid) {
643 synchronized (mInputDevicesLock) {
644 mInputDevicesChangedListeners.remove(pid);
645 }
646 }
647
648 // Must be called on handler.
Jeff Browncf39bdf2012-05-18 14:41:19 -0700649 private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) {
650 // Scan for changes.
651 int numFullKeyboardsAdded = 0;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700652 mTempInputDevicesChangedListenersToNotify.clear();
Jeff Browncf39bdf2012-05-18 14:41:19 -0700653 mTempFullKeyboards.clear();
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700654 final int numListeners;
655 final int[] deviceIdAndGeneration;
656 synchronized (mInputDevicesLock) {
657 if (!mInputDevicesChangedPending) {
658 return;
659 }
660 mInputDevicesChangedPending = false;
661
662 numListeners = mInputDevicesChangedListeners.size();
663 for (int i = 0; i < numListeners; i++) {
664 mTempInputDevicesChangedListenersToNotify.add(
665 mInputDevicesChangedListeners.valueAt(i));
666 }
667
668 final int numDevices = mInputDevices.length;
669 deviceIdAndGeneration = new int[numDevices * 2];
670 for (int i = 0; i < numDevices; i++) {
671 final InputDevice inputDevice = mInputDevices[i];
672 deviceIdAndGeneration[i * 2] = inputDevice.getId();
673 deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
Jeff Browncf39bdf2012-05-18 14:41:19 -0700674
Jeff Brown7e4ff4b2012-05-30 14:32:16 -0700675 if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700676 if (!containsInputDeviceWithDescriptor(oldInputDevices,
677 inputDevice.getDescriptor())) {
678 mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice);
679 } else {
680 mTempFullKeyboards.add(inputDevice);
681 }
682 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700683 }
684 }
685
Jeff Browncf39bdf2012-05-18 14:41:19 -0700686 // Notify listeners.
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700687 for (int i = 0; i < numListeners; i++) {
688 mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged(
689 deviceIdAndGeneration);
690 }
Jeff Browncf39bdf2012-05-18 14:41:19 -0700691 mTempInputDevicesChangedListenersToNotify.clear();
692
693 // Check for missing keyboard layouts.
694 if (mNotificationManager != null) {
695 final int numFullKeyboards = mTempFullKeyboards.size();
696 boolean missingLayoutForExternalKeyboard = false;
697 boolean missingLayoutForExternalKeyboardAdded = false;
Michael Wrightc93fbd12014-09-22 20:07:59 -0700698 boolean multipleMissingLayoutsForExternalKeyboardsAdded = false;
699 InputDevice keyboardMissingLayout = null;
Jeff Browncf39bdf2012-05-18 14:41:19 -0700700 synchronized (mDataStore) {
701 for (int i = 0; i < numFullKeyboards; i++) {
702 final InputDevice inputDevice = mTempFullKeyboards.get(i);
Michael Wright86aaca62014-09-08 18:54:45 -0700703 final String layout =
704 getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
705 if (layout == null) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700706 missingLayoutForExternalKeyboard = true;
707 if (i < numFullKeyboardsAdded) {
708 missingLayoutForExternalKeyboardAdded = true;
Michael Wrightc93fbd12014-09-22 20:07:59 -0700709 if (keyboardMissingLayout == null) {
710 keyboardMissingLayout = inputDevice;
711 } else {
712 multipleMissingLayoutsForExternalKeyboardsAdded = true;
713 }
Jeff Browncf39bdf2012-05-18 14:41:19 -0700714 }
715 }
716 }
717 }
718 if (missingLayoutForExternalKeyboard) {
719 if (missingLayoutForExternalKeyboardAdded) {
Michael Wrightc93fbd12014-09-22 20:07:59 -0700720 if (multipleMissingLayoutsForExternalKeyboardsAdded) {
721 // We have more than one keyboard missing a layout, so drop the
722 // user at the generic input methods page so they can pick which
723 // one to set.
724 showMissingKeyboardLayoutNotification(null);
725 } else {
726 showMissingKeyboardLayoutNotification(keyboardMissingLayout);
727 }
Jeff Browncf39bdf2012-05-18 14:41:19 -0700728 }
729 } else if (mKeyboardLayoutNotificationShown) {
730 hideMissingKeyboardLayoutNotification();
731 }
732 }
733 mTempFullKeyboards.clear();
734 }
735
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800736 @Override // Binder call & native callback
Jason Gerecked5220742014-03-10 09:47:59 -0700737 public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
738 int surfaceRotation) {
Jason Gerecked6396d62014-01-27 18:30:37 -0800739 if (inputDeviceDescriptor == null) {
740 throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
741 }
742
743 synchronized (mDataStore) {
Jason Gerecked5220742014-03-10 09:47:59 -0700744 return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
Jason Gerecked6396d62014-01-27 18:30:37 -0800745 }
746 }
747
748 @Override // Binder call
Jason Gerecked5220742014-03-10 09:47:59 -0700749 public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
Jason Gerecked6396d62014-01-27 18:30:37 -0800750 TouchCalibration calibration) {
751 if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
752 "setTouchCalibrationForInputDevice()")) {
753 throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
754 }
755 if (inputDeviceDescriptor == null) {
756 throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
757 }
758 if (calibration == null) {
759 throw new IllegalArgumentException("calibration must not be null");
760 }
Jason Gerecked5220742014-03-10 09:47:59 -0700761 if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
762 throw new IllegalArgumentException("surfaceRotation value out of bounds");
763 }
Jason Gerecked6396d62014-01-27 18:30:37 -0800764
765 synchronized (mDataStore) {
766 try {
Jason Gerecked5220742014-03-10 09:47:59 -0700767 if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
768 calibration)) {
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800769 nativeReloadCalibration(mPtr);
770 }
Jason Gerecked6396d62014-01-27 18:30:37 -0800771 } finally {
772 mDataStore.saveIfNeeded();
773 }
774 }
775 }
776
Jeff Browncf39bdf2012-05-18 14:41:19 -0700777 // Must be called on handler.
Michael Wrightc93fbd12014-09-22 20:07:59 -0700778 private void showMissingKeyboardLayoutNotification(InputDevice device) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700779 if (!mKeyboardLayoutNotificationShown) {
Michael Wrightc93fbd12014-09-22 20:07:59 -0700780 final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
781 if (device != null) {
782 intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, device.getIdentifier());
Jeff Browncf39bdf2012-05-18 14:41:19 -0700783 }
Michael Wrightc93fbd12014-09-22 20:07:59 -0700784 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
785 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
786 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
787 final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
788 intent, 0, null, UserHandle.CURRENT);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700789
790 Resources r = mContext.getResources();
791 Notification notification = new Notification.Builder(mContext)
792 .setContentTitle(r.getString(
793 R.string.select_keyboard_layout_notification_title))
794 .setContentText(r.getString(
795 R.string.select_keyboard_layout_notification_message))
Michael Wrightc93fbd12014-09-22 20:07:59 -0700796 .setContentIntent(keyboardLayoutIntent)
Jeff Browncf39bdf2012-05-18 14:41:19 -0700797 .setSmallIcon(R.drawable.ic_settings_language)
798 .setPriority(Notification.PRIORITY_LOW)
Selim Cinek255dd042014-08-19 22:29:02 +0200799 .setColor(mContext.getResources().getColor(
800 com.android.internal.R.color.system_notification_accent_color))
Jeff Browncf39bdf2012-05-18 14:41:19 -0700801 .build();
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700802 mNotificationManager.notifyAsUser(null,
803 R.string.select_keyboard_layout_notification_title,
804 notification, UserHandle.ALL);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700805 mKeyboardLayoutNotificationShown = true;
806 }
807 }
808
809 // Must be called on handler.
810 private void hideMissingKeyboardLayoutNotification() {
811 if (mKeyboardLayoutNotificationShown) {
812 mKeyboardLayoutNotificationShown = false;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700813 mNotificationManager.cancelAsUser(null,
814 R.string.select_keyboard_layout_notification_title,
815 UserHandle.ALL);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700816 }
817 }
818
819 // Must be called on handler.
820 private void updateKeyboardLayouts() {
821 // Scan all input devices state for keyboard layouts that have been uninstalled.
822 final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
823 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
824 @Override
Michael Wright8ebac232014-09-18 18:29:49 -0700825 public void visitKeyboardLayout(Resources resources, String descriptor, String label,
826 String collection, int keyboardLayoutResId, int priority) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700827 availableKeyboardLayouts.add(descriptor);
828 }
829 });
830 synchronized (mDataStore) {
831 try {
832 mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
833 } finally {
834 mDataStore.saveIfNeeded();
835 }
836 }
837
838 // Reload keyboard layouts.
839 reloadKeyboardLayouts();
840 }
841
Jeff Browncf39bdf2012-05-18 14:41:19 -0700842 private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices,
843 String descriptor) {
844 final int numDevices = inputDevices.length;
845 for (int i = 0; i < numDevices; i++) {
846 final InputDevice inputDevice = inputDevices[i];
847 if (inputDevice.getDescriptor().equals(descriptor)) {
848 return true;
849 }
850 }
851 return false;
Jeff Brown8d608662010-08-30 03:02:23 -0700852 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700853
854 @Override // Binder call
855 public KeyboardLayout[] getKeyboardLayouts() {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700856 final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
857 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
858 @Override
Michael Wright8ebac232014-09-18 18:29:49 -0700859 public void visitKeyboardLayout(Resources resources, String descriptor, String label,
860 String collection, int keyboardLayoutResId, int priority) {
861 list.add(new KeyboardLayout(descriptor, label, collection, priority));
Jeff Brown6ec6f792012-04-17 16:52:41 -0700862 }
863 });
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700864 return list.toArray(new KeyboardLayout[list.size()]);
865 }
866
867 @Override // Binder call
868 public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
869 if (keyboardLayoutDescriptor == null) {
870 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
871 }
872
Jeff Brown6ec6f792012-04-17 16:52:41 -0700873 final KeyboardLayout[] result = new KeyboardLayout[1];
874 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
875 @Override
Michael Wright8ebac232014-09-18 18:29:49 -0700876 public void visitKeyboardLayout(Resources resources, String descriptor,
877 String label, String collection, int keyboardLayoutResId, int priority) {
878 result[0] = new KeyboardLayout(descriptor, label, collection, priority);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700879 }
880 });
881 if (result[0] == null) {
882 Log.w(TAG, "Could not get keyboard layout with descriptor '"
883 + keyboardLayoutDescriptor + "'.");
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700884 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700885 return result[0];
886 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700887
Jeff Brown6ec6f792012-04-17 16:52:41 -0700888 private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700889 final PackageManager pm = mContext.getPackageManager();
Jeff Brown6ec6f792012-04-17 16:52:41 -0700890 Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
891 for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
892 PackageManager.GET_META_DATA)) {
Michael Wright8ebac232014-09-18 18:29:49 -0700893 final ActivityInfo activityInfo = resolveInfo.activityInfo;
894 final int priority = resolveInfo.priority;
895 visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700896 }
897 }
898
Jeff Brown6ec6f792012-04-17 16:52:41 -0700899 private void visitKeyboardLayout(String keyboardLayoutDescriptor,
900 KeyboardLayoutVisitor visitor) {
901 KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor);
902 if (d != null) {
903 final PackageManager pm = mContext.getPackageManager();
904 try {
905 ActivityInfo receiver = pm.getReceiverInfo(
906 new ComponentName(d.packageName, d.receiverName),
907 PackageManager.GET_META_DATA);
Michael Wright8ebac232014-09-18 18:29:49 -0700908 visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, 0, visitor);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700909 } catch (NameNotFoundException ex) {
910 }
911 }
912 }
913
914 private void visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver,
Michael Wright8ebac232014-09-18 18:29:49 -0700915 String keyboardName, int requestedPriority, KeyboardLayoutVisitor visitor) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700916 Bundle metaData = receiver.metaData;
917 if (metaData == null) {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700918 return;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700919 }
920
921 int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS);
922 if (configResId == 0) {
923 Log.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
924 + "' on receiver " + receiver.packageName + "/" + receiver.name);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700925 return;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700926 }
927
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700928 CharSequence receiverLabel = receiver.loadLabel(pm);
929 String collection = receiverLabel != null ? receiverLabel.toString() : "";
Michael Wright8ebac232014-09-18 18:29:49 -0700930 int priority;
931 if ((receiver.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
932 priority = requestedPriority;
933 } else {
934 priority = 0;
935 }
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700936
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700937 try {
938 Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
939 XmlResourceParser parser = resources.getXml(configResId);
940 try {
941 XmlUtils.beginDocument(parser, "keyboard-layouts");
942
943 for (;;) {
944 XmlUtils.nextElement(parser);
945 String element = parser.getName();
946 if (element == null) {
947 break;
948 }
949 if (element.equals("keyboard-layout")) {
950 TypedArray a = resources.obtainAttributes(
951 parser, com.android.internal.R.styleable.KeyboardLayout);
952 try {
953 String name = a.getString(
954 com.android.internal.R.styleable.KeyboardLayout_name);
955 String label = a.getString(
956 com.android.internal.R.styleable.KeyboardLayout_label);
Jeff Brown2f095762012-05-10 21:29:33 -0700957 int keyboardLayoutResId = a.getResourceId(
958 com.android.internal.R.styleable.KeyboardLayout_keyboardLayout,
959 0);
960 if (name == null || label == null || keyboardLayoutResId == 0) {
961 Log.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700962 + "attributes in keyboard layout "
963 + "resource from receiver "
964 + receiver.packageName + "/" + receiver.name);
965 } else {
966 String descriptor = KeyboardLayoutDescriptor.format(
967 receiver.packageName, receiver.name, name);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700968 if (keyboardName == null || name.equals(keyboardName)) {
969 visitor.visitKeyboardLayout(resources, descriptor,
Michael Wright8ebac232014-09-18 18:29:49 -0700970 label, collection, keyboardLayoutResId, priority);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700971 }
972 }
973 } finally {
974 a.recycle();
975 }
976 } else {
977 Log.w(TAG, "Skipping unrecognized element '" + element
978 + "' in keyboard layout resource from receiver "
979 + receiver.packageName + "/" + receiver.name);
980 }
981 }
982 } finally {
983 parser.close();
984 }
985 } catch (Exception ex) {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700986 Log.w(TAG, "Could not parse keyboard layout resource from receiver "
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700987 + receiver.packageName + "/" + receiver.name, ex);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700988 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700989 }
990
RoboErikfb290df2013-12-16 11:27:55 -0800991 /**
992 * Builds a layout descriptor for the vendor/product. This returns the
993 * descriptor for ids that aren't useful (such as the default 0, 0).
994 */
995 private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
996 if (identifier == null || identifier.getDescriptor() == null) {
997 throw new IllegalArgumentException("identifier and descriptor must not be null");
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700998 }
999
RoboErikfb290df2013-12-16 11:27:55 -08001000 if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
1001 return identifier.getDescriptor();
1002 }
1003 StringBuilder bob = new StringBuilder();
1004 bob.append("vendor:").append(identifier.getVendorId());
1005 bob.append(",product:").append(identifier.getProductId());
1006 return bob.toString();
1007 }
1008
1009 @Override // Binder call
1010 public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
1011
1012 String key = getLayoutDescriptor(identifier);
Jeff Browna3bc5652012-04-17 11:42:25 -07001013 synchronized (mDataStore) {
RoboErikfb290df2013-12-16 11:27:55 -08001014 String layout = null;
1015 // try loading it using the layout descriptor if we have it
1016 layout = mDataStore.getCurrentKeyboardLayout(key);
1017 if (layout == null && !key.equals(identifier.getDescriptor())) {
1018 // if it doesn't exist fall back to the device descriptor
1019 layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1020 }
1021 if (DEBUG) {
1022 Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got "
1023 + layout);
1024 }
1025 return layout;
Jeff Browna3bc5652012-04-17 11:42:25 -07001026 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001027 }
1028
1029 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001030 public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001031 String keyboardLayoutDescriptor) {
1032 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001033 "setCurrentKeyboardLayoutForInputDevice()")) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001034 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1035 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001036 if (keyboardLayoutDescriptor == null) {
1037 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1038 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001039
RoboErikfb290df2013-12-16 11:27:55 -08001040 String key = getLayoutDescriptor(identifier);
Jeff Browna3bc5652012-04-17 11:42:25 -07001041 synchronized (mDataStore) {
1042 try {
RoboErikfb290df2013-12-16 11:27:55 -08001043 if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
1044 if (DEBUG) {
1045 Slog.d(TAG, "Saved keyboard layout using " + key);
1046 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001047 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1048 }
Jeff Browna3bc5652012-04-17 11:42:25 -07001049 } finally {
1050 mDataStore.saveIfNeeded();
1051 }
1052 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001053 }
Jeff Brown6ec6f792012-04-17 16:52:41 -07001054
Jeff Browncf39bdf2012-05-18 14:41:19 -07001055 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001056 public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
1057 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001058 synchronized (mDataStore) {
RoboErikfb290df2013-12-16 11:27:55 -08001059 String[] layouts = mDataStore.getKeyboardLayouts(key);
1060 if ((layouts == null || layouts.length == 0)
1061 && !key.equals(identifier.getDescriptor())) {
1062 layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
1063 }
1064 return layouts;
Jeff Browncf39bdf2012-05-18 14:41:19 -07001065 }
1066 }
1067
1068 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001069 public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001070 String keyboardLayoutDescriptor) {
1071 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1072 "addKeyboardLayoutForInputDevice()")) {
1073 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1074 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001075 if (keyboardLayoutDescriptor == null) {
1076 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1077 }
1078
RoboErikfb290df2013-12-16 11:27:55 -08001079 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001080 synchronized (mDataStore) {
1081 try {
RoboErikfb290df2013-12-16 11:27:55 -08001082 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1083 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1084 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1085 }
1086 if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
Jeff Browncf39bdf2012-05-18 14:41:19 -07001087 && !Objects.equal(oldLayout,
RoboErikfb290df2013-12-16 11:27:55 -08001088 mDataStore.getCurrentKeyboardLayout(key))) {
Jeff Browncf39bdf2012-05-18 14:41:19 -07001089 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1090 }
1091 } finally {
1092 mDataStore.saveIfNeeded();
Jeff Brown6ec6f792012-04-17 16:52:41 -07001093 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001094 }
1095 }
1096
1097 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001098 public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001099 String keyboardLayoutDescriptor) {
1100 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1101 "removeKeyboardLayoutForInputDevice()")) {
1102 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1103 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001104 if (keyboardLayoutDescriptor == null) {
1105 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1106 }
1107
RoboErikfb290df2013-12-16 11:27:55 -08001108 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001109 synchronized (mDataStore) {
1110 try {
RoboErikfb290df2013-12-16 11:27:55 -08001111 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1112 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1113 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1114 }
1115 boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
1116 if (!key.equals(identifier.getDescriptor())) {
1117 // We need to remove from both places to ensure it is gone
1118 removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
1119 keyboardLayoutDescriptor);
1120 }
1121 if (removed && !Objects.equal(oldLayout,
1122 mDataStore.getCurrentKeyboardLayout(key))) {
Jeff Browncf39bdf2012-05-18 14:41:19 -07001123 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1124 }
1125 } finally {
1126 mDataStore.saveIfNeeded();
1127 }
1128 }
1129 }
1130
1131 public void switchKeyboardLayout(int deviceId, int direction) {
1132 mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
1133 }
1134
1135 // Must be called on handler.
1136 private void handleSwitchKeyboardLayout(int deviceId, int direction) {
1137 final InputDevice device = getInputDevice(deviceId);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001138 if (device != null) {
1139 final boolean changed;
1140 final String keyboardLayoutDescriptor;
RoboErikfb290df2013-12-16 11:27:55 -08001141
1142 String key = getLayoutDescriptor(device.getIdentifier());
Jeff Browncf39bdf2012-05-18 14:41:19 -07001143 synchronized (mDataStore) {
1144 try {
RoboErikfb290df2013-12-16 11:27:55 -08001145 changed = mDataStore.switchKeyboardLayout(key, direction);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001146 keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
RoboErikfb290df2013-12-16 11:27:55 -08001147 key);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001148 } finally {
1149 mDataStore.saveIfNeeded();
1150 }
1151 }
1152
1153 if (changed) {
1154 if (mSwitchedKeyboardLayoutToast != null) {
1155 mSwitchedKeyboardLayoutToast.cancel();
1156 mSwitchedKeyboardLayoutToast = null;
1157 }
1158 if (keyboardLayoutDescriptor != null) {
1159 KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
1160 if (keyboardLayout != null) {
1161 mSwitchedKeyboardLayoutToast = Toast.makeText(
1162 mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
1163 mSwitchedKeyboardLayoutToast.show();
1164 }
1165 }
1166
1167 reloadKeyboardLayouts();
1168 }
Jeff Brown6ec6f792012-04-17 16:52:41 -07001169 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001170 }
1171
Jeff Brown9302c872011-07-13 22:51:29 -07001172 public void setInputWindows(InputWindowHandle[] windowHandles) {
Jeff Brown4532e612012-04-05 14:27:12 -07001173 nativeSetInputWindows(mPtr, windowHandles);
Jeff Brown349703e2010-06-22 01:27:15 -07001174 }
RoboErikfb290df2013-12-16 11:27:55 -08001175
Jeff Brown9302c872011-07-13 22:51:29 -07001176 public void setFocusedApplication(InputApplicationHandle application) {
Jeff Brown4532e612012-04-05 14:27:12 -07001177 nativeSetFocusedApplication(mPtr, application);
Jeff Brown349703e2010-06-22 01:27:15 -07001178 }
RoboErikfb290df2013-12-16 11:27:55 -08001179
Jeff Brown349703e2010-06-22 01:27:15 -07001180 public void setInputDispatchMode(boolean enabled, boolean frozen) {
Jeff Brown4532e612012-04-05 14:27:12 -07001181 nativeSetInputDispatchMode(mPtr, enabled, frozen);
Jeff Brown349703e2010-06-22 01:27:15 -07001182 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001183
1184 public void setSystemUiVisibility(int visibility) {
Jeff Brown4532e612012-04-05 14:27:12 -07001185 nativeSetSystemUiVisibility(mPtr, visibility);
Jeff Brown05dc66a2011-03-02 14:41:58 -08001186 }
1187
Jeff Browne6504122010-09-27 14:52:15 -07001188 /**
1189 * Atomically transfers touch focus from one window to another as identified by
1190 * their input channels. It is possible for multiple windows to have
1191 * touch focus if they support split touch dispatch
1192 * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
1193 * method only transfers touch focus of the specified window without affecting
1194 * other windows that may also have touch focus at the same time.
1195 * @param fromChannel The channel of a window that currently has touch focus.
1196 * @param toChannel The channel of the window that should receive touch focus in
1197 * place of the first.
1198 * @return True if the transfer was successful. False if the window with the
1199 * specified channel did not actually have touch focus at the time of the request.
1200 */
1201 public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
1202 if (fromChannel == null) {
1203 throw new IllegalArgumentException("fromChannel must not be null.");
1204 }
1205 if (toChannel == null) {
1206 throw new IllegalArgumentException("toChannel must not be null.");
1207 }
Jeff Brown4532e612012-04-05 14:27:12 -07001208 return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
Jeff Browne6504122010-09-27 14:52:15 -07001209 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001210
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001211 @Override // Binder call
Jeff Brownac143512012-04-05 18:57:33 -07001212 public void tryPointerSpeed(int speed) {
1213 if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
1214 "tryPointerSpeed()")) {
1215 throw new SecurityException("Requires SET_POINTER_SPEED permission");
1216 }
1217
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001218 if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) {
1219 throw new IllegalArgumentException("speed out of range");
1220 }
1221
Jeff Brownac143512012-04-05 18:57:33 -07001222 setPointerSpeedUnchecked(speed);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001223 }
1224
1225 public void updatePointerSpeedFromSettings() {
Jeff Brownac143512012-04-05 18:57:33 -07001226 int speed = getPointerSpeedSetting();
1227 setPointerSpeedUnchecked(speed);
1228 }
1229
1230 private void setPointerSpeedUnchecked(int speed) {
1231 speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
1232 InputManager.MAX_POINTER_SPEED);
1233 nativeSetPointerSpeed(mPtr, speed);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001234 }
1235
1236 private void registerPointerSpeedSettingObserver() {
1237 mContext.getContentResolver().registerContentObserver(
1238 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
Jeff Brown4532e612012-04-05 14:27:12 -07001239 new ContentObserver(mHandler) {
Jeff Brown1a84fd12011-06-02 01:26:32 -07001240 @Override
1241 public void onChange(boolean selfChange) {
1242 updatePointerSpeedFromSettings();
1243 }
Jeff Brownd4935962012-09-25 13:27:20 -07001244 }, UserHandle.USER_ALL);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001245 }
1246
Jeff Brownac143512012-04-05 18:57:33 -07001247 private int getPointerSpeedSetting() {
1248 int speed = InputManager.DEFAULT_POINTER_SPEED;
Jeff Brown1a84fd12011-06-02 01:26:32 -07001249 try {
Jeff Brownd4935962012-09-25 13:27:20 -07001250 speed = Settings.System.getIntForUser(mContext.getContentResolver(),
1251 Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001252 } catch (SettingNotFoundException snfe) {
1253 }
1254 return speed;
1255 }
1256
Jeff Browndaf4a122011-08-26 17:14:14 -07001257 public void updateShowTouchesFromSettings() {
1258 int setting = getShowTouchesSetting(0);
Jeff Brown4532e612012-04-05 14:27:12 -07001259 nativeSetShowTouches(mPtr, setting != 0);
Jeff Browndaf4a122011-08-26 17:14:14 -07001260 }
1261
1262 private void registerShowTouchesSettingObserver() {
1263 mContext.getContentResolver().registerContentObserver(
1264 Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
Jeff Brown4532e612012-04-05 14:27:12 -07001265 new ContentObserver(mHandler) {
Jeff Browndaf4a122011-08-26 17:14:14 -07001266 @Override
1267 public void onChange(boolean selfChange) {
1268 updateShowTouchesFromSettings();
1269 }
Jeff Brownd4935962012-09-25 13:27:20 -07001270 }, UserHandle.USER_ALL);
Jeff Browndaf4a122011-08-26 17:14:14 -07001271 }
1272
1273 private int getShowTouchesSetting(int defaultValue) {
1274 int result = defaultValue;
1275 try {
Jeff Brownd4935962012-09-25 13:27:20 -07001276 result = Settings.System.getIntForUser(mContext.getContentResolver(),
1277 Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
Jeff Browndaf4a122011-08-26 17:14:14 -07001278 } catch (SettingNotFoundException snfe) {
1279 }
1280 return result;
1281 }
1282
Jeff Browna47425a2012-04-13 04:09:27 -07001283 // Binder call
1284 @Override
1285 public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {
1286 if (repeat >= pattern.length) {
1287 throw new ArrayIndexOutOfBoundsException();
1288 }
1289
1290 VibratorToken v;
1291 synchronized (mVibratorLock) {
1292 v = mVibratorTokens.get(token);
1293 if (v == null) {
1294 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);
1295 try {
1296 token.linkToDeath(v, 0);
1297 } catch (RemoteException ex) {
1298 // give up
1299 throw new RuntimeException(ex);
1300 }
1301 mVibratorTokens.put(token, v);
1302 }
1303 }
1304
1305 synchronized (v) {
1306 v.mVibrating = true;
1307 nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue);
1308 }
1309 }
1310
1311 // Binder call
1312 @Override
1313 public void cancelVibrate(int deviceId, IBinder token) {
1314 VibratorToken v;
1315 synchronized (mVibratorLock) {
1316 v = mVibratorTokens.get(token);
1317 if (v == null || v.mDeviceId != deviceId) {
1318 return; // nothing to cancel
1319 }
1320 }
1321
1322 cancelVibrateIfNeeded(v);
1323 }
1324
1325 void onVibratorTokenDied(VibratorToken v) {
1326 synchronized (mVibratorLock) {
1327 mVibratorTokens.remove(v.mToken);
1328 }
1329
1330 cancelVibrateIfNeeded(v);
1331 }
1332
1333 private void cancelVibrateIfNeeded(VibratorToken v) {
1334 synchronized (v) {
1335 if (v.mVibrating) {
1336 nativeCancelVibrate(mPtr, v.mDeviceId, v.mTokenValue);
1337 v.mVibrating = false;
1338 }
1339 }
1340 }
1341
Jeff Brown4532e612012-04-05 14:27:12 -07001342 @Override
1343 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Browna3bc5652012-04-17 11:42:25 -07001344 if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
Jeff Brown4532e612012-04-05 14:27:12 -07001345 != PackageManager.PERMISSION_GRANTED) {
1346 pw.println("Permission Denial: can't dump InputManager from from pid="
1347 + Binder.getCallingPid()
1348 + ", uid=" + Binder.getCallingUid());
1349 return;
1350 }
1351
1352 pw.println("INPUT MANAGER (dumpsys input)\n");
1353 String dumpStr = nativeDump(mPtr);
Jeff Browne33348b2010-07-15 23:54:05 -07001354 if (dumpStr != null) {
1355 pw.println(dumpStr);
1356 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001357 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001358
Jeff Brownac143512012-04-05 18:57:33 -07001359 private boolean checkCallingPermission(String permission, String func) {
1360 // Quick check: if the calling permission is me, it's all okay.
1361 if (Binder.getCallingPid() == Process.myPid()) {
1362 return true;
1363 }
1364
1365 if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
1366 return true;
1367 }
1368 String msg = "Permission Denial: " + func + " from pid="
1369 + Binder.getCallingPid()
1370 + ", uid=" + Binder.getCallingUid()
1371 + " requires " + permission;
1372 Slog.w(TAG, msg);
1373 return false;
1374 }
1375
Jeff Brown4532e612012-04-05 14:27:12 -07001376 // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001377 @Override
Jeff Brown89ef0722011-08-10 16:25:21 -07001378 public void monitor() {
1379 synchronized (mInputFilterLock) { }
Jeff Brown4532e612012-04-05 14:27:12 -07001380 nativeMonitor(mPtr);
Jeff Brown89ef0722011-08-10 16:25:21 -07001381 }
1382
Jeff Brown4532e612012-04-05 14:27:12 -07001383 // Native callback.
1384 private void notifyConfigurationChanged(long whenNanos) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001385 mWindowManagerCallbacks.notifyConfigurationChanged();
Jeff Brown4532e612012-04-05 14:27:12 -07001386 }
1387
1388 // Native callback.
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001389 private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
1390 synchronized (mInputDevicesLock) {
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001391 if (!mInputDevicesChangedPending) {
1392 mInputDevicesChangedPending = true;
Jeff Browncf39bdf2012-05-18 14:41:19 -07001393 mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED,
1394 mInputDevices).sendToTarget();
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001395 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001396
1397 mInputDevices = inputDevices;
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001398 }
1399 }
1400
1401 // Native callback.
Jeff Brownbcc046a2012-09-27 20:46:43 -07001402 private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
1403 if (DEBUG) {
1404 Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
1405 + ", mask=" + Integer.toHexString(switchMask));
1406 }
1407
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001408 if ((switchMask & SW_LID_BIT) != 0) {
1409 final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
Jeff Brownbcc046a2012-09-27 20:46:43 -07001410 mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
Jeff Brown53384282012-08-20 20:16:01 -07001411 }
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001412
Michael Wright3818c922014-09-02 13:59:07 -07001413 if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
Michael Wright9e10d252014-09-13 19:41:20 -07001414 final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
Michael Wright3818c922014-09-02 13:59:07 -07001415 mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
1416 }
1417
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001418 if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
1419 mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
1420 switchMask);
1421 }
Jeff Brown4532e612012-04-05 14:27:12 -07001422 }
1423
1424 // Native callback.
1425 private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001426 mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
Jeff Brown4532e612012-04-05 14:27:12 -07001427 }
1428
1429 // Native callback.
1430 private long notifyANR(InputApplicationHandle inputApplicationHandle,
Jeff Brownbd181bb2013-09-10 16:44:24 -07001431 InputWindowHandle inputWindowHandle, String reason) {
1432 return mWindowManagerCallbacks.notifyANR(
1433 inputApplicationHandle, inputWindowHandle, reason);
Jeff Brown4532e612012-04-05 14:27:12 -07001434 }
1435
1436 // Native callback.
1437 final boolean filterInputEvent(InputEvent event, int policyFlags) {
1438 synchronized (mInputFilterLock) {
1439 if (mInputFilter != null) {
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001440 try {
1441 mInputFilter.filterInputEvent(event, policyFlags);
1442 } catch (RemoteException e) {
1443 /* ignore */
1444 }
Jeff Brown4532e612012-04-05 14:27:12 -07001445 return false;
1446 }
1447 }
1448 event.recycle();
1449 return true;
1450 }
1451
1452 // Native callback.
Jeff Brown037c33e2014-04-09 00:31:55 -07001453 private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1454 return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001455 }
1456
1457 // Native callback.
Michael Wright70af00a2014-09-03 19:30:20 -07001458 private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
1459 return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
Jeff Brown26875502014-01-30 21:47:47 -08001460 whenNanos, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001461 }
1462
1463 // Native callback.
1464 private long interceptKeyBeforeDispatching(InputWindowHandle focus,
1465 KeyEvent event, int policyFlags) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001466 return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001467 }
1468
1469 // Native callback.
1470 private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1471 KeyEvent event, int policyFlags) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001472 return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001473 }
1474
1475 // Native callback.
1476 private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
1477 return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
1478 injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
1479 }
1480
1481 // Native callback.
1482 private int getVirtualKeyQuietTimeMillis() {
1483 return mContext.getResources().getInteger(
1484 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
1485 }
1486
1487 // Native callback.
1488 private String[] getExcludedDeviceNames() {
1489 ArrayList<String> names = new ArrayList<String>();
1490
1491 // Read partner-provided list of excluded input devices
1492 XmlPullParser parser = null;
1493 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
1494 File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
1495 FileReader confreader = null;
1496 try {
1497 confreader = new FileReader(confFile);
1498 parser = Xml.newPullParser();
1499 parser.setInput(confreader);
1500 XmlUtils.beginDocument(parser, "devices");
1501
1502 while (true) {
1503 XmlUtils.nextElement(parser);
1504 if (!"device".equals(parser.getName())) {
1505 break;
1506 }
1507 String name = parser.getAttributeValue(null, "name");
1508 if (name != null) {
1509 names.add(name);
1510 }
1511 }
1512 } catch (FileNotFoundException e) {
1513 // It's ok if the file does not exist.
1514 } catch (Exception e) {
1515 Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
1516 } finally {
1517 try { if (confreader != null) confreader.close(); } catch (IOException e) { }
1518 }
1519
1520 return names.toArray(new String[names.size()]);
1521 }
1522
1523 // Native callback.
1524 private int getKeyRepeatTimeout() {
1525 return ViewConfiguration.getKeyRepeatTimeout();
1526 }
1527
1528 // Native callback.
1529 private int getKeyRepeatDelay() {
1530 return ViewConfiguration.getKeyRepeatDelay();
1531 }
1532
1533 // Native callback.
1534 private int getHoverTapTimeout() {
1535 return ViewConfiguration.getHoverTapTimeout();
1536 }
1537
1538 // Native callback.
1539 private int getHoverTapSlop() {
1540 return ViewConfiguration.getHoverTapSlop();
1541 }
1542
1543 // Native callback.
1544 private int getDoubleTapTimeout() {
1545 return ViewConfiguration.getDoubleTapTimeout();
1546 }
1547
1548 // Native callback.
1549 private int getLongPressTimeout() {
1550 return ViewConfiguration.getLongPressTimeout();
1551 }
1552
1553 // Native callback.
1554 private int getPointerLayer() {
Jeff Browna9d131c2012-09-20 16:48:17 -07001555 return mWindowManagerCallbacks.getPointerLayer();
Jeff Brown4532e612012-04-05 14:27:12 -07001556 }
1557
1558 // Native callback.
1559 private PointerIcon getPointerIcon() {
1560 return PointerIcon.getDefaultIcon(mContext);
1561 }
1562
Jeff Brown6ec6f792012-04-17 16:52:41 -07001563 // Native callback.
RoboErikfb290df2013-12-16 11:27:55 -08001564 private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
Jeff Brown6ec6f792012-04-17 16:52:41 -07001565 if (!mSystemReady) {
1566 return null;
1567 }
1568
RoboErikfb290df2013-12-16 11:27:55 -08001569 String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
Jeff Brown6ec6f792012-04-17 16:52:41 -07001570 if (keyboardLayoutDescriptor == null) {
1571 return null;
1572 }
1573
1574 final String[] result = new String[2];
1575 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
1576 @Override
Michael Wright8ebac232014-09-18 18:29:49 -07001577 public void visitKeyboardLayout(Resources resources, String descriptor, String label,
1578 String collection, int keyboardLayoutResId, int priority) {
Jeff Brown6ec6f792012-04-17 16:52:41 -07001579 try {
1580 result[0] = descriptor;
1581 result[1] = Streams.readFully(new InputStreamReader(
Jeff Brown2f095762012-05-10 21:29:33 -07001582 resources.openRawResource(keyboardLayoutResId)));
Jeff Brown6ec6f792012-04-17 16:52:41 -07001583 } catch (IOException ex) {
1584 } catch (NotFoundException ex) {
1585 }
1586 }
1587 });
1588 if (result[0] == null) {
1589 Log.w(TAG, "Could not get keyboard layout with descriptor '"
1590 + keyboardLayoutDescriptor + "'.");
1591 return null;
1592 }
1593 return result;
1594 }
1595
Jeff Brown5bbd4b42012-04-20 19:28:00 -07001596 // Native callback.
1597 private String getDeviceAlias(String uniqueId) {
Matthew Xie96313142012-06-29 16:57:31 -07001598 if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
1599 // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
1600 return null;
Jeff Brown5bbd4b42012-04-20 19:28:00 -07001601 }
1602 return null;
1603 }
1604
Jeff Brown4532e612012-04-05 14:27:12 -07001605 /**
1606 * Callback interface implemented by the Window Manager.
1607 */
Jeff Browna9d131c2012-09-20 16:48:17 -07001608 public interface WindowManagerCallbacks {
Jeff Brown4532e612012-04-05 14:27:12 -07001609 public void notifyConfigurationChanged();
1610
1611 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
1612
Michael Wright3818c922014-09-02 13:59:07 -07001613 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
1614
Jeff Brown4532e612012-04-05 14:27:12 -07001615 public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
1616
1617 public long notifyANR(InputApplicationHandle inputApplicationHandle,
Jeff Brownbd181bb2013-09-10 16:44:24 -07001618 InputWindowHandle inputWindowHandle, String reason);
Jeff Brown4532e612012-04-05 14:27:12 -07001619
Jeff Brown037c33e2014-04-09 00:31:55 -07001620 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001621
Michael Wright70af00a2014-09-03 19:30:20 -07001622 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001623
1624 public long interceptKeyBeforeDispatching(InputWindowHandle focus,
1625 KeyEvent event, int policyFlags);
1626
1627 public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1628 KeyEvent event, int policyFlags);
1629
1630 public int getPointerLayer();
1631 }
1632
1633 /**
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001634 * Callback interface implemented by WiredAccessoryObserver.
1635 */
1636 public interface WiredAccessoryCallbacks {
1637 public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
Eric Laurent4a5eeb92014-05-06 10:49:04 -07001638 public void systemReady();
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001639 }
1640
1641 /**
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001642 * Private handler for the input manager.
1643 */
1644 private final class InputManagerHandler extends Handler {
Jeff Browna9d131c2012-09-20 16:48:17 -07001645 public InputManagerHandler(Looper looper) {
1646 super(looper, null, true /*async*/);
Jeff Browna2910d02012-08-25 12:29:46 -07001647 }
1648
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001649 @Override
1650 public void handleMessage(Message msg) {
1651 switch (msg.what) {
1652 case MSG_DELIVER_INPUT_DEVICES_CHANGED:
Jeff Browncf39bdf2012-05-18 14:41:19 -07001653 deliverInputDevicesChanged((InputDevice[])msg.obj);
1654 break;
1655 case MSG_SWITCH_KEYBOARD_LAYOUT:
1656 handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
1657 break;
1658 case MSG_RELOAD_KEYBOARD_LAYOUTS:
1659 reloadKeyboardLayouts();
1660 break;
1661 case MSG_UPDATE_KEYBOARD_LAYOUTS:
1662 updateKeyboardLayouts();
1663 break;
1664 case MSG_RELOAD_DEVICE_ALIASES:
1665 reloadDeviceAliases();
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001666 break;
1667 }
1668 }
1669 }
1670
1671 /**
Jeff Brown4532e612012-04-05 14:27:12 -07001672 * Hosting interface for input filters to call back into the input manager.
1673 */
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001674 private final class InputFilterHost extends IInputFilterHost.Stub {
Jeff Brown0029c662011-03-30 02:25:18 -07001675 private boolean mDisconnected;
1676
1677 public void disconnectLocked() {
1678 mDisconnected = true;
1679 }
1680
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001681 @Override
Jeff Brown0029c662011-03-30 02:25:18 -07001682 public void sendInputEvent(InputEvent event, int policyFlags) {
1683 if (event == null) {
1684 throw new IllegalArgumentException("event must not be null");
1685 }
1686
1687 synchronized (mInputFilterLock) {
1688 if (!mDisconnected) {
Jeff Brownca9bc702014-02-11 14:32:56 -08001689 nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
Jeff Brownac143512012-04-05 18:57:33 -07001690 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
Jeff Brown0029c662011-03-30 02:25:18 -07001691 policyFlags | WindowManagerPolicy.FLAG_FILTERED);
1692 }
1693 }
1694 }
1695 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001696
1697 private static final class KeyboardLayoutDescriptor {
1698 public String packageName;
1699 public String receiverName;
1700 public String keyboardLayoutName;
1701
1702 public static String format(String packageName,
1703 String receiverName, String keyboardName) {
1704 return packageName + "/" + receiverName + "/" + keyboardName;
1705 }
1706
1707 public static KeyboardLayoutDescriptor parse(String descriptor) {
1708 int pos = descriptor.indexOf('/');
1709 if (pos < 0 || pos + 1 == descriptor.length()) {
1710 return null;
1711 }
1712 int pos2 = descriptor.indexOf('/', pos + 1);
1713 if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
1714 return null;
1715 }
1716
1717 KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
1718 result.packageName = descriptor.substring(0, pos);
1719 result.receiverName = descriptor.substring(pos + 1, pos2);
1720 result.keyboardLayoutName = descriptor.substring(pos2 + 1);
1721 return result;
1722 }
1723 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001724
Jeff Brown6ec6f792012-04-17 16:52:41 -07001725 private interface KeyboardLayoutVisitor {
Michael Wright8ebac232014-09-18 18:29:49 -07001726 void visitKeyboardLayout(Resources resources, String descriptor, String label,
1727 String collection, int keyboardLayoutResId, int priority);
Jeff Brown6ec6f792012-04-17 16:52:41 -07001728 }
1729
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001730 private final class InputDevicesChangedListenerRecord implements DeathRecipient {
1731 private final int mPid;
1732 private final IInputDevicesChangedListener mListener;
1733
1734 public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
1735 mPid = pid;
1736 mListener = listener;
1737 }
1738
1739 @Override
1740 public void binderDied() {
1741 if (DEBUG) {
1742 Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
1743 }
1744 onInputDevicesChangedListenerDied(mPid);
1745 }
1746
1747 public void notifyInputDevicesChanged(int[] info) {
1748 try {
1749 mListener.onInputDevicesChanged(info);
1750 } catch (RemoteException ex) {
1751 Slog.w(TAG, "Failed to notify process "
1752 + mPid + " that input devices changed, assuming it died.", ex);
1753 binderDied();
1754 }
1755 }
1756 }
Jeff Browna47425a2012-04-13 04:09:27 -07001757
1758 private final class VibratorToken implements DeathRecipient {
1759 public final int mDeviceId;
1760 public final IBinder mToken;
1761 public final int mTokenValue;
1762
1763 public boolean mVibrating;
1764
1765 public VibratorToken(int deviceId, IBinder token, int tokenValue) {
1766 mDeviceId = deviceId;
1767 mToken = token;
1768 mTokenValue = tokenValue;
1769 }
1770
1771 @Override
1772 public void binderDied() {
1773 if (DEBUG) {
1774 Slog.d(TAG, "Vibrator token died.");
1775 }
1776 onVibratorTokenDied(this);
1777 }
1778 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001779
1780 private final class LocalService extends InputManagerInternal {
1781 @Override
1782 public void setDisplayViewports(
1783 DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
1784 setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
1785 }
Jeff Brownca9bc702014-02-11 14:32:56 -08001786
1787 @Override
1788 public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
1789 return injectInputEventInternal(event, displayId, mode);
1790 }
Jeff Brown037c33e2014-04-09 00:31:55 -07001791
1792 @Override
1793 public void setInteractive(boolean interactive) {
1794 nativeSetInteractive(mPtr, interactive);
1795 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001796 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001797}