Merge "New API methods to access external battery info" into sc-dev

This commit is contained in:
Chris Ye
2021-02-02 06:42:37 +00:00
committed by Android (Google) Code Review
12 changed files with 265 additions and 12 deletions

View File

@@ -16803,6 +16803,18 @@ package android.graphics.text {
package android.hardware { 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 { @Deprecated public class Camera {
method @Deprecated public final void addCallbackBuffer(byte[]); method @Deprecated public final void addCallbackBuffer(byte[]);
method @Deprecated public final void autoFocus(android.hardware.Camera.AutoFocusCallback); 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 { public final class InputDevice implements android.os.Parcelable {
method public int describeContents(); method public int describeContents();
method @NonNull public android.hardware.Battery getBattery();
method public int getControllerNumber(); method public int getControllerNumber();
method public String getDescriptor(); method public String getDescriptor();
method public static android.view.InputDevice getDevice(int); method public static android.view.InputDevice getDevice(int);

View File

@@ -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();
}

View File

@@ -93,6 +93,10 @@ interface IInputManager {
int[] getVibratorIds(int deviceId); int[] getVibratorIds(int deviceId);
boolean isVibrating(int deviceId); boolean isVibrating(int deviceId);
// Input device battery query.
int getBatteryStatus(int deviceId);
int getBatteryCapacity(int deviceId);
void setPointerIconType(int typeId); void setPointerIconType(int typeId);
void setCustomPointerIcon(in PointerIcon icon); void setCustomPointerIcon(in PointerIcon icon);

View File

@@ -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;
}
}

View File

@@ -1244,6 +1244,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 * Add a runtime association between the input port and the display port. This overrides any
* static associations. * static associations.
@@ -1470,6 +1496,15 @@ public final class InputManager {
return mInputDeviceSensorManager.getSensorManager(deviceId); return mInputDeviceSensorManager.getSensorManager(deviceId);
} }
/**
* 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. * Listens for changes in input devices.
*/ */

View File

@@ -22,6 +22,7 @@ import android.annotation.RequiresPermission;
import android.annotation.TestApi; import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context; import android.content.Context;
import android.hardware.Battery;
import android.hardware.SensorManager; import android.hardware.SensorManager;
import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager; import android.hardware.input.InputManager;
@@ -73,6 +74,7 @@ public final class InputDevice implements Parcelable {
private final boolean mHasMicrophone; private final boolean mHasMicrophone;
private final boolean mHasButtonUnderPad; private final boolean mHasButtonUnderPad;
private final boolean mHasSensor; private final boolean mHasSensor;
private final boolean mHasBattery;
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>(); private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
@GuardedBy("mMotionRanges") @GuardedBy("mMotionRanges")
@@ -84,6 +86,9 @@ public final class InputDevice implements Parcelable {
@GuardedBy("mMotionRanges") @GuardedBy("mMotionRanges")
private SensorManager mSensorManager; private SensorManager mSensorManager;
@GuardedBy("mMotionRanges")
private Battery mBattery;
/** /**
* A mask for input source classes. * 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, public InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
int productId, String descriptor, boolean isExternal, int sources, int keyboardType, int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone, KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
boolean hasButtonUnderPad, boolean hasSensor) { boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery) {
mId = id; mId = id;
mGeneration = generation; mGeneration = generation;
mControllerNumber = controllerNumber; mControllerNumber = controllerNumber;
@@ -471,6 +476,7 @@ public final class InputDevice implements Parcelable {
mHasMicrophone = hasMicrophone; mHasMicrophone = hasMicrophone;
mHasButtonUnderPad = hasButtonUnderPad; mHasButtonUnderPad = hasButtonUnderPad;
mHasSensor = hasSensor; mHasSensor = hasSensor;
mHasBattery = hasBattery;
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId); mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
} }
@@ -490,6 +496,7 @@ public final class InputDevice implements Parcelable {
mHasMicrophone = in.readInt() != 0; mHasMicrophone = in.readInt() != 0;
mHasButtonUnderPad = in.readInt() != 0; mHasButtonUnderPad = in.readInt() != 0;
mHasSensor = in.readInt() != 0; mHasSensor = in.readInt() != 0;
mHasBattery = in.readInt() != 0;
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId); mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
int numRanges = in.readInt(); int numRanges = in.readInt();
@@ -836,6 +843,22 @@ public final class InputDevice implements Parcelable {
return mVibratorManager; return mVibratorManager;
} }
/**
* 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. * Gets the sensor manager service associated with the input device.
* Even if the device does not have a sensor, the result is never null. * Even if the device does not have a sensor, the result is never null.
@@ -1058,6 +1081,7 @@ public final class InputDevice implements Parcelable {
out.writeInt(mHasMicrophone ? 1 : 0); out.writeInt(mHasMicrophone ? 1 : 0);
out.writeInt(mHasButtonUnderPad ? 1 : 0); out.writeInt(mHasButtonUnderPad ? 1 : 0);
out.writeInt(mHasSensor ? 1 : 0); out.writeInt(mHasSensor ? 1 : 0);
out.writeInt(mHasBattery ? 1 : 0);
final int numRanges = mMotionRanges.size(); final int numRanges = mMotionRanges.size();
out.writeInt(numRanges); out.writeInt(numRanges);
@@ -1104,6 +1128,8 @@ public final class InputDevice implements Parcelable {
description.append(" Has Sensor: ").append(mHasSensor).append("\n"); 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(" Has mic: ").append(mHasMicrophone).append("\n");
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" ("); description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");

View File

@@ -70,7 +70,8 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
deviceInfo.isExternal(), deviceInfo.getSources(), deviceInfo.isExternal(), deviceInfo.getSources(),
deviceInfo.getKeyboardType(), kcmObj.get(), deviceInfo.getKeyboardType(), kcmObj.get(),
deviceInfo.hasVibrator(), hasMic, deviceInfo.hasVibrator(), hasMic,
deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor())); deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor(),
deviceInfo.hasBattery()));
const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
for (const InputDeviceInfo::MotionRange& range: ranges) { 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 = FindClassOrDie(env, "android/view/InputDevice");
gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz); gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz);
gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>", gInputDeviceClassInfo.ctor =
GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
"(IIILjava/lang/String;IILjava/lang/" "(IIILjava/lang/String;IILjava/lang/"
"String;ZIILandroid/view/KeyCharacterMap;ZZZZ)V"); "String;ZIILandroid/view/KeyCharacterMap;ZZZZZ)V");
gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz,
"addMotionRange", "(IIFFFFF)V"); "addMotionRange", "(IIFFFFF)V");

View File

@@ -149,7 +149,7 @@ public class InputDeviceSensorManagerTest {
0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */, 0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */, 0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */,
false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */, false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
true /* hasSensor */); true /* hasSensor */, false /* hasBattery */);
assertTrue(d.hasSensor()); assertTrue(d.hasSensor());
return d; return d;
} }

View File

@@ -289,6 +289,8 @@ public class InputManagerService extends IInputManager.Stub
private static native void nativeCancelVibrate(long ptr, int deviceId, int token); private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
private static native boolean nativeIsVibrating(long ptr, int deviceId); private static native boolean nativeIsVibrating(long ptr, int deviceId);
private static native int[] nativeGetVibratorIds(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 nativeReloadKeyboardLayouts(long ptr);
private static native void nativeReloadDeviceAliases(long ptr); private static native void nativeReloadDeviceAliases(long ptr);
private static native String nativeDump(long ptr); private static native String nativeDump(long ptr);
@@ -2006,6 +2008,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 // Binder call
@Override @Override
public void setPointerIconType(int iconId) { public void setPointerIconType(int iconId) {

View File

@@ -26,14 +26,14 @@
// Log debug messages about InputDispatcherPolicy // Log debug messages about InputDispatcherPolicy
#define DEBUG_INPUT_DISPATCHER_POLICY 0 #define DEBUG_INPUT_DISPATCHER_POLICY 0
#include <atomic>
#include <cinttypes>
#include <limits.h>
#include <android-base/parseint.h> #include <android-base/parseint.h>
#include <android-base/stringprintf.h> #include <android-base/stringprintf.h>
#include <android/os/IInputConstants.h>
#include <android_runtime/AndroidRuntime.h> #include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h> #include <android_runtime/Log.h>
#include <limits.h>
#include <atomic>
#include <cinttypes>
#include <utils/Log.h> #include <utils/Log.h>
#include <utils/Looper.h> #include <utils/Looper.h>
@@ -46,6 +46,7 @@
#include <input/SpriteController.h> #include <input/SpriteController.h>
#include <ui/Region.h> #include <ui/Region.h>
#include <batteryservice/include/batteryservice/BatteryServiceConstants.h>
#include <inputflinger/InputManager.h> #include <inputflinger/InputManager.h>
#include <android_os_MessageQueue.h> #include <android_os_MessageQueue.h>
@@ -1908,6 +1909,20 @@ static jintArray nativeGetVibratorIds(JNIEnv* env, jclass clazz, jlong ptr, jint
return vibIdArray; 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 */, static void nativeReloadKeyboardLayouts(JNIEnv* /* env */,
jclass /* clazz */, jlong ptr) { jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -2163,6 +2178,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
{"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate}, {"nativeCancelVibrate", "(JII)V", (void*)nativeCancelVibrate},
{"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating}, {"nativeIsVibrating", "(JI)Z", (void*)nativeIsVibrating},
{"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds}, {"nativeGetVibratorIds", "(JI)[I", (void*)nativeGetVibratorIds},
{"nativeGetBatteryCapacity", "(JI)I", (void*)nativeGetBatteryCapacity},
{"nativeGetBatteryStatus", "(JI)I", (void*)nativeGetBatteryStatus},
{"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts}, {"nativeReloadKeyboardLayouts", "(J)V", (void*)nativeReloadKeyboardLayouts},
{"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases}, {"nativeReloadDeviceAliases", "(J)V", (void*)nativeReloadDeviceAliases},
{"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump}, {"nativeDump", "(J)Ljava/lang/String;", (void*)nativeDump},

View File

@@ -745,7 +745,8 @@ public class VibratorServiceTest {
private InputDevice createInputDeviceWithVibrator(int id) { private InputDevice createInputDeviceWithVibrator(int id) {
return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0, 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) { private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {

View File

@@ -294,6 +294,8 @@ public class InputDeviceDelegateTest {
private InputDevice createInputDevice(int id, boolean hasVibrator) { private InputDevice createInputDevice(int id, boolean hasVibrator) {
return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0, 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 */);
} }
} }