diff options
18 files changed, 435 insertions, 703 deletions
diff --git a/api/current.txt b/api/current.txt index f00911b..d7290317 100644 --- a/api/current.txt +++ b/api/current.txt @@ -80,7 +80,7 @@ package android { field public static final java.lang.String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE"; field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER"; field public static final java.lang.String READ_HISTORY_BOOKMARKS = "com.android.browser.permission.READ_HISTORY_BOOKMARKS"; - field public static final java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE"; + field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE"; field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS"; field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"; field public static final java.lang.String READ_PROFILE = "android.permission.READ_PROFILE"; diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java index c4c3b8a..3037881 100755 --- a/cmds/input/src/com/android/commands/input/Input.java +++ b/cmds/input/src/com/android/commands/input/Input.java @@ -16,11 +16,12 @@ package com.android.commands.input; +import android.hardware.input.InputManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.util.Log; -import android.view.IWindowManager; +import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; @@ -33,8 +34,6 @@ import android.view.MotionEvent; public class Input { private static final String TAG = "Input"; - private IWindowManager mWindowManager; - /** * Command-line entry point. * @@ -44,13 +43,6 @@ public class Input { (new Input()).run(args); } - private IWindowManager getWindowManager() { - if (mWindowManager == null) { - mWindowManager = (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))); - } - return mWindowManager; - } - private void run(String[] args) { if (args.length < 1) { showUsage(); @@ -127,8 +119,10 @@ public class Input { private void sendKeyEvent(int keyCode) { long now = SystemClock.uptimeMillis(); - injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0)); - injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0)); + injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); + injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); } private void sendTap(float x, float y) { @@ -150,23 +144,14 @@ public class Input { } private void injectKeyEvent(KeyEvent event) { - try { - Log.i(TAG, "InjectKeyEvent: " + event); - getWindowManager().injectKeyEvent(event, true); - } catch (RemoteException ex) { - Log.i(TAG, "RemoteException", ex); - } + Log.i(TAG, "InjectKeyEvent: " + event); + InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } private void injectPointerEvent(MotionEvent event) { - try { - Log.i("Input", "InjectPointerEvent: " + event); - getWindowManager().injectPointerEvent(event, true); - } catch (RemoteException ex) { - Log.i(TAG, "RemoteException", ex); - } finally { - event.recycle(); - } + event.setSource(InputDevice.SOURCE_TOUCHSCREEN); + Log.i("Input", "InjectPointerEvent: " + event); + InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } private static final float lerp(float a, float b, float alpha) { @@ -174,7 +159,7 @@ public class Input { } private void showUsage() { - System.err.println("usage: input [text|keyevent]"); + System.err.println("usage: input ..."); System.err.println(" input text <string>"); System.err.println(" input keyevent <key code>"); System.err.println(" input tap <x> <y>"); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 9dde51c..c5d7b91 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -45,6 +45,7 @@ import android.graphics.drawable.Drawable; import android.hardware.ISerialManager; import android.hardware.SensorManager; import android.hardware.SerialManager; +import android.hardware.input.IInputManager; import android.hardware.input.InputManager; import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbManager; @@ -325,9 +326,9 @@ class ContextImpl extends Context { }}); registerService(INPUT_SERVICE, new ServiceFetcher() { - public Object createService(ContextImpl ctx) { - return new InputManager(ctx); - }}); + public Object createService(ContextImpl ctx) { + return new InputManager(ctx); + }}); registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index e4f7950..f955713 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.hardware.input.InputManager; import android.os.Bundle; import android.os.Debug; import android.os.IBinder; @@ -35,6 +36,7 @@ import android.os.SystemClock; import android.util.AndroidRuntimeException; import android.util.Log; import android.view.IWindowManager; +import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; @@ -859,11 +861,30 @@ public class Instrumentation { */ public void sendKeySync(KeyEvent event) { validateNotAppThread(); - try { - (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))) - .injectKeyEvent(event, true); - } catch (RemoteException e) { + + long downTime = event.getDownTime(); + long eventTime = event.getEventTime(); + int action = event.getAction(); + int code = event.getKeyCode(); + int repeatCount = event.getRepeatCount(); + int metaState = event.getMetaState(); + int deviceId = event.getDeviceId(); + int scancode = event.getScanCode(); + int source = event.getSource(); + int flags = event.getFlags(); + if (source == InputDevice.SOURCE_UNKNOWN) { + source = InputDevice.SOURCE_KEYBOARD; + } + if (eventTime == 0) { + eventTime = SystemClock.uptimeMillis(); + } + if (downTime == 0) { + downTime = eventTime; } + KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, + deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source); + InputManager.injectInputEvent(newEvent, + InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } /** @@ -902,11 +923,10 @@ public class Instrumentation { */ public void sendPointerSync(MotionEvent event) { validateNotAppThread(); - try { - (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))) - .injectPointerEvent(event, true); - } catch (RemoteException e) { + if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { + event.setSource(InputDevice.SOURCE_TOUCHSCREEN); } + InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } /** @@ -922,11 +942,10 @@ public class Instrumentation { */ public void sendTrackballEventSync(MotionEvent event) { validateNotAppThread(); - try { - (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))) - .injectTrackballEvent(event, true); - } catch (RemoteException e) { + if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) { + event.setSource(InputDevice.SOURCE_TRACKBALL); } + InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } /** diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index 85061bb..c2abce5 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -16,6 +16,22 @@ package android.hardware.input; +import android.view.InputDevice; +import android.view.InputEvent; + /** @hide */ interface IInputManager { + // Gets input device information. + InputDevice getInputDevice(int deviceId); + int[] getInputDeviceIds(); + + // Reports whether the hardware supports the given keys; returns true if successful + boolean hasKeys(int deviceId, int sourceMask, in int[] keyCodes, out boolean[] keyExists); + + // Temporarily changes the pointer speed. + void tryPointerSpeed(int speed); + + // Injects an input event into the system. To inject into windows owned by other + // applications, the caller must have the INJECT_EVENTS permission. + boolean injectInputEvent(in InputEvent ev, int mode); } diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 6093404..ba64035 100755 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -31,10 +31,20 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.os.Bundle; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.provider.Settings; +import android.provider.Settings.SettingNotFoundException; import android.util.Log; +import android.view.Display; +import android.view.IWindowManager; +import android.view.InputDevice; +import android.view.InputEvent; import android.view.KeyCharacterMap; +import android.view.WindowManagerPolicy; import android.view.KeyCharacterMap.UnavailableException; import java.util.ArrayList; @@ -53,6 +63,8 @@ import java.util.List; public final class InputManager { private static final String TAG = "InputManager"; + private static final IInputManager sIm; + private final Context mContext; // Used to simulate a persistent data store. @@ -118,6 +130,53 @@ public final class InputManager { public static final String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS"; + /** + * Pointer Speed: The minimum (slowest) pointer speed (-7). + * @hide + */ + public static final int MIN_POINTER_SPEED = -7; + + /** + * Pointer Speed: The maximum (fastest) pointer speed (7). + * @hide + */ + public static final int MAX_POINTER_SPEED = 7; + + /** + * Pointer Speed: The default pointer speed (0). + * @hide + */ + public static final int DEFAULT_POINTER_SPEED = 0; + + /** + * Input Event Injection Synchronization Mode: None. + * Never blocks. Injection is asynchronous and is assumed always to be successful. + * @hide + */ + public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; // see InputDispatcher.h + + /** + * Input Event Injection Synchronization Mode: Wait for result. + * Waits for previous events to be dispatched so that the input dispatcher can + * determine whether input event injection will be permitted based on the current + * input focus. Does not wait for the input event to finish being handled + * by the application. + * @hide + */ + public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1; // see InputDispatcher.h + + /** + * Input Event Injection Synchronization Mode: Wait for finish. + * Waits for the event to be delivered to the application and handled. + * @hide + */ + public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; // see InputDispatcher.h + + static { + IBinder b = ServiceManager.getService(Context.INPUT_SERVICE); + sIm = IInputManager.Stub.asInterface(b); + } + /** @hide */ public InputManager(Context context) { mContext = context; @@ -296,6 +355,160 @@ public final class InputManager { return null; } + /** + * Gets the mouse pointer speed. + * <p> + * Only returns the permanent mouse pointer speed. Ignores any temporary pointer + * speed set by {@link #tryPointerSpeed}. + * </p> + * + * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and + * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}. + * + * @hide + */ + public int getPointerSpeed() { + int speed = DEFAULT_POINTER_SPEED; + try { + speed = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.POINTER_SPEED); + } catch (SettingNotFoundException snfe) { + } + return speed; + } + + /** + * Sets the mouse pointer speed. + * <p> + * Requires {@link android.Manifest.permissions.WRITE_SETTINGS}. + * </p> + * + * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and + * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}. + * + * @hide + */ + public void setPointerSpeed(int speed) { + if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) { + throw new IllegalArgumentException("speed out of range"); + } + + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.POINTER_SPEED, speed); + } + + /** + * Changes the mouse pointer speed temporarily, but does not save the setting. + * <p> + * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}. + * </p> + * + * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and + * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}. + * + * @hide + */ + public void tryPointerSpeed(int speed) { + if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) { + throw new IllegalArgumentException("speed out of range"); + } + + try { + sIm.tryPointerSpeed(speed); + } catch (RemoteException ex) { + Log.w(TAG, "Could not set temporary pointer speed.", ex); + } + } + + /** + * Gets information about the input device with the specified id. + * @param id The device id. + * @return The input device or null if not found. + * + * @hide + */ + public static InputDevice getInputDevice(int id) { + try { + return sIm.getInputDevice(id); + } catch (RemoteException ex) { + throw new RuntimeException("Could not get input device information.", ex); + } + } + + /** + * Gets the ids of all input devices in the system. + * @return The input device ids. + * + * @hide + */ + public static int[] getInputDeviceIds() { + try { + return sIm.getInputDeviceIds(); + } catch (RemoteException ex) { + throw new RuntimeException("Could not get input device ids.", ex); + } + } + + /** + * Queries the framework about whether any physical keys exist on the + * any keyboard attached to the device that are capable of producing the given + * array of key codes. + * + * @param keyCodes The array of key codes to query. + * @return A new array of the same size as the key codes array whose elements + * are set to true if at least one attached keyboard supports the corresponding key code + * at the same index in the key codes array. + * + * @hide + */ + public static boolean[] deviceHasKeys(int[] keyCodes) { + boolean[] ret = new boolean[keyCodes.length]; + try { + sIm.hasKeys(-1, InputDevice.SOURCE_ANY, keyCodes, ret); + } catch (RemoteException e) { + // no fallback; just return the empty array + } + return ret; + } + + /** + * Injects an input event into the event system on behalf of an application. + * The synchronization mode determines whether the method blocks while waiting for + * input injection to proceed. + * <p> + * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into + * windows that are owned by other applications. + * </p><p> + * Make sure you correctly set the event time and input source of the event + * before calling this method. + * </p> + * + * @param event The event to inject. + * @param mode The synchronization mode. One of: + * {@link #INJECT_INPUT_EVENT_MODE_ASYNC}, + * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT}, or + * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH}. + * @return True if input event injection succeeded. + * + * @hide + */ + public static boolean injectInputEvent(InputEvent event, int mode) { + if (event == null) { + throw new IllegalArgumentException("event must not be null"); + } + if (mode != INJECT_INPUT_EVENT_MODE_ASYNC + && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH + && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) { + throw new IllegalArgumentException("mode is invalid"); + } + + try { + return sIm.injectInputEvent(event, mode); + } catch (RemoteException ex) { + return false; + } + } + private static String makeKeyboardLayoutDescriptor(String packageName, String receiverName, String keyboardName) { return packageName + "/" + receiverName + "/" + keyboardName; diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index eb030de..8fe8e40 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -65,15 +65,6 @@ interface IWindowManager // Is the device configured to have a full system bar for larger screens? boolean hasSystemNavBar(); - // These can only be called when injecting events to your own window, - // or by holding the INJECT_EVENTS permission. These methods may block - // until pending input events are finished being dispatched even when 'sync' is false. - // Avoid calling these methods on your UI thread or use the 'NoWait' version instead. - boolean injectKeyEvent(in KeyEvent ev, boolean sync); - boolean injectPointerEvent(in MotionEvent ev, boolean sync); - boolean injectTrackballEvent(in MotionEvent ev, boolean sync); - boolean injectInputEventNoWait(in InputEvent ev); - // These can only be called when holding the MANAGE_APP_TOKENS permission. void pauseKeyDispatching(IBinder token); void resumeKeyDispatching(IBinder token); @@ -128,26 +119,6 @@ interface IWindowManager void setAnimationScale(int which, float scale); void setAnimationScales(in float[] scales); - // These require the READ_INPUT_STATE permission. - int getSwitchState(int sw); - int getSwitchStateForDevice(int devid, int sw); - int getScancodeState(int sw); - int getScancodeStateForDevice(int devid, int sw); - int getTrackballScancodeState(int sw); - int getDPadScancodeState(int sw); - int getKeycodeState(int sw); - int getKeycodeStateForDevice(int devid, int sw); - int getTrackballKeycodeState(int sw); - int getDPadKeycodeState(int sw); - InputChannel monitorInput(String inputChannelName); - - // Report whether the hardware supports the given keys; returns true if successful - boolean hasKeys(in int[] keycodes, inout boolean[] keyExists); - - // Get input device information. - InputDevice getInputDevice(int deviceId); - int[] getInputDeviceIds(); - // For testing void setInTouchMode(boolean showFocus); @@ -220,11 +191,6 @@ interface IWindowManager void statusBarVisibilityChanged(int visibility); /** - * Called by the settings application to temporarily set the pointer speed. - */ - void setPointerSpeed(int speed); - - /** * Block until the given window has been drawn to the screen. */ void waitForWindowDrawn(IBinder token, in IRemoteCallback callback); diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 91e47e6..93a0185 100755 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -16,9 +16,9 @@ package android.view; +import android.hardware.input.InputManager; import android.os.Parcel; import android.os.Parcelable; -import android.os.RemoteException; import java.util.ArrayList; import java.util.List; @@ -301,13 +301,7 @@ public final class InputDevice implements Parcelable { * @return The input device or null if not found. */ public static InputDevice getDevice(int id) { - IWindowManager wm = Display.getWindowManager(); - try { - return wm.getInputDevice(id); - } catch (RemoteException ex) { - throw new RuntimeException( - "Could not get input device information from Window Manager.", ex); - } + return InputManager.getInputDevice(id); } /** @@ -315,13 +309,7 @@ public final class InputDevice implements Parcelable { * @return The input device ids. */ public static int[] getDeviceIds() { - IWindowManager wm = Display.getWindowManager(); - try { - return wm.getInputDeviceIds(); - } catch (RemoteException ex) { - throw new RuntimeException( - "Could not get input device ids from Window Manager.", ex); - } + return InputManager.getInputDeviceIds(); } /** diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java index 98cce5e..b03f086 100644 --- a/core/java/android/view/KeyCharacterMap.java +++ b/core/java/android/view/KeyCharacterMap.java @@ -19,10 +19,9 @@ package android.view; import android.text.method.MetaKeyKeyListener; import android.util.AndroidRuntimeException; import android.util.SparseIntArray; -import android.os.RemoteException; +import android.hardware.input.InputManager; import android.util.SparseArray; -import java.io.Reader; import java.lang.Character; /** @@ -528,10 +527,7 @@ public class KeyCharacterMap { * @return True if at least one attached keyboard supports the specified key code. */ public static boolean deviceHasKey(int keyCode) { - int[] codeArray = new int[1]; - codeArray[0] = keyCode; - boolean[] ret = deviceHasKeys(codeArray); - return ret[0]; + return InputManager.deviceHasKeys(new int[] { keyCode })[0]; } /** @@ -545,14 +541,7 @@ public class KeyCharacterMap { * at the same index in the key codes array. */ public static boolean[] deviceHasKeys(int[] keyCodes) { - boolean[] ret = new boolean[keyCodes.length]; - IWindowManager wm = Display.getWindowManager(); - try { - wm.hasKeys(keyCodes, ret); - } catch (RemoteException e) { - // no fallback; just return the empty array - } - return ret; + return InputManager.deviceHasKeys(keyCodes); } /** diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index cf9cafc..491cd67 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -349,6 +349,10 @@ public interface WindowManagerPolicy { * between it and the policy. */ public interface WindowManagerFuncs { + public static final int LID_ABSENT = -1; + public static final int LID_CLOSED = 0; + public static final int LID_OPEN = 1; + /** * Ask the window manager to re-evaluate the system UI flags. */ @@ -362,6 +366,16 @@ public interface WindowManagerPolicy { InputEventReceiver.Factory inputEventReceiverFactory, String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen); + + /** + * Returns a code that describes the current state of the lid switch. + */ + public int getLidState(); + + /** + * Creates an input channel that will receive all input from the input dispatcher. + */ + public InputChannel monitorInput(String name); } /** @@ -943,10 +957,10 @@ public interface WindowManagerPolicy { public void setRotationLw(int rotation); /** - * Called when the system is mostly done booting to determine whether + * Called when the system is mostly done booting to set whether * the system should go into safe mode. */ - public boolean detectSafeMode(); + public void setSafeMode(boolean safeMode); /** * Called when the system is mostly done booting. diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5ae12b6..00faa41 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1200,7 +1200,8 @@ android:protectionLevel="signature|system" /> <!-- Allows an application to retrieve the current state of keys and - switches. This is only for use by the system.--> + switches. This is only for use by the system. + @deprecated The API that used this permission has been removed. --> <permission android:name="android.permission.READ_INPUT_STATE" android:label="@string/permlab_readInputState" android:description="@string/permdesc_readInputState" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index cc07240..0c8208f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -23,6 +23,7 @@ import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.graphics.Canvas; import android.graphics.RectF; +import android.hardware.input.InputManager; import android.os.RemoteException; import android.os.SystemClock; import android.os.ServiceManager; @@ -47,7 +48,6 @@ public class KeyButtonView extends ImageView { final float GLOW_MAX_SCALE_FACTOR = 1.8f; final float BUTTON_QUIESCENT_ALPHA = 0.6f; - IWindowManager mWindowManager; long mDownTime; int mCode; int mTouchSlop; @@ -93,9 +93,6 @@ public class KeyButtonView extends ImageView { a.recycle(); - mWindowManager = IWindowManager.Stub.asInterface( - ServiceManager.getService(Context.WINDOW_SERVICE)); - setClickable(true); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } @@ -276,12 +273,7 @@ public class KeyButtonView extends ImageView { 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, InputDevice.SOURCE_KEYBOARD); - try { - //Slog.d(TAG, "injecting event " + ev); - mWindowManager.injectInputEventNoWait(ev); - } catch (RemoteException ex) { - // System process is dead - } + InputManager.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index 49b1a14..09283f4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -1322,14 +1322,6 @@ public class TabletStatusBar extends BaseStatusBar implements } } - private void sendKey(KeyEvent key) { - try { - if (DEBUG) Slog.d(TAG, "injecting key event: " + key); - mWindowManager.injectInputEventNoWait(key); - } catch (RemoteException ex) { - } - } - private View.OnClickListener mOnClickListener = new View.OnClickListener() { public void onClick(View v) { if (v == mRecentButton) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index ded190b..1be5bd7 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -132,6 +132,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; import android.view.WindowManagerImpl; import android.view.WindowManagerPolicy; +import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; +import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; +import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; import android.view.KeyCharacterMap.FallbackAction; import android.view.accessibility.AccessibilityEvent; import android.view.animation.Animation; @@ -237,8 +240,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int SYSTEM_UI_CHANGING_LAYOUT = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; - // Useful scan codes. - private static final int SW_LID = 0x00; private static final int BTN_MOUSE = 0x110; /* Table of Application Launch keys. Maps from key codes to intent categories. @@ -322,10 +323,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { RecentApplicationsDialog mRecentAppsDialog; int mRecentAppsDialogHeldModifiers; - private static final int LID_ABSENT = -1; - private static final int LID_CLOSED = 0; - private static final int LID_OPEN = 1; - int mLidOpen = LID_ABSENT; boolean mSystemReady; @@ -1120,16 +1117,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; wm.addView(mPointerLocationView, lp); - try { - mPointerLocationInputChannel = - mWindowManager.monitorInput("PointerLocationView"); - mPointerLocationInputEventReceiver = - new PointerLocationInputEventReceiver(mPointerLocationInputChannel, - Looper.myLooper(), mPointerLocationView); - } catch (RemoteException ex) { - Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.", - ex); - } + mPointerLocationInputChannel = + mWindowManagerFuncs.monitorInput("PointerLocationView"); + mPointerLocationInputEventReceiver = + new PointerLocationInputEventReceiver(mPointerLocationInputChannel, + Looper.myLooper(), mPointerLocationView); } } @@ -1223,18 +1215,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } void readLidState() { - try { - int sw = mWindowManager.getSwitchState(SW_LID); - if (sw > 0) { - mLidOpen = LID_OPEN; - } else if (sw == 0) { - mLidOpen = LID_CLOSED; - } else { - mLidOpen = LID_ABSENT; - } - } catch (RemoteException e) { - // Ignore - } + mLidOpen = mWindowManagerFuncs.getLidState(); } private int determineHiddenState(int mode, int hiddenValue, int visibleValue) { @@ -3648,29 +3629,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - public boolean detectSafeMode() { - try { - int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU); - int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S); - int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER); - int trackballState = mWindowManager.getTrackballScancodeState(BTN_MOUSE); - int volumeDownState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_VOLUME_DOWN); - mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 - || volumeDownState > 0; - performHapticFeedbackLw(null, mSafeMode - ? HapticFeedbackConstants.SAFE_MODE_ENABLED - : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); - if (mSafeMode) { - Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState - + " dpad=" + dpadState + " trackball=" + trackballState + ")"); - } else { - Log.i(TAG, "SAFE MODE not enabled"); - } - return mSafeMode; - } catch (RemoteException e) { - // Doom! (it's also local) - throw new RuntimeException("window manager dead"); - } + public void setSafeMode(boolean safeMode) { + mSafeMode = safeMode; + performHapticFeedbackLw(null, safeMode + ? HapticFeedbackConstants.SAFE_MODE_ENABLED + : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); } static long[] getLongIntArray(Resources r, int resid) { diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index 6a566ae..b8cc65e 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -28,11 +28,13 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.ContentObserver; import android.hardware.input.IInputManager; +import android.hardware.input.InputManager; import android.os.Binder; import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.MessageQueue; +import android.os.Process; import android.os.SystemProperties; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; @@ -108,18 +110,16 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. private static native void nativeSetShowTouches(int ptr, boolean enabled); private static native String nativeDump(int ptr); private static native void nativeMonitor(int ptr); - + // Input event injection constants defined in InputDispatcher.h. - public static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0; - public static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1; - public static final int INPUT_EVENT_INJECTION_FAILED = 2; - public static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3; - - // Input event injection synchronization modes defined in InputDispatcher.h - public static final int INPUT_EVENT_INJECTION_SYNC_NONE = 0; - public static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1; - public static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH = 2; - + private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0; + private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1; + private static final int INPUT_EVENT_INJECTION_FAILED = 2; + private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3; + + // Maximum number of milliseconds to wait for input event injection. + private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; + // Key states (may be returned by queries about the current state of a // particular key code, scan code or switch). @@ -194,7 +194,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. nativeGetInputConfiguration(mPtr, config); } - + /** * Gets the current state of a key or button by key code. * @param deviceId The input device id, or -1 to consult all devices. @@ -246,6 +246,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. * key codes. * @return True if the lookup was successful, false otherwise. */ + @Override public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) { if (keyCodes == null) { throw new IllegalArgumentException("keyCodes must not be null."); @@ -336,43 +337,42 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. } } - /** - * Injects an input event into the event system on behalf of an application. - * The synchronization mode determines whether the method blocks while waiting for - * input injection to proceed. - * - * {@link #INPUT_EVENT_INJECTION_SYNC_NONE} never blocks. Injection is asynchronous and - * is assumed always to be successful. - * - * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT} waits for previous events to be - * dispatched so that the input dispatcher can determine whether input event injection will - * be permitted based on the current input focus. Does not wait for the input event to - * finish processing. - * - * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH} waits for the input event to - * be completely processed. - * - * @param event The event to inject. - * @param injectorPid The pid of the injecting application. - * @param injectorUid The uid of the injecting application. - * @param syncMode The synchronization mode. - * @param timeoutMillis The injection timeout in milliseconds. - * @return One of the INPUT_EVENT_INJECTION_XXX constants. - */ - public int injectInputEvent(InputEvent event, int injectorPid, int injectorUid, - int syncMode, int timeoutMillis) { + @Override + public boolean injectInputEvent(InputEvent event, int mode) { if (event == null) { throw new IllegalArgumentException("event must not be null"); } - if (injectorPid < 0 || injectorUid < 0) { - throw new IllegalArgumentException("injectorPid and injectorUid must not be negative."); - } - if (timeoutMillis <= 0) { - throw new IllegalArgumentException("timeoutMillis must be positive"); + if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC + && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH + && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) { + throw new IllegalArgumentException("mode is invalid"); } - return nativeInjectInputEvent(mPtr, event, injectorPid, injectorUid, syncMode, - timeoutMillis, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + final int result; + try { + result = nativeInjectInputEvent(mPtr, event, pid, uid, mode, + INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); + } finally { + Binder.restoreCallingIdentity(ident); + } + switch (result) { + case INPUT_EVENT_INJECTION_PERMISSION_DENIED: + Slog.w(TAG, "Input event injection from pid " + pid + " permission denied."); + throw new SecurityException( + "Injecting to another application requires INJECT_EVENTS permission"); + case INPUT_EVENT_INJECTION_SUCCEEDED: + return true; + case INPUT_EVENT_INJECTION_TIMED_OUT: + Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); + return false; + case INPUT_EVENT_INJECTION_FAILED: + default: + Slog.w(TAG, "Input event injection from pid " + pid + " failed."); + return false; + } } /** @@ -380,6 +380,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. * @param id The device id. * @return The input device or null if not found. */ + @Override public InputDevice getInputDevice(int deviceId) { return nativeGetInputDevice(mPtr, deviceId); } @@ -388,6 +389,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. * Gets the ids of all input devices in the system. * @return The input device ids. */ + @Override public int[] getInputDeviceIds() { return nativeGetInputDeviceIds(mPtr); } @@ -436,14 +438,25 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. * @param speed The pointer speed as a value between -7 (slowest) and 7 (fastest) * where 0 is the default speed. */ - public void setPointerSpeed(int speed) { - speed = Math.min(Math.max(speed, -7), 7); - nativeSetPointerSpeed(mPtr, speed); + @Override + public void tryPointerSpeed(int speed) { + if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED, + "tryPointerSpeed()")) { + throw new SecurityException("Requires SET_POINTER_SPEED permission"); + } + + setPointerSpeedUnchecked(speed); } public void updatePointerSpeedFromSettings() { - int speed = getPointerSpeedSetting(0); - setPointerSpeed(speed); + int speed = getPointerSpeedSetting(); + setPointerSpeedUnchecked(speed); + } + + private void setPointerSpeedUnchecked(int speed) { + speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED), + InputManager.MAX_POINTER_SPEED); + nativeSetPointerSpeed(mPtr, speed); } private void registerPointerSpeedSettingObserver() { @@ -457,8 +470,8 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. }); } - private int getPointerSpeedSetting(int defaultValue) { - int speed = defaultValue; + private int getPointerSpeedSetting() { + int speed = InputManager.DEFAULT_POINTER_SPEED; try { speed = Settings.System.getInt(mContext.getContentResolver(), Settings.System.POINTER_SPEED); @@ -510,6 +523,23 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. } } + private boolean checkCallingPermission(String permission, String func) { + // Quick check: if the calling permission is me, it's all okay. + if (Binder.getCallingPid() == Process.myPid()) { + return true; + } + + if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) { + return true; + } + String msg = "Permission Denial: " + func + " from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + + " requires " + permission; + Slog.w(TAG, msg); + return false; + } + // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection). public void monitor() { synchronized (mInputFilterLock) { } @@ -703,7 +733,8 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. synchronized (mInputFilterLock) { if (!mDisconnected) { - nativeInjectInputEvent(mPtr, event, 0, 0, INPUT_EVENT_INJECTION_SYNC_NONE, 0, + nativeInjectInputEvent(mPtr, event, 0, 0, + InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, policyFlags | WindowManagerPolicy.FLAG_FILTERED); } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 8ea00c1..3e74486 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -245,10 +245,6 @@ public class WindowManagerService extends IWindowManager.Stub */ static final boolean CUSTOM_SCREEN_ROTATION = true; - // Maximum number of milliseconds to wait for input event injection. - // FIXME is this value reasonable? - private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; - // Maximum number of milliseconds to wait for input devices to be enumerated before // proceding with safe mode detection. private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000; @@ -4855,90 +4851,22 @@ public class WindowManagerService extends IWindowManager.Stub mAnimatorDurationScale }; } - public int getSwitchState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getSwitchState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getSwitchStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getSwitchStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getSwitchState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getScancodeStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getScancodeStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getTrackballScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getTrackballScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw); - } - - public int getDPadScancodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getDPadScancodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_DPAD, sw); - } - - public int getKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, sw); - } - - public int getKeycodeStateForDevice(int devid, int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getKeycodeStateForDevice()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(devid, InputDevice.SOURCE_ANY, sw); - } - - public int getTrackballKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getTrackballKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw); - } - - public int getDPadKeycodeState(int sw) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "getDPadKeycodeState()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); + // Called by window manager policy. Not exposed externally. + @Override + public int getLidState() { + final int SW_LID = 0x00; + int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LID); + if (sw > 0) { + return LID_OPEN; + } else if (sw == 0) { + return LID_CLOSED; + } else { + return LID_ABSENT; } - return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, sw); - } - - public boolean hasKeys(int[] keycodes, boolean[] keyExists) { - return mInputManager.hasKeys(-1, InputDevice.SOURCE_ANY, keycodes, keyExists); } + // Called by window manager policy. Not exposed externally. + @Override public InputChannel monitorInput(String inputChannelName) { if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, "monitorInput()")) { @@ -4951,14 +4879,6 @@ public class WindowManagerService extends IWindowManager.Stub mInputManager.setInputFilter(filter); } - public InputDevice getInputDevice(int deviceId) { - return mInputManager.getInputDevice(deviceId); - } - - public int[] getInputDeviceIds() { - return mInputManager.getInputDeviceIds(); - } - public void enableScreenAfterBoot() { synchronized(mWindowMap) { if (DEBUG_BOOT) { @@ -6444,164 +6364,6 @@ public class WindowManagerService extends IWindowManager.Stub sendScreenStatusToClients(); } - /** - * Injects a keystroke event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the keystroke action. (Be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectKeyEvent(KeyEvent ev, boolean sync) { - long downTime = ev.getDownTime(); - long eventTime = ev.getEventTime(); - - int action = ev.getAction(); - int code = ev.getKeyCode(); - int repeatCount = ev.getRepeatCount(); - int metaState = ev.getMetaState(); - int deviceId = ev.getDeviceId(); - int scancode = ev.getScanCode(); - int source = ev.getSource(); - int flags = ev.getFlags(); - - if (source == InputDevice.SOURCE_UNKNOWN) { - source = InputDevice.SOURCE_KEYBOARD; - } - - if (eventTime == 0) eventTime = SystemClock.uptimeMillis(); - if (downTime == 0) downTime = eventTime; - - KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, - deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source); - - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result, pid); - } - - /** - * Inject a pointer (touch) event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the pointer (touch) action. (As noted in - * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectPointerEvent(MotionEvent ev, boolean sync) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - MotionEvent newEvent = MotionEvent.obtain(ev); - if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { - newEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); - } - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result, pid); - } - - /** - * Inject a trackball (navigation device) event into the UI. - * Even when sync is false, this method may block while waiting for current - * input events to be dispatched. - * - * @param ev A motion event describing the trackball action. (As noted in - * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use - * {@link SystemClock#uptimeMillis()} as the timebase.) - * @param sync If true, wait for the event to be completed before returning to the caller. - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectTrackballEvent(MotionEvent ev, boolean sync) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - MotionEvent newEvent = MotionEvent.obtain(ev); - if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) { - newEvent.setSource(InputDevice.SOURCE_TRACKBALL); - } - - final int result = mInputManager.injectInputEvent(newEvent, pid, uid, - sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH - : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result, pid); - } - - /** - * Inject an input event into the UI without waiting for dispatch to commence. - * This variant is useful for fire-and-forget input event injection. It does not - * block any longer than it takes to enqueue the input event. - * - * @param ev An input event. (Be sure to set the input source correctly.) - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - public boolean injectInputEventNoWait(InputEvent ev) { - final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - final long ident = Binder.clearCallingIdentity(); - - final int result = mInputManager.injectInputEvent(ev, pid, uid, - InputManagerService.INPUT_EVENT_INJECTION_SYNC_NONE, - INJECTION_TIMEOUT_MILLIS); - - Binder.restoreCallingIdentity(ident); - return reportInjectionResult(result, pid); - } - - private boolean reportInjectionResult(int result, int pid) { - switch (result) { - case InputManagerService.INPUT_EVENT_INJECTION_PERMISSION_DENIED: - Slog.w(TAG, "Input event injection from pid " + pid + " permission denied."); - throw new SecurityException( - "Injecting to another application requires INJECT_EVENTS permission"); - case InputManagerService.INPUT_EVENT_INJECTION_SUCCEEDED: - return true; - case InputManagerService.INPUT_EVENT_INJECTION_TIMED_OUT: - Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); - return false; - case InputManagerService.INPUT_EVENT_INJECTION_FAILED: - default: - Slog.w(TAG, "Input event injection from pid " + pid + " failed."); - return false; - } - } - - /** - * Temporarily set the pointer speed. Does not save the new setting. - * Used by the settings application. - */ - public void setPointerSpeed(int speed) { - if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED, - "setPointerSpeed()")) { - throw new SecurityException("Requires SET_POINTER_SPEED permission"); - } - - mInputManager.setPointerSpeed(speed); - } - private WindowState getFocusedWindow() { synchronized (mWindowMap) { return getFocusedWindowLocked(); @@ -6616,11 +6378,29 @@ public class WindowManagerService extends IWindowManager.Stub if (!mInputMonitor.waitForInputDevicesReady( INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) { Slog.w(TAG, "Devices still not ready after waiting " - + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS - + " milliseconds before attempting to detect safe mode."); + + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS + + " milliseconds before attempting to detect safe mode."); + } + + final int BTN_MOUSE = 0x110; + int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, + KeyEvent.KEYCODE_MENU); + int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); + int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, + KeyEvent.KEYCODE_DPAD_CENTER); + int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, + BTN_MOUSE); + int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, + KeyEvent.KEYCODE_VOLUME_DOWN); + mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0 + || volumeDownState > 0; + if (mSafeMode) { + Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState + + " dpad=" + dpadState + " trackball=" + trackballState + ")"); + } else { + Log.i(TAG, "SAFE MODE not enabled"); } - - mSafeMode = mPolicy.detectSafeMode(); + mPolicy.setSafeMode(mSafeMode); return mSafeMode; } diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index 58f65be..1f6279c 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -255,41 +255,6 @@ public class WindowManagerPermissionTests extends TestCase { } @SmallTest - public void testINJECT_EVENTS() { - try { - mWm.injectKeyEvent(new KeyEvent(0, 0), false); - fail("IWindowManager.injectKeyEvent did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - - try { - mWm.injectPointerEvent(MotionEvent.obtain(0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0), false); - fail("IWindowManager.injectPointerEvent did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - - try { - mWm.injectTrackballEvent(MotionEvent.obtain(0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0), false); - fail("IWindowManager.injectTrackballEvent did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - } - - @SmallTest public void testDISABLE_KEYGUARD() { Binder token = new Binder(); try { @@ -347,73 +312,9 @@ public class WindowManagerPermissionTests extends TestCase { } @SmallTest - public void testREAD_INPUT_STATE() { - try { - mWm.getSwitchState(0); - fail("IWindowManager.getSwitchState did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - - try { - mWm.getSwitchStateForDevice(0, 0); - fail("IWindowManager.getSwitchStateForDevice did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - - try { - mWm.getScancodeState(0); - fail("IWindowManager.getScancodeState did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - - try { - mWm.getScancodeStateForDevice(0, 0); - fail("IWindowManager.getScancodeStateForDevice did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - - try { - mWm.getKeycodeState(0); - fail("IWindowManager.getKeycodeState did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - - try { - mWm.getKeycodeStateForDevice(0, 0); - fail("IWindowManager.getKeycodeStateForDevice did not throw SecurityException as" - + " expected"); - } catch (SecurityException e) { - // expected - } catch (RemoteException e) { - fail("Unexpected remote exception"); - } - } - - @SmallTest public void testSET_ORIENTATION() { try { mWm.updateRotation(true, false); - mWm.getSwitchState(0); fail("IWindowManager.updateRotation did not throw SecurityException as" + " expected"); } catch (SecurityException e) { @@ -424,7 +325,6 @@ public class WindowManagerPermissionTests extends TestCase { try { mWm.freezeRotation(-1); - mWm.getSwitchState(0); fail("IWindowManager.freezeRotation did not throw SecurityException as" + " expected"); } catch (SecurityException e) { @@ -435,7 +335,6 @@ public class WindowManagerPermissionTests extends TestCase { try { mWm.thawRotation(); - mWm.getSwitchState(0); fail("IWindowManager.thawRotation did not throw SecurityException as" + " expected"); } catch (SecurityException e) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java index 0755670..e6c9351 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java @@ -161,92 +161,11 @@ public class BridgeWindowManager implements IWindowManager { } @Override - public int getDPadKeycodeState(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getDPadScancodeState(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - - @Override - public InputDevice getInputDevice(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int[] getInputDeviceIds() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getKeycodeState(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getKeycodeStateForDevice(int arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - - @Override public int getPendingAppTransition() throws RemoteException { // TODO Auto-generated method stub return 0; } - - @Override - public int getScancodeState(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getScancodeStateForDevice(int arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getSwitchState(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getSwitchStateForDevice(int arg0, int arg1) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getTrackballKeycodeState(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public int getTrackballScancodeState(int arg0) throws RemoteException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public boolean hasKeys(int[] arg0, boolean[] arg1) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - @Override public boolean inKeyguardRestrictedInputMode() throws RemoteException { // TODO Auto-generated method stub @@ -254,30 +173,6 @@ public class BridgeWindowManager implements IWindowManager { } @Override - public boolean injectInputEventNoWait(InputEvent arg0) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean injectKeyEvent(KeyEvent arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean injectPointerEvent(MotionEvent arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean injectTrackballEvent(MotionEvent arg0, boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException { // TODO Auto-generated method stub return false; @@ -302,12 +197,6 @@ public class BridgeWindowManager implements IWindowManager { } @Override - public InputChannel monitorInput(String arg0) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override public void moveAppToken(int arg0, IBinder arg1) throws RemoteException { // TODO Auto-generated method stub @@ -462,12 +351,6 @@ public class BridgeWindowManager implements IWindowManager { } @Override - public void setPointerSpeed(int arg0) throws RemoteException { - // TODO Auto-generated method stub - - } - - @Override public void updateRotation(boolean arg0, boolean arg1) throws RemoteException { // TODO Auto-generated method stub } |
