From 2c31d40dce96150287caca76667230f03f01cae1 Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Tue, 4 Apr 2023 03:34:47 -0700 Subject: [PATCH] Pipe potential wakeup events from sensor service Sensor events from wakeup sensors can cause CPU wakeups. Exposing an aidl method to receive notification of such events from sensor service native code. Creating a helper method to retreive a Sensor object given a sensor handle in SensorManager. These notifications will be used to attribute to a wakeup in CpuWakeupStats in a subsequent change. Test: Manually trigger sensor events and check logcat. Bug: 275436924 Change-Id: Ia16fa43dcd82e9a869db3b510292694a51e2b995 --- core/java/android/hardware/SensorManager.java | 21 +++++++++++++++++ .../android/hardware/SystemSensorManager.java | 6 +++++ .../android/internal/app/IBatteryStats.aidl | 1 + .../server/am/BatteryStatsService.java | 23 ++++++++++++++++++- 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 6d8c4a93b44eb..c2aebd7cfaca1 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -449,6 +449,27 @@ public abstract class SensorManager { return list; } + /** + * Returns the {@link Sensor} object identified by the given sensor handle. + * + * The raw sensor handle integer is an implementation detail and as such this method should only + * be used by internal system components. + * + * @param sensorHandle The integer handle uniquely identifying the sensor. + * @return A Sensor object identified by the given {@code sensorHandle}, if such a sensor + * exists, {@code null} otherwise. + * + * @hide + */ + public @Nullable Sensor getSensorByHandle(int sensorHandle) { + for (final Sensor sensor : getFullSensorList()) { + if (sensor.getHandle() == sensorHandle) { + return sensor; + } + } + return null; + } + /** * Use this method to get a list of available dynamic sensors of a certain type. * Make multiple calls to get sensors of different types or use diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 73157e62cb562..d8ab6f7da82da 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -220,6 +220,12 @@ public class SystemSensorManager extends SensorManager { return fullList; } + /** @hide */ + @Override + public Sensor getSensorByHandle(int sensorHandle) { + return mHandleToSensor.get(sensorHandle); + } + /** @hide */ @Override protected List getFullDynamicSensorList() { diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 787b594af6bb6..65394bd87d642 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -63,6 +63,7 @@ interface IBatteryStats { void noteResetCamera(); @EnforcePermission("UPDATE_DEVICE_STATS") void noteResetFlashlight(); + void noteWakeupSensorEvent(long elapsedNanos, int uid, int handle); // Remaining methods are only used in Java. @EnforcePermission("BATTERY_STATS") diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index ed297d0867a14..b1ca4fef85f51 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -37,6 +37,8 @@ import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.hardware.Sensor; +import android.hardware.SensorManager; import android.hardware.power.stats.PowerEntity; import android.hardware.power.stats.State; import android.hardware.power.stats.StateResidency; @@ -149,7 +151,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub private final PowerProfile mPowerProfile; final BatteryStatsImpl mStats; - @GuardedBy("mWakeupStats") final CpuWakeupStats mCpuWakeupStats; private final BatteryUsageStatsStore mBatteryUsageStatsStore; private final BatteryStatsImpl.UserInfoProvider mUserManagerUserInfoProvider; @@ -1262,6 +1263,26 @@ public final class BatteryStatsService extends IBatteryStats.Stub null, sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__ON); } + @Override + public void noteWakeupSensorEvent(long elapsedNanos, int uid, int sensorHandle) { + final int callingUid = Binder.getCallingUid(); + if (callingUid != Process.SYSTEM_UID) { + throw new SecurityException("Calling uid " + callingUid + " is not system uid"); + } + + final SensorManager sm = mContext.getSystemService(SensorManager.class); + final Sensor sensor = sm.getSensorByHandle(sensorHandle); + if (sensor == null) { + Slog.w(TAG, "Unknown sensor handle " + sensorHandle + + " received in noteWakeupSensorEvent"); + return; + } + Slog.i(TAG, "Sensor " + sensor + " wakeup event at " + elapsedNanos + " sent to uid " + + uid); + // TODO (b/275436924): Remove log and pipe to CpuWakeupStats for wakeup attribution + // This method should return as quickly as possible. Use mHandler#post to do longer work. + } + @Override @EnforcePermission(UPDATE_DEVICE_STATS) public void noteStopSensor(final int uid, final int sensor) {