Adding feature: input device disable/enable.

This functionality will only be available for signed system applications.
A disable call will cause a file descriptor to the input device
driver to be closed, which in turn may cause the input device
to switch into a low-power mode.
An enable call will reopen the input device.

Bug: 30143923
Test: developed a custom apk with signature permission that
calls disable/enable on touchscreen device. Verified that
touchscreen stops working when disable is called and starts
working again when enable is called. Verified that the file
handle to the driver is closed and reopened. Verified that
the notification onInputDeviceChanged is received in the app.
CTS test - android.view.cts.InputDeviceEnabledTest

Change-Id: I1e42c6996e679c083cd3f0c9adfaef8ba22c4ee4
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index bdb278b..4586316 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -34,6 +34,11 @@
     InputDevice getInputDevice(int deviceId);
     int[] getInputDeviceIds();
 
+    // Enable/disable input device.
+    boolean isInputDeviceEnabled(int deviceId);
+    void enableInputDevice(int deviceId);
+    void disableInputDevice(int deviceId);
+
     // Reports whether the hardware supports the given keys; returns true if successful
     boolean hasKeys(int deviceId, int sourceMask, in int[] keyCodes, out boolean[] keyExists);
 
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 631b77d..22b3638 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,8 +16,6 @@
 
 package android.hardware.input;
 
-import com.android.internal.os.SomeArgs;
-
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
@@ -31,10 +29,10 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.Vibrator;
-import android.os.VibrationEffect;
 import android.os.ServiceManager.ServiceNotFoundException;
+import android.os.SystemClock;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
@@ -46,6 +44,8 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.internal.os.SomeArgs;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -323,6 +323,62 @@
     }
 
     /**
+     * Returns true if an input device is enabled. Should return true for most
+     * situations. Some system apps may disable an input device, for
+     * example to prevent unwanted touch events.
+     *
+     * @param id The input device Id.
+     *
+     * @hide
+     */
+    public boolean isInputDeviceEnabled(int id) {
+        try {
+            return mIm.isInputDeviceEnabled(id);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Could not check enabled status of input device with id = " + id);
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Enables an InputDevice.
+     * <p>
+     * Requires {@link android.Manifest.permissions.DISABLE_INPUT_DEVICE}.
+     * </p>
+     *
+     * @param id The input device Id.
+     *
+     * @hide
+     */
+    public void enableInputDevice(int id) {
+        try {
+            mIm.enableInputDevice(id);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Could not enable input device with id = " + id);
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Disables an InputDevice.
+     * <p>
+     * Requires {@link android.Manifest.permissions.DISABLE_INPUT_DEVICE}.
+     * </p>
+     *
+     * @param id The input device Id.
+     *
+     * @hide
+     */
+    public void disableInputDevice(int id) {
+        try {
+            mIm.disableInputDevice(id);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Could not disable input device with id = " + id);
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Registers an input device listener to receive notifications about when
      * input devices are added, removed or changed.
      *
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index ea2434e..8405d9e 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
@@ -768,6 +770,36 @@
     }
 
     /**
+     * Returns true if input device is enabled.
+     * @return Whether the input device is enabled.
+     */
+    public boolean isEnabled() {
+        return InputManager.getInstance().isInputDeviceEnabled(mId);
+    }
+
+    /**
+     * Enables the input device.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE)
+    @TestApi
+    public void enable() {
+        InputManager.getInstance().enableInputDevice(mId);
+    }
+
+    /**
+     * Disables the input device.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE)
+    @TestApi
+    public void disable() {
+        InputManager.getInstance().disableInputDevice(mId);
+    }
+
+    /**
      * Reports whether the device has a built-in microphone.
      * @return Whether the device has a built-in microphone.
      */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4811f7a..0565ba1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2743,6 +2743,13 @@
     <permission android:name="android.permission.ACCESS_INPUT_FLINGER"
         android:protectionLevel="signature" />
 
+    <!-- Allows an application to disable/enable input devices.
+         Could be used to prevent unwanted touch events
+         on a touchscreen, for example during swimming or rain.
+         @hide -->
+    <permission android:name="android.permission.DISABLE_INPUT_DEVICE"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to configure and connect to Wifi displays
          @hide -->
     <permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"