summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt13
-rw-r--r--core/java/android/hardware/Battery.java74
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl4
-rw-r--r--core/java/android/hardware/input/InputDeviceBattery.java65
-rw-r--r--core/java/android/hardware/input/InputManager.java35
-rw-r--r--core/java/android/view/InputDevice.java28
-rw-r--r--core/jni/android_view_InputDevice.cpp10
-rw-r--r--core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java2
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java14
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp25
-rw-r--r--services/tests/servicestests/src/com/android/server/VibratorServiceTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java4
12 files changed, 265 insertions, 12 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 88c961afb8e0..d1b9716b4cd3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -16803,6 +16803,18 @@ package android.graphics.text {
package android.hardware {
+ public abstract class Battery {
+ ctor public Battery();
+ method @FloatRange(from=-1.0F, to=1.0f) public abstract float getCapacity();
+ method public abstract int getStatus();
+ method public abstract boolean hasBattery();
+ field public static final int STATUS_CHARGING = 2; // 0x2
+ field public static final int STATUS_DISCHARGING = 3; // 0x3
+ field public static final int STATUS_FULL = 5; // 0x5
+ field public static final int STATUS_NOT_CHARGING = 4; // 0x4
+ field public static final int STATUS_UNKNOWN = 1; // 0x1
+ }
+
@Deprecated public class Camera {
method @Deprecated public final void addCallbackBuffer(byte[]);
method @Deprecated public final void autoFocus(android.hardware.Camera.AutoFocusCallback);
@@ -46363,6 +46375,7 @@ package android.view {
public final class InputDevice implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public android.hardware.Battery getBattery();
method public int getControllerNumber();
method public String getDescriptor();
method public static android.view.InputDevice getDevice(int);
diff --git a/core/java/android/hardware/Battery.java b/core/java/android/hardware/Battery.java
new file mode 100644
index 000000000000..24c8d76a9813
--- /dev/null
+++ b/core/java/android/hardware/Battery.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+import android.os.BatteryManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * The Battery class is a representation of a single battery on a device.
+ */
+public abstract class Battery {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "STATUS_" }, value = {
+ STATUS_UNKNOWN,
+ STATUS_CHARGING,
+ STATUS_DISCHARGING,
+ STATUS_NOT_CHARGING,
+ STATUS_FULL
+ })
+ public @interface BatteryStatus {
+ }
+
+ /** Battery status is unknown. */
+ public static final int STATUS_UNKNOWN = BatteryManager.BATTERY_STATUS_UNKNOWN;
+ /** Battery is charging. */
+ public static final int STATUS_CHARGING = BatteryManager.BATTERY_STATUS_CHARGING;
+ /** Battery is discharging. */
+ public static final int STATUS_DISCHARGING = BatteryManager.BATTERY_STATUS_DISCHARGING;
+ /** Battery is connected to power but not charging. */
+ public static final int STATUS_NOT_CHARGING = BatteryManager.BATTERY_STATUS_NOT_CHARGING;
+ /** Battery is full. */
+ public static final int STATUS_FULL = BatteryManager.BATTERY_STATUS_FULL;
+
+ /**
+ * Check whether the hardware has a battery.
+ *
+ * @return True if the hardware has a battery, else false.
+ */
+ public abstract boolean hasBattery();
+
+ /**
+ * Get the battery status.
+ *
+ * @return the battery status.
+ */
+ public abstract @BatteryStatus int getStatus();
+
+ /**
+ * Get remaining battery capacity as float percentage [0.0f, 1.0f] of total capacity
+ * Returns -1 when battery capacity can't be read.
+ *
+ * @return the battery capacity.
+ */
+ public abstract @FloatRange(from = -1.0f, to = 1.0f) float getCapacity();
+}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index b39df4d2b6bf..c69c47f80d01 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -93,6 +93,10 @@ interface IInputManager {
int[] getVibratorIds(int deviceId);
boolean isVibrating(int deviceId);
+ // Input device battery query.
+ int getBatteryStatus(int deviceId);
+ int getBatteryCapacity(int deviceId);
+
void setPointerIconType(int typeId);
void setCustomPointerIcon(in PointerIcon icon);
diff --git a/core/java/android/hardware/input/InputDeviceBattery.java b/core/java/android/hardware/input/InputDeviceBattery.java
new file mode 100644
index 000000000000..0fe124e2c0ce
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceBattery.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.IInputConstants.INVALID_BATTERY_CAPACITY;
+
+import android.hardware.Battery;
+
+/**
+ * Battery implementation for input devices.
+ *
+ * @hide
+ */
+public final class InputDeviceBattery extends Battery {
+ private static final float NULL_BATTERY_CAPACITY = -1.0f;
+
+ private final InputManager mInputManager;
+ private final int mDeviceId;
+ private final boolean mHasBattery;
+
+ InputDeviceBattery(InputManager inputManager, int deviceId, boolean hasBattery) {
+ mInputManager = inputManager;
+ mDeviceId = deviceId;
+ mHasBattery = hasBattery;
+ }
+
+ @Override
+ public boolean hasBattery() {
+ return mHasBattery;
+ }
+
+ @Override
+ public int getStatus() {
+ if (!mHasBattery) {
+ return BATTERY_STATUS_UNKNOWN;
+ }
+ return mInputManager.getBatteryStatus(mDeviceId);
+ }
+
+ @Override
+ public float getCapacity() {
+ if (mHasBattery) {
+ int capacity = mInputManager.getBatteryCapacity(mDeviceId);
+ if (capacity != INVALID_BATTERY_CAPACITY) {
+ return (float) capacity / 100.0f;
+ }
+ }
+ return NULL_BATTERY_CAPACITY;
+ }
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index e63dc112233f..185c59d8ccfc 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1245,6 +1245,32 @@ public final class InputManager {
}
/**
+ * Get the battery status of the input device
+ * @param deviceId The input device ID
+ * @hide
+ */
+ public int getBatteryStatus(int deviceId) {
+ try {
+ return mIm.getBatteryStatus(deviceId);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Get the remaining battery capacity of the input device
+ * @param deviceId The input device ID
+ * @hide
+ */
+ public int getBatteryCapacity(int deviceId) {
+ try {
+ return mIm.getBatteryCapacity(deviceId);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Add a runtime association between the input port and the display port. This overrides any
* static associations.
* @param inputPort The port of the input device.
@@ -1471,6 +1497,15 @@ public final class InputManager {
}
/**
+ * Gets a battery object associated with an input device, assuming it has one.
+ * @return The battery, never null.
+ * @hide
+ */
+ public InputDeviceBattery getInputDeviceBattery(int deviceId, boolean hasBattery) {
+ return new InputDeviceBattery(this, deviceId, hasBattery);
+ }
+
+ /**
* Listens for changes in input devices.
*/
public interface InputDeviceListener {
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 242188991e27..bc03222f390d 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -22,6 +22,7 @@ import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.hardware.Battery;
import android.hardware.SensorManager;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
@@ -73,6 +74,7 @@ public final class InputDevice implements Parcelable {
private final boolean mHasMicrophone;
private final boolean mHasButtonUnderPad;
private final boolean mHasSensor;
+ private final boolean mHasBattery;
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
@GuardedBy("mMotionRanges")
@@ -84,6 +86,9 @@ public final class InputDevice implements Parcelable {
@GuardedBy("mMotionRanges")
private SensorManager mSensorManager;
+ @GuardedBy("mMotionRanges")
+ private Battery mBattery;
+
/**
* A mask for input source classes.
*
@@ -455,7 +460,7 @@ public final class InputDevice implements Parcelable {
public InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
- boolean hasButtonUnderPad, boolean hasSensor) {
+ boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery) {
mId = id;
mGeneration = generation;
mControllerNumber = controllerNumber;
@@ -471,6 +476,7 @@ public final class InputDevice implements Parcelable {
mHasMicrophone = hasMicrophone;
mHasButtonUnderPad = hasButtonUnderPad;
mHasSensor = hasSensor;
+ mHasBattery = hasBattery;
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
}
@@ -490,6 +496,7 @@ public final class InputDevice implements Parcelable {
mHasMicrophone = in.readInt() != 0;
mHasButtonUnderPad = in.readInt() != 0;
mHasSensor = in.readInt() != 0;
+ mHasBattery = in.readInt() != 0;
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
int numRanges = in.readInt();
@@ -837,6 +844,22 @@ public final class InputDevice implements Parcelable {
}
/**
+ * Gets the battery object associated with the device, if there is one.
+ * Even if the device does not have a battery, the result is never null.
+ * Use {@link Battery#hasBattery} to determine whether a battery is
+ * present.
+ *
+ * @return The battery object associated with the device, never null.
+ */
+ @NonNull
+ public Battery getBattery() {
+ if (mBattery == null) {
+ mBattery = InputManager.getInstance().getInputDeviceBattery(mId, mHasBattery);
+ }
+ return mBattery;
+ }
+
+ /**
* Gets the sensor manager service associated with the input device.
* Even if the device does not have a sensor, the result is never null.
* Use {@link SensorManager#getSensorList} to get a full list of all supported sensors.
@@ -1058,6 +1081,7 @@ public final class InputDevice implements Parcelable {
out.writeInt(mHasMicrophone ? 1 : 0);
out.writeInt(mHasButtonUnderPad ? 1 : 0);
out.writeInt(mHasSensor ? 1 : 0);
+ out.writeInt(mHasBattery ? 1 : 0);
final int numRanges = mMotionRanges.size();
out.writeInt(numRanges);
@@ -1104,6 +1128,8 @@ public final class InputDevice implements Parcelable {
description.append(" Has Sensor: ").append(mHasSensor).append("\n");
+ description.append(" Has battery: ").append(mHasBattery).append("\n");
+
description.append(" Has mic: ").append(mHasMicrophone).append("\n");
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 4eaa016df6f2..9cc72437a023 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -70,7 +70,8 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
deviceInfo.isExternal(), deviceInfo.getSources(),
deviceInfo.getKeyboardType(), kcmObj.get(),
deviceInfo.hasVibrator(), hasMic,
- deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor()));
+ deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor(),
+ deviceInfo.hasBattery()));
const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
for (const InputDeviceInfo::MotionRange& range: ranges) {
@@ -90,9 +91,10 @@ int register_android_view_InputDevice(JNIEnv* env)
gInputDeviceClassInfo.clazz = FindClassOrDie(env, "android/view/InputDevice");
gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz);
- gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
- "(IIILjava/lang/String;IILjava/lang/"
- "String;ZIILandroid/view/KeyCharacterMap;ZZZZ)V");
+ gInputDeviceClassInfo.ctor =
+ GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
+ "(IIILjava/lang/String;IILjava/lang/"
+ "String;ZIILandroid/view/KeyCharacterMap;ZZZZZ)V");
gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz,
"addMotionRange", "(IIFFFFF)V");
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
index b319886ae466..341ee37aee39 100644
--- a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
+++ b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
@@ -149,7 +149,7 @@ public class InputDeviceSensorManagerTest {
0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */,
false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
- true /* hasSensor */);
+ true /* hasSensor */, false /* hasBattery */);
assertTrue(d.hasSensor());
return d;
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index f6e08fbaf379..2e4200c1f7d9 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -289,6 +289,8 @@ public class InputManagerService extends IInputManager.Stub
private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
private static native boolean nativeIsVibrating(long ptr, int deviceId);
private static native int[] nativeGetVibratorIds(long ptr, int deviceId);
+ private static native int nativeGetBatteryCapacity(long ptr, int deviceId);
+ private static native int nativeGetBatteryStatus(long ptr, int deviceId);
private static native void nativeReloadKeyboardLayouts(long ptr);
private static native void nativeReloadDeviceAliases(long ptr);
private static native String nativeDump(long ptr);
@@ -2008,6 +2010,18 @@ public class InputManagerService extends IInputManager.Stub
// Binder call
@Override
+ public int getBatteryStatus(int deviceId) {
+ return nativeGetBatteryStatus(mPtr, deviceId);
+ }
+
+ // Binder call
+ @Override
+ public int getBatteryCapacity(int deviceId) {
+ return nativeGetBatteryCapacity(mPtr, deviceId);
+ }
+
+ // Binder call
+ @Override
public void setPointerIconType(int iconId) {
nativeSetPointerIconType(mPtr, iconId);
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index dc15b0749bb1..5b587e9859d8 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -26,14 +26,14 @@
// Log debug messages about InputDispatcherPolicy
#define DEBUG_INPUT_DISPATCHER_POLICY 0
-
-#include <atomic>
-#include <cinttypes>
-#include <limits.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
+#include <android/os/IInputConstants.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
+#include <limits.h>
+#include <atomic>
+#include <cinttypes>
#include <utils/Log.h>
#include <utils/Looper.h>
@@ -46,6 +46,7 @@
#include <input/SpriteController.h>
#include <ui/Region.h>
+#include <batteryservice/include/batteryservice/BatteryServiceConstants.h>
#include <inputflinger/InputManager.h>
#include <android_os_MessageQueue.h>
@@ -1908,6 +1909,20 @@ static jintArray nativeGetVibratorIds(JNIEnv* env, jclass clazz, jlong ptr, jint
return vibIdArray;
}
+static jint nativeGetBatteryCapacity(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ std::optional<int32_t> ret = im->getInputManager()->getReader()->getBatteryCapacity(deviceId);
+ return static_cast<jint>(ret.value_or(android::os::IInputConstants::INVALID_BATTERY_CAPACITY));
+}
+
+static jint nativeGetBatteryStatus(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ std::optional<int32_t> ret = im->getInputManager()->getReader()->getBatteryStatus(deviceId);
+ return static_cast<jint>(ret.value_or(BATTERY_STATUS_UNKNOWN));
+}
+
static void nativeReloadKeyboardLayouts(JNIEnv* /* env */,
jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -2163,6 +2178,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
{"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate},
{"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating},
{"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds},
+ {"nativeGetBatteryCapacity", "(JI)I", (void*)nativeGetBatteryCapacity},
+ {"nativeGetBatteryStatus", "(JI)I", (void*)nativeGetBatteryStatus},
{"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts},
{"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases},
{"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump},
diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
index 743848c2453c..2932926b0b05 100644
--- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
@@ -745,7 +745,8 @@ public class VibratorServiceTest {
private InputDevice createInputDeviceWithVibrator(int id) {
return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
- null, /* hasVibrator= */ true, false, false, false /* hasSensor */);
+ null, /* hasVibrator= */ true, false, false, false /* hasSensor */,
+ false /* hasBattery */);
}
private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
index 28d313b4d4b5..e71c2f5ba8da 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
@@ -294,6 +294,8 @@ public class InputDeviceDelegateTest {
private InputDevice createInputDevice(int id, boolean hasVibrator) {
return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
- null, hasVibrator, false, false, false /* hasSensor */);
+ null, hasVibrator, false, false, false /* hasSensor */, false /* hasBattery */);
+
+
}
}