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
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 6d8c4a9..c2aebd7 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -450,6 +450,27 @@
     }
 
     /**
+     * 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
      * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all dynamic sensors.
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 73157e6..d8ab6f7 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -222,6 +222,12 @@
 
     /** @hide */
     @Override
+    public Sensor getSensorByHandle(int sensorHandle) {
+        return mHandleToSensor.get(sensorHandle);
+    }
+
+    /** @hide */
+    @Override
     protected List<Sensor> getFullDynamicSensorList() {
         // only set up broadcast receiver if the application tries to find dynamic sensors or
         // explicitly register a DynamicSensorCallback
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 787b594..65394bd 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -63,6 +63,7 @@
     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 ed297d0..b1ca4fe 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.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 @@
 
     private final PowerProfile mPowerProfile;
     final BatteryStatsImpl mStats;
-    @GuardedBy("mWakeupStats")
     final CpuWakeupStats mCpuWakeupStats;
     private final BatteryUsageStatsStore mBatteryUsageStatsStore;
     private final BatteryStatsImpl.UserInfoProvider mUserManagerUserInfoProvider;
@@ -1263,6 +1264,26 @@
     }
 
     @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) {
         super.noteStopSensor_enforcePermission();