blob: 0f5805c857d64173ee9b9b913ae178672a12dd53 [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
238 /** Switch code: Headphone/Microphone Jack. When set, something is inserted. */
239 public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
240
241 public static final int SW_LID_BIT = 1 << SW_LID;
242 public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
243 public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
244 public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
245 public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
246 public static final int SW_JACK_BITS =
247 SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT;
248
249 /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
250 final boolean mUseDevInputEventForAudioJack;
251
Jeff Brown4ccb8232014-01-16 22:16:42 -0800252 public InputManagerService(Context context) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700253 this.mContext = context;
Jeff Brown4ccb8232014-01-16 22:16:42 -0800254 this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
Jeff Brown05dc66a2011-03-02 14:41:58 -0800255
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700256 mUseDevInputEventForAudioJack =
257 context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
258 Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
259 + mUseDevInputEventForAudioJack);
Jeff Brown4532e612012-04-05 14:27:12 -0700260 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
Jeff Brown4ccb8232014-01-16 22:16:42 -0800261
262 LocalServices.addService(InputManagerInternal.class, new LocalService());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700263 }
Jeff Brown1a84fd12011-06-02 01:26:32 -0700264
Jeff Browna9d131c2012-09-20 16:48:17 -0700265 public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
266 mWindowManagerCallbacks = callbacks;
267 }
268
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700269 public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) {
270 mWiredAccessoryCallbacks = callbacks;
271 }
272
Jeff Brown46b9ac02010-04-22 18:58:52 -0700273 public void start() {
274 Slog.i(TAG, "Starting input manager");
Jeff Brown4532e612012-04-05 14:27:12 -0700275 nativeStart(mPtr);
276
277 // Add ourself to the Watchdog monitors.
278 Watchdog.getInstance().addMonitor(this);
Jeff Brown1a84fd12011-06-02 01:26:32 -0700279
280 registerPointerSpeedSettingObserver();
Jeff Browndaf4a122011-08-26 17:14:14 -0700281 registerShowTouchesSettingObserver();
282
Jeff Brownd4935962012-09-25 13:27:20 -0700283 mContext.registerReceiver(new BroadcastReceiver() {
284 @Override
285 public void onReceive(Context context, Intent intent) {
286 updatePointerSpeedFromSettings();
287 updateShowTouchesFromSettings();
288 }
289 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
290
Jeff Brown1a84fd12011-06-02 01:26:32 -0700291 updatePointerSpeedFromSettings();
Jeff Browndaf4a122011-08-26 17:14:14 -0700292 updateShowTouchesFromSettings();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700293 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700294
Matthew Xie96313142012-06-29 16:57:31 -0700295 // TODO(BT) Pass in paramter for bluetooth system
Svetoslav Ganova0027152013-06-25 14:59:53 -0700296 public void systemRunning() {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700297 if (DEBUG) {
298 Slog.d(TAG, "System ready.");
299 }
Jeff Browncf39bdf2012-05-18 14:41:19 -0700300 mNotificationManager = (NotificationManager)mContext.getSystemService(
301 Context.NOTIFICATION_SERVICE);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700302 mSystemReady = true;
Jeff Brown6ec6f792012-04-17 16:52:41 -0700303
304 IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
305 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
306 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
Jeff Brown69b07162013-11-07 00:30:16 -0800307 filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700308 filter.addDataScheme("package");
309 mContext.registerReceiver(new BroadcastReceiver() {
310 @Override
311 public void onReceive(Context context, Intent intent) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700312 updateKeyboardLayouts();
Jeff Brown6ec6f792012-04-17 16:52:41 -0700313 }
314 }, filter, null, mHandler);
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700315
316 filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
317 mContext.registerReceiver(new BroadcastReceiver() {
318 @Override
319 public void onReceive(Context context, Intent intent) {
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700320 reloadDeviceAliases();
321 }
322 }, filter, null, mHandler);
323
Jeff Browncf39bdf2012-05-18 14:41:19 -0700324 mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
325 mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700326
327 if (mWiredAccessoryCallbacks != null) {
328 mWiredAccessoryCallbacks.systemReady();
329 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700330 }
331
332 private void reloadKeyboardLayouts() {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700333 if (DEBUG) {
334 Slog.d(TAG, "Reloading keyboard layouts.");
335 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700336 nativeReloadKeyboardLayouts(mPtr);
337 }
338
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700339 private void reloadDeviceAliases() {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700340 if (DEBUG) {
341 Slog.d(TAG, "Reloading device names.");
342 }
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700343 nativeReloadDeviceAliases(mPtr);
344 }
345
Jeff Brown4ccb8232014-01-16 22:16:42 -0800346 private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
Jeff Brownd728bf52012-09-08 18:05:28 -0700347 DisplayViewport externalTouchViewport) {
348 if (defaultViewport.valid) {
349 setDisplayViewport(false, defaultViewport);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700350 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700351
352 if (externalTouchViewport.valid) {
353 setDisplayViewport(true, externalTouchViewport);
354 } else if (defaultViewport.valid) {
355 setDisplayViewport(true, defaultViewport);
Jeff Brownb6997262010-10-08 22:31:17 -0700356 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700357 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700358
Jeff Brownd728bf52012-09-08 18:05:28 -0700359 private void setDisplayViewport(boolean external, DisplayViewport viewport) {
360 nativeSetDisplayViewport(mPtr, external,
361 viewport.displayId, viewport.orientation,
362 viewport.logicalFrame.left, viewport.logicalFrame.top,
363 viewport.logicalFrame.right, viewport.logicalFrame.bottom,
364 viewport.physicalFrame.left, viewport.physicalFrame.top,
Jeff Brown83d616a2012-09-09 20:33:43 -0700365 viewport.physicalFrame.right, viewport.physicalFrame.bottom,
366 viewport.deviceWidth, viewport.deviceHeight);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700367 }
Jeff Brownac143512012-04-05 18:57:33 -0700368
Jeff Brown6d0fec22010-07-23 21:28:06 -0700369 /**
370 * Gets the current state of a key or button by key code.
371 * @param deviceId The input device id, or -1 to consult all devices.
372 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
373 * consider all input sources. An input device is consulted if at least one of its
374 * non-class input source bits matches the specified source mask.
375 * @param keyCode The key code to check.
376 * @return The key state.
377 */
378 public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700379 return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700380 }
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700381
Jeff Brown6d0fec22010-07-23 21:28:06 -0700382 /**
383 * Gets the current state of a key or button by scan code.
384 * @param deviceId The input device id, or -1 to consult all devices.
385 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
386 * consider all input sources. An input device is consulted if at least one of its
387 * non-class input source bits matches the specified source mask.
388 * @param scanCode The scan code to check.
389 * @return The key state.
390 */
391 public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700392 return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700393 }
RoboErikfb290df2013-12-16 11:27:55 -0800394
Jeff Brown6d0fec22010-07-23 21:28:06 -0700395 /**
396 * Gets the current state of a switch by switch code.
397 * @param deviceId The input device id, or -1 to consult all devices.
398 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
399 * consider all input sources. An input device is consulted if at least one of its
400 * non-class input source bits matches the specified source mask.
401 * @param switchCode The switch code to check.
402 * @return The switch state.
403 */
404 public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700405 return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700406 }
407
Jeff Brown6d0fec22010-07-23 21:28:06 -0700408 /**
409 * Determines whether the specified key codes are supported by a particular device.
410 * @param deviceId The input device id, or -1 to consult all devices.
411 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
412 * consider all input sources. An input device is consulted if at least one of its
413 * non-class input source bits matches the specified source mask.
414 * @param keyCodes The array of key codes to check.
415 * @param keyExists An array at least as large as keyCodes whose entries will be set
416 * to true or false based on the presence or absence of support for the corresponding
417 * key codes.
418 * @return True if the lookup was successful, false otherwise.
419 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700420 @Override // Binder call
Jeff Brown6d0fec22010-07-23 21:28:06 -0700421 public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700422 if (keyCodes == null) {
423 throw new IllegalArgumentException("keyCodes must not be null.");
424 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700425 if (keyExists == null || keyExists.length < keyCodes.length) {
426 throw new IllegalArgumentException("keyExists must not be null and must be at "
427 + "least as large as keyCodes.");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700428 }
RoboErikfb290df2013-12-16 11:27:55 -0800429
Jeff Brown4532e612012-04-05 14:27:12 -0700430 return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700431 }
RoboErikfb290df2013-12-16 11:27:55 -0800432
Jeff Browna41ca772010-08-11 14:46:32 -0700433 /**
434 * Creates an input channel that will receive all input from the input dispatcher.
435 * @param inputChannelName The input channel name.
436 * @return The input channel.
437 */
438 public InputChannel monitorInput(String inputChannelName) {
439 if (inputChannelName == null) {
440 throw new IllegalArgumentException("inputChannelName must not be null.");
441 }
RoboErikfb290df2013-12-16 11:27:55 -0800442
Jeff Browna41ca772010-08-11 14:46:32 -0700443 InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
Jeff Brown4532e612012-04-05 14:27:12 -0700444 nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
Jeff Browna41ca772010-08-11 14:46:32 -0700445 inputChannels[0].dispose(); // don't need to retain the Java object reference
446 return inputChannels[1];
447 }
448
449 /**
450 * Registers an input channel so that it can be used as an input event target.
451 * @param inputChannel The input channel to register.
Jeff Brown928e0542011-01-10 11:17:36 -0800452 * @param inputWindowHandle The handle of the input window associated with the
453 * input channel, or null if none.
Jeff Browna41ca772010-08-11 14:46:32 -0700454 */
Jeff Brown928e0542011-01-10 11:17:36 -0800455 public void registerInputChannel(InputChannel inputChannel,
456 InputWindowHandle inputWindowHandle) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700457 if (inputChannel == null) {
458 throw new IllegalArgumentException("inputChannel must not be null.");
459 }
RoboErikfb290df2013-12-16 11:27:55 -0800460
Jeff Brown4532e612012-04-05 14:27:12 -0700461 nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700462 }
RoboErikfb290df2013-12-16 11:27:55 -0800463
Jeff Browna41ca772010-08-11 14:46:32 -0700464 /**
465 * Unregisters an input channel.
466 * @param inputChannel The input channel to unregister.
467 */
Jeff Brown46b9ac02010-04-22 18:58:52 -0700468 public void unregisterInputChannel(InputChannel inputChannel) {
469 if (inputChannel == null) {
470 throw new IllegalArgumentException("inputChannel must not be null.");
471 }
RoboErikfb290df2013-12-16 11:27:55 -0800472
Jeff Brown4532e612012-04-05 14:27:12 -0700473 nativeUnregisterInputChannel(mPtr, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700474 }
Jeff Brown0029c662011-03-30 02:25:18 -0700475
476 /**
477 * Sets an input filter that will receive all input events before they are dispatched.
478 * The input filter may then reinterpret input events or inject new ones.
479 *
480 * To ensure consistency, the input dispatcher automatically drops all events
481 * in progress whenever an input filter is installed or uninstalled. After an input
482 * filter is uninstalled, it can no longer send input events unless it is reinstalled.
483 * Any events it attempts to send after it has been uninstalled will be dropped.
484 *
485 * @param filter The input filter, or null to remove the current filter.
486 */
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700487 public void setInputFilter(IInputFilter filter) {
Jeff Brown0029c662011-03-30 02:25:18 -0700488 synchronized (mInputFilterLock) {
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700489 final IInputFilter oldFilter = mInputFilter;
Jeff Brown0029c662011-03-30 02:25:18 -0700490 if (oldFilter == filter) {
491 return; // nothing to do
492 }
493
494 if (oldFilter != null) {
495 mInputFilter = null;
496 mInputFilterHost.disconnectLocked();
497 mInputFilterHost = null;
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700498 try {
499 oldFilter.uninstall();
500 } catch (RemoteException re) {
501 /* ignore */
502 }
Jeff Brown0029c662011-03-30 02:25:18 -0700503 }
504
505 if (filter != null) {
506 mInputFilter = filter;
507 mInputFilterHost = new InputFilterHost();
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700508 try {
509 filter.install(mInputFilterHost);
510 } catch (RemoteException re) {
511 /* ignore */
512 }
Jeff Brown0029c662011-03-30 02:25:18 -0700513 }
514
Jeff Brown4532e612012-04-05 14:27:12 -0700515 nativeSetInputFilterEnabled(mPtr, filter != null);
Jeff Brown0029c662011-03-30 02:25:18 -0700516 }
517 }
518
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700519 @Override // Binder call
Jeff Brownac143512012-04-05 18:57:33 -0700520 public boolean injectInputEvent(InputEvent event, int mode) {
Jeff Brownca9bc702014-02-11 14:32:56 -0800521 return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
522 }
523
524 private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700525 if (event == null) {
526 throw new IllegalArgumentException("event must not be null");
527 }
Jeff Brownac143512012-04-05 18:57:33 -0700528 if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
529 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
530 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
531 throw new IllegalArgumentException("mode is invalid");
Jeff Brown7fbdc842010-06-17 20:52:56 -0700532 }
Jeff Brown6ec402b2010-07-28 15:48:59 -0700533
Jeff Brownac143512012-04-05 18:57:33 -0700534 final int pid = Binder.getCallingPid();
535 final int uid = Binder.getCallingUid();
536 final long ident = Binder.clearCallingIdentity();
537 final int result;
538 try {
Jeff Brownca9bc702014-02-11 14:32:56 -0800539 result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,
Jeff Brownac143512012-04-05 18:57:33 -0700540 INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
541 } finally {
542 Binder.restoreCallingIdentity(ident);
543 }
544 switch (result) {
545 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
546 Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
547 throw new SecurityException(
548 "Injecting to another application requires INJECT_EVENTS permission");
549 case INPUT_EVENT_INJECTION_SUCCEEDED:
550 return true;
551 case INPUT_EVENT_INJECTION_TIMED_OUT:
552 Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
553 return false;
554 case INPUT_EVENT_INJECTION_FAILED:
555 default:
556 Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
557 return false;
558 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700559 }
Jeff Brown0029c662011-03-30 02:25:18 -0700560
Jeff Brown8d608662010-08-30 03:02:23 -0700561 /**
562 * Gets information about the input device with the specified id.
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700563 * @param deviceId The device id.
Jeff Brown8d608662010-08-30 03:02:23 -0700564 * @return The input device or null if not found.
565 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700566 @Override // Binder call
Jeff Brown8d608662010-08-30 03:02:23 -0700567 public InputDevice getInputDevice(int deviceId) {
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700568 synchronized (mInputDevicesLock) {
569 final int count = mInputDevices.length;
570 for (int i = 0; i < count; i++) {
571 final InputDevice inputDevice = mInputDevices[i];
572 if (inputDevice.getId() == deviceId) {
573 return inputDevice;
574 }
575 }
576 }
577 return null;
Jeff Brown8d608662010-08-30 03:02:23 -0700578 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700579
Jeff Brown8d608662010-08-30 03:02:23 -0700580 /**
581 * Gets the ids of all input devices in the system.
582 * @return The input device ids.
583 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700584 @Override // Binder call
Jeff Brown8d608662010-08-30 03:02:23 -0700585 public int[] getInputDeviceIds() {
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700586 synchronized (mInputDevicesLock) {
587 final int count = mInputDevices.length;
588 int[] ids = new int[count];
589 for (int i = 0; i < count; i++) {
590 ids[i] = mInputDevices[i].getId();
591 }
592 return ids;
593 }
594 }
595
Jeff Browndaa37532012-05-01 15:54:03 -0700596 /**
597 * Gets all input devices in the system.
598 * @return The array of input devices.
599 */
600 public InputDevice[] getInputDevices() {
601 synchronized (mInputDevicesLock) {
602 return mInputDevices;
603 }
604 }
605
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700606 @Override // Binder call
607 public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
608 if (listener == null) {
609 throw new IllegalArgumentException("listener must not be null");
610 }
611
612 synchronized (mInputDevicesLock) {
613 int callingPid = Binder.getCallingPid();
614 if (mInputDevicesChangedListeners.get(callingPid) != null) {
615 throw new SecurityException("The calling process has already "
616 + "registered an InputDevicesChangedListener.");
617 }
618
619 InputDevicesChangedListenerRecord record =
620 new InputDevicesChangedListenerRecord(callingPid, listener);
621 try {
622 IBinder binder = listener.asBinder();
623 binder.linkToDeath(record, 0);
624 } catch (RemoteException ex) {
625 // give up
626 throw new RuntimeException(ex);
627 }
628
629 mInputDevicesChangedListeners.put(callingPid, record);
630 }
631 }
632
633 private void onInputDevicesChangedListenerDied(int pid) {
634 synchronized (mInputDevicesLock) {
635 mInputDevicesChangedListeners.remove(pid);
636 }
637 }
638
639 // Must be called on handler.
Jeff Browncf39bdf2012-05-18 14:41:19 -0700640 private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) {
641 // Scan for changes.
642 int numFullKeyboardsAdded = 0;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700643 mTempInputDevicesChangedListenersToNotify.clear();
Jeff Browncf39bdf2012-05-18 14:41:19 -0700644 mTempFullKeyboards.clear();
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700645 final int numListeners;
646 final int[] deviceIdAndGeneration;
647 synchronized (mInputDevicesLock) {
648 if (!mInputDevicesChangedPending) {
649 return;
650 }
651 mInputDevicesChangedPending = false;
652
653 numListeners = mInputDevicesChangedListeners.size();
654 for (int i = 0; i < numListeners; i++) {
655 mTempInputDevicesChangedListenersToNotify.add(
656 mInputDevicesChangedListeners.valueAt(i));
657 }
658
659 final int numDevices = mInputDevices.length;
660 deviceIdAndGeneration = new int[numDevices * 2];
661 for (int i = 0; i < numDevices; i++) {
662 final InputDevice inputDevice = mInputDevices[i];
663 deviceIdAndGeneration[i * 2] = inputDevice.getId();
664 deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
Jeff Browncf39bdf2012-05-18 14:41:19 -0700665
Jeff Brown7e4ff4b2012-05-30 14:32:16 -0700666 if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700667 if (!containsInputDeviceWithDescriptor(oldInputDevices,
668 inputDevice.getDescriptor())) {
669 mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice);
670 } else {
671 mTempFullKeyboards.add(inputDevice);
672 }
673 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700674 }
675 }
676
Jeff Browncf39bdf2012-05-18 14:41:19 -0700677 // Notify listeners.
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700678 for (int i = 0; i < numListeners; i++) {
679 mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged(
680 deviceIdAndGeneration);
681 }
Jeff Browncf39bdf2012-05-18 14:41:19 -0700682 mTempInputDevicesChangedListenersToNotify.clear();
683
684 // Check for missing keyboard layouts.
685 if (mNotificationManager != null) {
686 final int numFullKeyboards = mTempFullKeyboards.size();
687 boolean missingLayoutForExternalKeyboard = false;
688 boolean missingLayoutForExternalKeyboardAdded = false;
689 synchronized (mDataStore) {
690 for (int i = 0; i < numFullKeyboards; i++) {
691 final InputDevice inputDevice = mTempFullKeyboards.get(i);
692 if (mDataStore.getCurrentKeyboardLayout(inputDevice.getDescriptor()) == null) {
693 missingLayoutForExternalKeyboard = true;
694 if (i < numFullKeyboardsAdded) {
695 missingLayoutForExternalKeyboardAdded = true;
696 }
697 }
698 }
699 }
700 if (missingLayoutForExternalKeyboard) {
701 if (missingLayoutForExternalKeyboardAdded) {
702 showMissingKeyboardLayoutNotification();
703 }
704 } else if (mKeyboardLayoutNotificationShown) {
705 hideMissingKeyboardLayoutNotification();
706 }
707 }
708 mTempFullKeyboards.clear();
709 }
710
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800711 @Override // Binder call & native callback
Jason Gerecked5220742014-03-10 09:47:59 -0700712 public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
713 int surfaceRotation) {
Jason Gerecked6396d62014-01-27 18:30:37 -0800714 if (inputDeviceDescriptor == null) {
715 throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
716 }
717
718 synchronized (mDataStore) {
Jason Gerecked5220742014-03-10 09:47:59 -0700719 return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
Jason Gerecked6396d62014-01-27 18:30:37 -0800720 }
721 }
722
723 @Override // Binder call
Jason Gerecked5220742014-03-10 09:47:59 -0700724 public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
Jason Gerecked6396d62014-01-27 18:30:37 -0800725 TouchCalibration calibration) {
726 if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
727 "setTouchCalibrationForInputDevice()")) {
728 throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
729 }
730 if (inputDeviceDescriptor == null) {
731 throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
732 }
733 if (calibration == null) {
734 throw new IllegalArgumentException("calibration must not be null");
735 }
Jason Gerecked5220742014-03-10 09:47:59 -0700736 if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
737 throw new IllegalArgumentException("surfaceRotation value out of bounds");
738 }
Jason Gerecked6396d62014-01-27 18:30:37 -0800739
740 synchronized (mDataStore) {
741 try {
Jason Gerecked5220742014-03-10 09:47:59 -0700742 if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
743 calibration)) {
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800744 nativeReloadCalibration(mPtr);
745 }
Jason Gerecked6396d62014-01-27 18:30:37 -0800746 } finally {
747 mDataStore.saveIfNeeded();
748 }
749 }
750 }
751
Jeff Browncf39bdf2012-05-18 14:41:19 -0700752 // Must be called on handler.
753 private void showMissingKeyboardLayoutNotification() {
754 if (!mKeyboardLayoutNotificationShown) {
755 if (mKeyboardLayoutIntent == null) {
756 final Intent intent = new Intent("android.settings.INPUT_METHOD_SETTINGS");
757 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
758 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
759 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700760 mKeyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
761 intent, 0, null, UserHandle.CURRENT);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700762 }
763
764 Resources r = mContext.getResources();
765 Notification notification = new Notification.Builder(mContext)
766 .setContentTitle(r.getString(
767 R.string.select_keyboard_layout_notification_title))
768 .setContentText(r.getString(
769 R.string.select_keyboard_layout_notification_message))
770 .setContentIntent(mKeyboardLayoutIntent)
771 .setSmallIcon(R.drawable.ic_settings_language)
772 .setPriority(Notification.PRIORITY_LOW)
773 .build();
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700774 mNotificationManager.notifyAsUser(null,
775 R.string.select_keyboard_layout_notification_title,
776 notification, UserHandle.ALL);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700777 mKeyboardLayoutNotificationShown = true;
778 }
779 }
780
781 // Must be called on handler.
782 private void hideMissingKeyboardLayoutNotification() {
783 if (mKeyboardLayoutNotificationShown) {
784 mKeyboardLayoutNotificationShown = false;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700785 mNotificationManager.cancelAsUser(null,
786 R.string.select_keyboard_layout_notification_title,
787 UserHandle.ALL);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700788 }
789 }
790
791 // Must be called on handler.
792 private void updateKeyboardLayouts() {
793 // Scan all input devices state for keyboard layouts that have been uninstalled.
794 final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
795 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
796 @Override
797 public void visitKeyboardLayout(Resources resources,
798 String descriptor, String label, String collection, int keyboardLayoutResId) {
799 availableKeyboardLayouts.add(descriptor);
800 }
801 });
802 synchronized (mDataStore) {
803 try {
804 mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
805 } finally {
806 mDataStore.saveIfNeeded();
807 }
808 }
809
810 // Reload keyboard layouts.
811 reloadKeyboardLayouts();
812 }
813
Jeff Browncf39bdf2012-05-18 14:41:19 -0700814 private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices,
815 String descriptor) {
816 final int numDevices = inputDevices.length;
817 for (int i = 0; i < numDevices; i++) {
818 final InputDevice inputDevice = inputDevices[i];
819 if (inputDevice.getDescriptor().equals(descriptor)) {
820 return true;
821 }
822 }
823 return false;
Jeff Brown8d608662010-08-30 03:02:23 -0700824 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700825
826 @Override // Binder call
827 public KeyboardLayout[] getKeyboardLayouts() {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700828 final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
829 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
830 @Override
831 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700832 String descriptor, String label, String collection, int keyboardLayoutResId) {
833 list.add(new KeyboardLayout(descriptor, label, collection));
Jeff Brown6ec6f792012-04-17 16:52:41 -0700834 }
835 });
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700836 return list.toArray(new KeyboardLayout[list.size()]);
837 }
838
839 @Override // Binder call
840 public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
841 if (keyboardLayoutDescriptor == null) {
842 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
843 }
844
Jeff Brown6ec6f792012-04-17 16:52:41 -0700845 final KeyboardLayout[] result = new KeyboardLayout[1];
846 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
847 @Override
848 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700849 String descriptor, String label, String collection, int keyboardLayoutResId) {
850 result[0] = new KeyboardLayout(descriptor, label, collection);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700851 }
852 });
853 if (result[0] == null) {
854 Log.w(TAG, "Could not get keyboard layout with descriptor '"
855 + keyboardLayoutDescriptor + "'.");
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700856 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700857 return result[0];
858 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700859
Jeff Brown6ec6f792012-04-17 16:52:41 -0700860 private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700861 final PackageManager pm = mContext.getPackageManager();
Jeff Brown6ec6f792012-04-17 16:52:41 -0700862 Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
863 for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
864 PackageManager.GET_META_DATA)) {
865 visitKeyboardLayoutsInPackage(pm, resolveInfo.activityInfo, null, visitor);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700866 }
867 }
868
Jeff Brown6ec6f792012-04-17 16:52:41 -0700869 private void visitKeyboardLayout(String keyboardLayoutDescriptor,
870 KeyboardLayoutVisitor visitor) {
871 KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor);
872 if (d != null) {
873 final PackageManager pm = mContext.getPackageManager();
874 try {
875 ActivityInfo receiver = pm.getReceiverInfo(
876 new ComponentName(d.packageName, d.receiverName),
877 PackageManager.GET_META_DATA);
878 visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, visitor);
879 } catch (NameNotFoundException ex) {
880 }
881 }
882 }
883
884 private void visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver,
885 String keyboardName, KeyboardLayoutVisitor visitor) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700886 Bundle metaData = receiver.metaData;
887 if (metaData == null) {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700888 return;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700889 }
890
891 int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS);
892 if (configResId == 0) {
893 Log.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
894 + "' on receiver " + receiver.packageName + "/" + receiver.name);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700895 return;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700896 }
897
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700898 CharSequence receiverLabel = receiver.loadLabel(pm);
899 String collection = receiverLabel != null ? receiverLabel.toString() : "";
900
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700901 try {
902 Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
903 XmlResourceParser parser = resources.getXml(configResId);
904 try {
905 XmlUtils.beginDocument(parser, "keyboard-layouts");
906
907 for (;;) {
908 XmlUtils.nextElement(parser);
909 String element = parser.getName();
910 if (element == null) {
911 break;
912 }
913 if (element.equals("keyboard-layout")) {
914 TypedArray a = resources.obtainAttributes(
915 parser, com.android.internal.R.styleable.KeyboardLayout);
916 try {
917 String name = a.getString(
918 com.android.internal.R.styleable.KeyboardLayout_name);
919 String label = a.getString(
920 com.android.internal.R.styleable.KeyboardLayout_label);
Jeff Brown2f095762012-05-10 21:29:33 -0700921 int keyboardLayoutResId = a.getResourceId(
922 com.android.internal.R.styleable.KeyboardLayout_keyboardLayout,
923 0);
924 if (name == null || label == null || keyboardLayoutResId == 0) {
925 Log.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700926 + "attributes in keyboard layout "
927 + "resource from receiver "
928 + receiver.packageName + "/" + receiver.name);
929 } else {
930 String descriptor = KeyboardLayoutDescriptor.format(
931 receiver.packageName, receiver.name, name);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700932 if (keyboardName == null || name.equals(keyboardName)) {
933 visitor.visitKeyboardLayout(resources, descriptor,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700934 label, collection, keyboardLayoutResId);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700935 }
936 }
937 } finally {
938 a.recycle();
939 }
940 } else {
941 Log.w(TAG, "Skipping unrecognized element '" + element
942 + "' in keyboard layout resource from receiver "
943 + receiver.packageName + "/" + receiver.name);
944 }
945 }
946 } finally {
947 parser.close();
948 }
949 } catch (Exception ex) {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700950 Log.w(TAG, "Could not parse keyboard layout resource from receiver "
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700951 + receiver.packageName + "/" + receiver.name, ex);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700952 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700953 }
954
RoboErikfb290df2013-12-16 11:27:55 -0800955 /**
956 * Builds a layout descriptor for the vendor/product. This returns the
957 * descriptor for ids that aren't useful (such as the default 0, 0).
958 */
959 private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
960 if (identifier == null || identifier.getDescriptor() == null) {
961 throw new IllegalArgumentException("identifier and descriptor must not be null");
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700962 }
963
RoboErikfb290df2013-12-16 11:27:55 -0800964 if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
965 return identifier.getDescriptor();
966 }
967 StringBuilder bob = new StringBuilder();
968 bob.append("vendor:").append(identifier.getVendorId());
969 bob.append(",product:").append(identifier.getProductId());
970 return bob.toString();
971 }
972
973 @Override // Binder call
974 public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
975
976 String key = getLayoutDescriptor(identifier);
Jeff Browna3bc5652012-04-17 11:42:25 -0700977 synchronized (mDataStore) {
RoboErikfb290df2013-12-16 11:27:55 -0800978 String layout = null;
979 // try loading it using the layout descriptor if we have it
980 layout = mDataStore.getCurrentKeyboardLayout(key);
981 if (layout == null && !key.equals(identifier.getDescriptor())) {
982 // if it doesn't exist fall back to the device descriptor
983 layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
984 }
985 if (DEBUG) {
986 Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got "
987 + layout);
988 }
989 return layout;
Jeff Browna3bc5652012-04-17 11:42:25 -0700990 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700991 }
992
993 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -0800994 public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700995 String keyboardLayoutDescriptor) {
996 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
Jeff Browncf39bdf2012-05-18 14:41:19 -0700997 "setCurrentKeyboardLayoutForInputDevice()")) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700998 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
999 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001000 if (keyboardLayoutDescriptor == null) {
1001 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1002 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001003
RoboErikfb290df2013-12-16 11:27:55 -08001004 String key = getLayoutDescriptor(identifier);
Jeff Browna3bc5652012-04-17 11:42:25 -07001005 synchronized (mDataStore) {
1006 try {
RoboErikfb290df2013-12-16 11:27:55 -08001007 if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
1008 if (DEBUG) {
1009 Slog.d(TAG, "Saved keyboard layout using " + key);
1010 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001011 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1012 }
Jeff Browna3bc5652012-04-17 11:42:25 -07001013 } finally {
1014 mDataStore.saveIfNeeded();
1015 }
1016 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001017 }
Jeff Brown6ec6f792012-04-17 16:52:41 -07001018
Jeff Browncf39bdf2012-05-18 14:41:19 -07001019 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001020 public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
1021 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001022 synchronized (mDataStore) {
RoboErikfb290df2013-12-16 11:27:55 -08001023 String[] layouts = mDataStore.getKeyboardLayouts(key);
1024 if ((layouts == null || layouts.length == 0)
1025 && !key.equals(identifier.getDescriptor())) {
1026 layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
1027 }
1028 return layouts;
Jeff Browncf39bdf2012-05-18 14:41:19 -07001029 }
1030 }
1031
1032 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001033 public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001034 String keyboardLayoutDescriptor) {
1035 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1036 "addKeyboardLayoutForInputDevice()")) {
1037 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1038 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001039 if (keyboardLayoutDescriptor == null) {
1040 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1041 }
1042
RoboErikfb290df2013-12-16 11:27:55 -08001043 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001044 synchronized (mDataStore) {
1045 try {
RoboErikfb290df2013-12-16 11:27:55 -08001046 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1047 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1048 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1049 }
1050 if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
Jeff Browncf39bdf2012-05-18 14:41:19 -07001051 && !Objects.equal(oldLayout,
RoboErikfb290df2013-12-16 11:27:55 -08001052 mDataStore.getCurrentKeyboardLayout(key))) {
Jeff Browncf39bdf2012-05-18 14:41:19 -07001053 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1054 }
1055 } finally {
1056 mDataStore.saveIfNeeded();
Jeff Brown6ec6f792012-04-17 16:52:41 -07001057 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001058 }
1059 }
1060
1061 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001062 public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001063 String keyboardLayoutDescriptor) {
1064 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1065 "removeKeyboardLayoutForInputDevice()")) {
1066 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1067 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001068 if (keyboardLayoutDescriptor == null) {
1069 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1070 }
1071
RoboErikfb290df2013-12-16 11:27:55 -08001072 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001073 synchronized (mDataStore) {
1074 try {
RoboErikfb290df2013-12-16 11:27:55 -08001075 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1076 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1077 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1078 }
1079 boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
1080 if (!key.equals(identifier.getDescriptor())) {
1081 // We need to remove from both places to ensure it is gone
1082 removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
1083 keyboardLayoutDescriptor);
1084 }
1085 if (removed && !Objects.equal(oldLayout,
1086 mDataStore.getCurrentKeyboardLayout(key))) {
Jeff Browncf39bdf2012-05-18 14:41:19 -07001087 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1088 }
1089 } finally {
1090 mDataStore.saveIfNeeded();
1091 }
1092 }
1093 }
1094
1095 public void switchKeyboardLayout(int deviceId, int direction) {
1096 mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
1097 }
1098
1099 // Must be called on handler.
1100 private void handleSwitchKeyboardLayout(int deviceId, int direction) {
1101 final InputDevice device = getInputDevice(deviceId);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001102 if (device != null) {
1103 final boolean changed;
1104 final String keyboardLayoutDescriptor;
RoboErikfb290df2013-12-16 11:27:55 -08001105
1106 String key = getLayoutDescriptor(device.getIdentifier());
Jeff Browncf39bdf2012-05-18 14:41:19 -07001107 synchronized (mDataStore) {
1108 try {
RoboErikfb290df2013-12-16 11:27:55 -08001109 changed = mDataStore.switchKeyboardLayout(key, direction);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001110 keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
RoboErikfb290df2013-12-16 11:27:55 -08001111 key);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001112 } finally {
1113 mDataStore.saveIfNeeded();
1114 }
1115 }
1116
1117 if (changed) {
1118 if (mSwitchedKeyboardLayoutToast != null) {
1119 mSwitchedKeyboardLayoutToast.cancel();
1120 mSwitchedKeyboardLayoutToast = null;
1121 }
1122 if (keyboardLayoutDescriptor != null) {
1123 KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
1124 if (keyboardLayout != null) {
1125 mSwitchedKeyboardLayoutToast = Toast.makeText(
1126 mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
1127 mSwitchedKeyboardLayoutToast.show();
1128 }
1129 }
1130
1131 reloadKeyboardLayouts();
1132 }
Jeff Brown6ec6f792012-04-17 16:52:41 -07001133 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001134 }
1135
Jeff Brown9302c872011-07-13 22:51:29 -07001136 public void setInputWindows(InputWindowHandle[] windowHandles) {
Jeff Brown4532e612012-04-05 14:27:12 -07001137 nativeSetInputWindows(mPtr, windowHandles);
Jeff Brown349703e2010-06-22 01:27:15 -07001138 }
RoboErikfb290df2013-12-16 11:27:55 -08001139
Jeff Brown9302c872011-07-13 22:51:29 -07001140 public void setFocusedApplication(InputApplicationHandle application) {
Jeff Brown4532e612012-04-05 14:27:12 -07001141 nativeSetFocusedApplication(mPtr, application);
Jeff Brown349703e2010-06-22 01:27:15 -07001142 }
RoboErikfb290df2013-12-16 11:27:55 -08001143
Jeff Brown349703e2010-06-22 01:27:15 -07001144 public void setInputDispatchMode(boolean enabled, boolean frozen) {
Jeff Brown4532e612012-04-05 14:27:12 -07001145 nativeSetInputDispatchMode(mPtr, enabled, frozen);
Jeff Brown349703e2010-06-22 01:27:15 -07001146 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001147
1148 public void setSystemUiVisibility(int visibility) {
Jeff Brown4532e612012-04-05 14:27:12 -07001149 nativeSetSystemUiVisibility(mPtr, visibility);
Jeff Brown05dc66a2011-03-02 14:41:58 -08001150 }
1151
Jeff Browne6504122010-09-27 14:52:15 -07001152 /**
1153 * Atomically transfers touch focus from one window to another as identified by
1154 * their input channels. It is possible for multiple windows to have
1155 * touch focus if they support split touch dispatch
1156 * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
1157 * method only transfers touch focus of the specified window without affecting
1158 * other windows that may also have touch focus at the same time.
1159 * @param fromChannel The channel of a window that currently has touch focus.
1160 * @param toChannel The channel of the window that should receive touch focus in
1161 * place of the first.
1162 * @return True if the transfer was successful. False if the window with the
1163 * specified channel did not actually have touch focus at the time of the request.
1164 */
1165 public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
1166 if (fromChannel == null) {
1167 throw new IllegalArgumentException("fromChannel must not be null.");
1168 }
1169 if (toChannel == null) {
1170 throw new IllegalArgumentException("toChannel must not be null.");
1171 }
Jeff Brown4532e612012-04-05 14:27:12 -07001172 return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
Jeff Browne6504122010-09-27 14:52:15 -07001173 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001174
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001175 @Override // Binder call
Jeff Brownac143512012-04-05 18:57:33 -07001176 public void tryPointerSpeed(int speed) {
1177 if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
1178 "tryPointerSpeed()")) {
1179 throw new SecurityException("Requires SET_POINTER_SPEED permission");
1180 }
1181
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001182 if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) {
1183 throw new IllegalArgumentException("speed out of range");
1184 }
1185
Jeff Brownac143512012-04-05 18:57:33 -07001186 setPointerSpeedUnchecked(speed);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001187 }
1188
1189 public void updatePointerSpeedFromSettings() {
Jeff Brownac143512012-04-05 18:57:33 -07001190 int speed = getPointerSpeedSetting();
1191 setPointerSpeedUnchecked(speed);
1192 }
1193
1194 private void setPointerSpeedUnchecked(int speed) {
1195 speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
1196 InputManager.MAX_POINTER_SPEED);
1197 nativeSetPointerSpeed(mPtr, speed);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001198 }
1199
1200 private void registerPointerSpeedSettingObserver() {
1201 mContext.getContentResolver().registerContentObserver(
1202 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
Jeff Brown4532e612012-04-05 14:27:12 -07001203 new ContentObserver(mHandler) {
Jeff Brown1a84fd12011-06-02 01:26:32 -07001204 @Override
1205 public void onChange(boolean selfChange) {
1206 updatePointerSpeedFromSettings();
1207 }
Jeff Brownd4935962012-09-25 13:27:20 -07001208 }, UserHandle.USER_ALL);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001209 }
1210
Jeff Brownac143512012-04-05 18:57:33 -07001211 private int getPointerSpeedSetting() {
1212 int speed = InputManager.DEFAULT_POINTER_SPEED;
Jeff Brown1a84fd12011-06-02 01:26:32 -07001213 try {
Jeff Brownd4935962012-09-25 13:27:20 -07001214 speed = Settings.System.getIntForUser(mContext.getContentResolver(),
1215 Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001216 } catch (SettingNotFoundException snfe) {
1217 }
1218 return speed;
1219 }
1220
Jeff Browndaf4a122011-08-26 17:14:14 -07001221 public void updateShowTouchesFromSettings() {
1222 int setting = getShowTouchesSetting(0);
Jeff Brown4532e612012-04-05 14:27:12 -07001223 nativeSetShowTouches(mPtr, setting != 0);
Jeff Browndaf4a122011-08-26 17:14:14 -07001224 }
1225
1226 private void registerShowTouchesSettingObserver() {
1227 mContext.getContentResolver().registerContentObserver(
1228 Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
Jeff Brown4532e612012-04-05 14:27:12 -07001229 new ContentObserver(mHandler) {
Jeff Browndaf4a122011-08-26 17:14:14 -07001230 @Override
1231 public void onChange(boolean selfChange) {
1232 updateShowTouchesFromSettings();
1233 }
Jeff Brownd4935962012-09-25 13:27:20 -07001234 }, UserHandle.USER_ALL);
Jeff Browndaf4a122011-08-26 17:14:14 -07001235 }
1236
1237 private int getShowTouchesSetting(int defaultValue) {
1238 int result = defaultValue;
1239 try {
Jeff Brownd4935962012-09-25 13:27:20 -07001240 result = Settings.System.getIntForUser(mContext.getContentResolver(),
1241 Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
Jeff Browndaf4a122011-08-26 17:14:14 -07001242 } catch (SettingNotFoundException snfe) {
1243 }
1244 return result;
1245 }
1246
Jeff Browna47425a2012-04-13 04:09:27 -07001247 // Binder call
1248 @Override
1249 public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {
1250 if (repeat >= pattern.length) {
1251 throw new ArrayIndexOutOfBoundsException();
1252 }
1253
1254 VibratorToken v;
1255 synchronized (mVibratorLock) {
1256 v = mVibratorTokens.get(token);
1257 if (v == null) {
1258 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);
1259 try {
1260 token.linkToDeath(v, 0);
1261 } catch (RemoteException ex) {
1262 // give up
1263 throw new RuntimeException(ex);
1264 }
1265 mVibratorTokens.put(token, v);
1266 }
1267 }
1268
1269 synchronized (v) {
1270 v.mVibrating = true;
1271 nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue);
1272 }
1273 }
1274
1275 // Binder call
1276 @Override
1277 public void cancelVibrate(int deviceId, IBinder token) {
1278 VibratorToken v;
1279 synchronized (mVibratorLock) {
1280 v = mVibratorTokens.get(token);
1281 if (v == null || v.mDeviceId != deviceId) {
1282 return; // nothing to cancel
1283 }
1284 }
1285
1286 cancelVibrateIfNeeded(v);
1287 }
1288
1289 void onVibratorTokenDied(VibratorToken v) {
1290 synchronized (mVibratorLock) {
1291 mVibratorTokens.remove(v.mToken);
1292 }
1293
1294 cancelVibrateIfNeeded(v);
1295 }
1296
1297 private void cancelVibrateIfNeeded(VibratorToken v) {
1298 synchronized (v) {
1299 if (v.mVibrating) {
1300 nativeCancelVibrate(mPtr, v.mDeviceId, v.mTokenValue);
1301 v.mVibrating = false;
1302 }
1303 }
1304 }
1305
Jeff Brown4532e612012-04-05 14:27:12 -07001306 @Override
1307 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Browna3bc5652012-04-17 11:42:25 -07001308 if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
Jeff Brown4532e612012-04-05 14:27:12 -07001309 != PackageManager.PERMISSION_GRANTED) {
1310 pw.println("Permission Denial: can't dump InputManager from from pid="
1311 + Binder.getCallingPid()
1312 + ", uid=" + Binder.getCallingUid());
1313 return;
1314 }
1315
1316 pw.println("INPUT MANAGER (dumpsys input)\n");
1317 String dumpStr = nativeDump(mPtr);
Jeff Browne33348b2010-07-15 23:54:05 -07001318 if (dumpStr != null) {
1319 pw.println(dumpStr);
1320 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001321 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001322
Jeff Brownac143512012-04-05 18:57:33 -07001323 private boolean checkCallingPermission(String permission, String func) {
1324 // Quick check: if the calling permission is me, it's all okay.
1325 if (Binder.getCallingPid() == Process.myPid()) {
1326 return true;
1327 }
1328
1329 if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
1330 return true;
1331 }
1332 String msg = "Permission Denial: " + func + " from pid="
1333 + Binder.getCallingPid()
1334 + ", uid=" + Binder.getCallingUid()
1335 + " requires " + permission;
1336 Slog.w(TAG, msg);
1337 return false;
1338 }
1339
Jeff Brown4532e612012-04-05 14:27:12 -07001340 // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001341 @Override
Jeff Brown89ef0722011-08-10 16:25:21 -07001342 public void monitor() {
1343 synchronized (mInputFilterLock) { }
Jeff Brown4532e612012-04-05 14:27:12 -07001344 nativeMonitor(mPtr);
Jeff Brown89ef0722011-08-10 16:25:21 -07001345 }
1346
Jeff Brown4532e612012-04-05 14:27:12 -07001347 // Native callback.
1348 private void notifyConfigurationChanged(long whenNanos) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001349 mWindowManagerCallbacks.notifyConfigurationChanged();
Jeff Brown4532e612012-04-05 14:27:12 -07001350 }
1351
1352 // Native callback.
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001353 private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
1354 synchronized (mInputDevicesLock) {
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001355 if (!mInputDevicesChangedPending) {
1356 mInputDevicesChangedPending = true;
Jeff Browncf39bdf2012-05-18 14:41:19 -07001357 mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED,
1358 mInputDevices).sendToTarget();
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001359 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001360
1361 mInputDevices = inputDevices;
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001362 }
1363 }
1364
1365 // Native callback.
Jeff Brownbcc046a2012-09-27 20:46:43 -07001366 private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
1367 if (DEBUG) {
1368 Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
1369 + ", mask=" + Integer.toHexString(switchMask));
1370 }
1371
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001372 if ((switchMask & SW_LID_BIT) != 0) {
1373 final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
Jeff Brownbcc046a2012-09-27 20:46:43 -07001374 mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
Jeff Brown53384282012-08-20 20:16:01 -07001375 }
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001376
1377 if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
1378 mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
1379 switchMask);
1380 }
Jeff Brown4532e612012-04-05 14:27:12 -07001381 }
1382
1383 // Native callback.
1384 private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001385 mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
Jeff Brown4532e612012-04-05 14:27:12 -07001386 }
1387
1388 // Native callback.
1389 private long notifyANR(InputApplicationHandle inputApplicationHandle,
Jeff Brownbd181bb2013-09-10 16:44:24 -07001390 InputWindowHandle inputWindowHandle, String reason) {
1391 return mWindowManagerCallbacks.notifyANR(
1392 inputApplicationHandle, inputWindowHandle, reason);
Jeff Brown4532e612012-04-05 14:27:12 -07001393 }
1394
1395 // Native callback.
1396 final boolean filterInputEvent(InputEvent event, int policyFlags) {
1397 synchronized (mInputFilterLock) {
1398 if (mInputFilter != null) {
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001399 try {
1400 mInputFilter.filterInputEvent(event, policyFlags);
1401 } catch (RemoteException e) {
1402 /* ignore */
1403 }
Jeff Brown4532e612012-04-05 14:27:12 -07001404 return false;
1405 }
1406 }
1407 event.recycle();
1408 return true;
1409 }
1410
1411 // Native callback.
Jeff Brown037c33e2014-04-09 00:31:55 -07001412 private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1413 return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001414 }
1415
1416 // Native callback.
Jeff Brown037c33e2014-04-09 00:31:55 -07001417 private int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
1418 return mWindowManagerCallbacks.interceptWakeMotionBeforeQueueing(
Jeff Brown26875502014-01-30 21:47:47 -08001419 whenNanos, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001420 }
1421
1422 // Native callback.
1423 private long interceptKeyBeforeDispatching(InputWindowHandle focus,
1424 KeyEvent event, int policyFlags) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001425 return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001426 }
1427
1428 // Native callback.
1429 private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1430 KeyEvent event, int policyFlags) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001431 return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001432 }
1433
1434 // Native callback.
1435 private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
1436 return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
1437 injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
1438 }
1439
1440 // Native callback.
1441 private int getVirtualKeyQuietTimeMillis() {
1442 return mContext.getResources().getInteger(
1443 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
1444 }
1445
1446 // Native callback.
1447 private String[] getExcludedDeviceNames() {
1448 ArrayList<String> names = new ArrayList<String>();
1449
1450 // Read partner-provided list of excluded input devices
1451 XmlPullParser parser = null;
1452 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
1453 File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
1454 FileReader confreader = null;
1455 try {
1456 confreader = new FileReader(confFile);
1457 parser = Xml.newPullParser();
1458 parser.setInput(confreader);
1459 XmlUtils.beginDocument(parser, "devices");
1460
1461 while (true) {
1462 XmlUtils.nextElement(parser);
1463 if (!"device".equals(parser.getName())) {
1464 break;
1465 }
1466 String name = parser.getAttributeValue(null, "name");
1467 if (name != null) {
1468 names.add(name);
1469 }
1470 }
1471 } catch (FileNotFoundException e) {
1472 // It's ok if the file does not exist.
1473 } catch (Exception e) {
1474 Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
1475 } finally {
1476 try { if (confreader != null) confreader.close(); } catch (IOException e) { }
1477 }
1478
1479 return names.toArray(new String[names.size()]);
1480 }
1481
1482 // Native callback.
1483 private int getKeyRepeatTimeout() {
1484 return ViewConfiguration.getKeyRepeatTimeout();
1485 }
1486
1487 // Native callback.
1488 private int getKeyRepeatDelay() {
1489 return ViewConfiguration.getKeyRepeatDelay();
1490 }
1491
1492 // Native callback.
1493 private int getHoverTapTimeout() {
1494 return ViewConfiguration.getHoverTapTimeout();
1495 }
1496
1497 // Native callback.
1498 private int getHoverTapSlop() {
1499 return ViewConfiguration.getHoverTapSlop();
1500 }
1501
1502 // Native callback.
1503 private int getDoubleTapTimeout() {
1504 return ViewConfiguration.getDoubleTapTimeout();
1505 }
1506
1507 // Native callback.
1508 private int getLongPressTimeout() {
1509 return ViewConfiguration.getLongPressTimeout();
1510 }
1511
1512 // Native callback.
1513 private int getPointerLayer() {
Jeff Browna9d131c2012-09-20 16:48:17 -07001514 return mWindowManagerCallbacks.getPointerLayer();
Jeff Brown4532e612012-04-05 14:27:12 -07001515 }
1516
1517 // Native callback.
1518 private PointerIcon getPointerIcon() {
1519 return PointerIcon.getDefaultIcon(mContext);
1520 }
1521
Jeff Brown6ec6f792012-04-17 16:52:41 -07001522 // Native callback.
RoboErikfb290df2013-12-16 11:27:55 -08001523 private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
Jeff Brown6ec6f792012-04-17 16:52:41 -07001524 if (!mSystemReady) {
1525 return null;
1526 }
1527
RoboErikfb290df2013-12-16 11:27:55 -08001528 String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
Jeff Brown6ec6f792012-04-17 16:52:41 -07001529 if (keyboardLayoutDescriptor == null) {
1530 return null;
1531 }
1532
1533 final String[] result = new String[2];
1534 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
1535 @Override
1536 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -07001537 String descriptor, String label, String collection, int keyboardLayoutResId) {
Jeff Brown6ec6f792012-04-17 16:52:41 -07001538 try {
1539 result[0] = descriptor;
1540 result[1] = Streams.readFully(new InputStreamReader(
Jeff Brown2f095762012-05-10 21:29:33 -07001541 resources.openRawResource(keyboardLayoutResId)));
Jeff Brown6ec6f792012-04-17 16:52:41 -07001542 } catch (IOException ex) {
1543 } catch (NotFoundException ex) {
1544 }
1545 }
1546 });
1547 if (result[0] == null) {
1548 Log.w(TAG, "Could not get keyboard layout with descriptor '"
1549 + keyboardLayoutDescriptor + "'.");
1550 return null;
1551 }
1552 return result;
1553 }
1554
Jeff Brown5bbd4b42012-04-20 19:28:00 -07001555 // Native callback.
1556 private String getDeviceAlias(String uniqueId) {
Matthew Xie96313142012-06-29 16:57:31 -07001557 if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
1558 // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
1559 return null;
Jeff Brown5bbd4b42012-04-20 19:28:00 -07001560 }
1561 return null;
1562 }
1563
Jeff Brown4532e612012-04-05 14:27:12 -07001564 /**
1565 * Callback interface implemented by the Window Manager.
1566 */
Jeff Browna9d131c2012-09-20 16:48:17 -07001567 public interface WindowManagerCallbacks {
Jeff Brown4532e612012-04-05 14:27:12 -07001568 public void notifyConfigurationChanged();
1569
1570 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
1571
1572 public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
1573
1574 public long notifyANR(InputApplicationHandle inputApplicationHandle,
Jeff Brownbd181bb2013-09-10 16:44:24 -07001575 InputWindowHandle inputWindowHandle, String reason);
Jeff Brown4532e612012-04-05 14:27:12 -07001576
Jeff Brown037c33e2014-04-09 00:31:55 -07001577 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001578
Jeff Brown037c33e2014-04-09 00:31:55 -07001579 public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001580
1581 public long interceptKeyBeforeDispatching(InputWindowHandle focus,
1582 KeyEvent event, int policyFlags);
1583
1584 public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1585 KeyEvent event, int policyFlags);
1586
1587 public int getPointerLayer();
1588 }
1589
1590 /**
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001591 * Callback interface implemented by WiredAccessoryObserver.
1592 */
1593 public interface WiredAccessoryCallbacks {
1594 public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
Eric Laurent4a5eeb92014-05-06 10:49:04 -07001595 public void systemReady();
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001596 }
1597
1598 /**
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001599 * Private handler for the input manager.
1600 */
1601 private final class InputManagerHandler extends Handler {
Jeff Browna9d131c2012-09-20 16:48:17 -07001602 public InputManagerHandler(Looper looper) {
1603 super(looper, null, true /*async*/);
Jeff Browna2910d02012-08-25 12:29:46 -07001604 }
1605
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001606 @Override
1607 public void handleMessage(Message msg) {
1608 switch (msg.what) {
1609 case MSG_DELIVER_INPUT_DEVICES_CHANGED:
Jeff Browncf39bdf2012-05-18 14:41:19 -07001610 deliverInputDevicesChanged((InputDevice[])msg.obj);
1611 break;
1612 case MSG_SWITCH_KEYBOARD_LAYOUT:
1613 handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
1614 break;
1615 case MSG_RELOAD_KEYBOARD_LAYOUTS:
1616 reloadKeyboardLayouts();
1617 break;
1618 case MSG_UPDATE_KEYBOARD_LAYOUTS:
1619 updateKeyboardLayouts();
1620 break;
1621 case MSG_RELOAD_DEVICE_ALIASES:
1622 reloadDeviceAliases();
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001623 break;
1624 }
1625 }
1626 }
1627
1628 /**
Jeff Brown4532e612012-04-05 14:27:12 -07001629 * Hosting interface for input filters to call back into the input manager.
1630 */
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001631 private final class InputFilterHost extends IInputFilterHost.Stub {
Jeff Brown0029c662011-03-30 02:25:18 -07001632 private boolean mDisconnected;
1633
1634 public void disconnectLocked() {
1635 mDisconnected = true;
1636 }
1637
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001638 @Override
Jeff Brown0029c662011-03-30 02:25:18 -07001639 public void sendInputEvent(InputEvent event, int policyFlags) {
1640 if (event == null) {
1641 throw new IllegalArgumentException("event must not be null");
1642 }
1643
1644 synchronized (mInputFilterLock) {
1645 if (!mDisconnected) {
Jeff Brownca9bc702014-02-11 14:32:56 -08001646 nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
Jeff Brownac143512012-04-05 18:57:33 -07001647 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
Jeff Brown0029c662011-03-30 02:25:18 -07001648 policyFlags | WindowManagerPolicy.FLAG_FILTERED);
1649 }
1650 }
1651 }
1652 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001653
1654 private static final class KeyboardLayoutDescriptor {
1655 public String packageName;
1656 public String receiverName;
1657 public String keyboardLayoutName;
1658
1659 public static String format(String packageName,
1660 String receiverName, String keyboardName) {
1661 return packageName + "/" + receiverName + "/" + keyboardName;
1662 }
1663
1664 public static KeyboardLayoutDescriptor parse(String descriptor) {
1665 int pos = descriptor.indexOf('/');
1666 if (pos < 0 || pos + 1 == descriptor.length()) {
1667 return null;
1668 }
1669 int pos2 = descriptor.indexOf('/', pos + 1);
1670 if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
1671 return null;
1672 }
1673
1674 KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
1675 result.packageName = descriptor.substring(0, pos);
1676 result.receiverName = descriptor.substring(pos + 1, pos2);
1677 result.keyboardLayoutName = descriptor.substring(pos2 + 1);
1678 return result;
1679 }
1680 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001681
Jeff Brown6ec6f792012-04-17 16:52:41 -07001682 private interface KeyboardLayoutVisitor {
1683 void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -07001684 String descriptor, String label, String collection, int keyboardLayoutResId);
Jeff Brown6ec6f792012-04-17 16:52:41 -07001685 }
1686
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001687 private final class InputDevicesChangedListenerRecord implements DeathRecipient {
1688 private final int mPid;
1689 private final IInputDevicesChangedListener mListener;
1690
1691 public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
1692 mPid = pid;
1693 mListener = listener;
1694 }
1695
1696 @Override
1697 public void binderDied() {
1698 if (DEBUG) {
1699 Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
1700 }
1701 onInputDevicesChangedListenerDied(mPid);
1702 }
1703
1704 public void notifyInputDevicesChanged(int[] info) {
1705 try {
1706 mListener.onInputDevicesChanged(info);
1707 } catch (RemoteException ex) {
1708 Slog.w(TAG, "Failed to notify process "
1709 + mPid + " that input devices changed, assuming it died.", ex);
1710 binderDied();
1711 }
1712 }
1713 }
Jeff Browna47425a2012-04-13 04:09:27 -07001714
1715 private final class VibratorToken implements DeathRecipient {
1716 public final int mDeviceId;
1717 public final IBinder mToken;
1718 public final int mTokenValue;
1719
1720 public boolean mVibrating;
1721
1722 public VibratorToken(int deviceId, IBinder token, int tokenValue) {
1723 mDeviceId = deviceId;
1724 mToken = token;
1725 mTokenValue = tokenValue;
1726 }
1727
1728 @Override
1729 public void binderDied() {
1730 if (DEBUG) {
1731 Slog.d(TAG, "Vibrator token died.");
1732 }
1733 onVibratorTokenDied(this);
1734 }
1735 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001736
1737 private final class LocalService extends InputManagerInternal {
1738 @Override
1739 public void setDisplayViewports(
1740 DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
1741 setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
1742 }
Jeff Brownca9bc702014-02-11 14:32:56 -08001743
1744 @Override
1745 public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
1746 return injectInputEventInternal(event, displayId, mode);
1747 }
Jeff Brown037c33e2014-04-09 00:31:55 -07001748
1749 @Override
1750 public void setInteractive(boolean interactive) {
1751 nativeSetInteractive(mPtr, interactive);
1752 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001753 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001754}