Add additional logging for temperature readings.

In order to determine how often devices are reaching various
temperatures, we now cache the last hour of temperature readings.
Once it's been an hour, we calculate the avg/min/max and log the results.

Additionally, this CL adds some logging to show how the temperature has
changed over time during the one hour window and what the charging status
is when the notification shows.

Bug: 34510881, 34379897
Change-Id: If8c7d39452034313fd01dea0c8d97c7b55b3cb9c
Merged-In: I62a5ccc92122f5d2955a52677740e896f0d7892b
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 67798e9..13b8bd6 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -33,6 +33,7 @@
 import android.text.format.DateUtils;
 import android.util.Log;
 import android.util.Slog;
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -45,6 +46,8 @@
     static final String TAG = "PowerUI";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final long TEMPERATURE_INTERVAL = 30 * DateUtils.SECOND_IN_MILLIS;
+    private static final long TEMPERATURE_LOGGING_INTERVAL = DateUtils.HOUR_IN_MILLIS;
+    private static final int MAX_RECENT_TEMPS = 125; // TEMPERATURE_LOGGING_INTERVAL plus a buffer
 
     private final Handler mHandler = new Handler();
     private final Receiver mReceiver = new Receiver();
@@ -62,7 +65,10 @@
 
     private long mScreenOffTime = -1;
 
-    private float mThrottlingTemp;
+    private float mThresholdTemp;
+    private float[] mRecentTemps = new float[MAX_RECENT_TEMPS];
+    private int mNumTemps;
+    private long mNextLogTime;
 
     public void start() {
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -228,10 +234,10 @@
             return;
         }
 
-        mThrottlingTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
+        mThresholdTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
                 resources.getInteger(R.integer.config_warningTemperature));
 
-        if (mThrottlingTemp < 0f) {
+        if (mThresholdTemp < 0f) {
             // Get the throttling temperature. No need to check if we're not throttling.
             float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
                     HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
@@ -241,41 +247,86 @@
                     || throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
                 return;
             }
-            mThrottlingTemp = throttlingTemps[0];
+            mThresholdTemp = throttlingTemps[0];
         }
+        setNextLogTime();
 
         // We have passed all of the checks, start checking the temp
         updateTemperatureWarning();
     }
 
     private void updateTemperatureWarning() {
-        PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
-        if (phoneStatusBar != null && phoneStatusBar.isDeviceInVrMode()) {
-            // ensure the warning isn't showing, since VR shows its own warning
-            mWarnings.dismissTemperatureWarning();
-        } else {
-            float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
-                    HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
-                    HardwarePropertiesManager.TEMPERATURE_CURRENT);
-            boolean shouldShowTempWarning = false;
-            for (float temp : temps) {
-                if (temp >= mThrottlingTemp) {
-                    Slog.i(TAG, "currentTemp=" + temp + ", throttlingTemp=" + mThrottlingTemp);
-                    shouldShowTempWarning = true;
-                    break;
-                }
-            }
-            if (shouldShowTempWarning) {
+        float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+                HardwarePropertiesManager.TEMPERATURE_CURRENT);
+        if (temps.length != 0) {
+            float temp = temps[0];
+            mRecentTemps[mNumTemps++] = temp;
+
+            PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
+            if (phoneStatusBar != null && !phoneStatusBar.isDeviceInVrMode()
+                    && temp >= mThresholdTemp) {
+                logAtTemperatureThreshold(temp);
                 mWarnings.showTemperatureWarning();
             } else {
                 mWarnings.dismissTemperatureWarning();
             }
         }
 
-        // TODO: skip this when in VR mode since we already get a callback
+        logTemperatureStats();
+
         mHandler.postDelayed(this::updateTemperatureWarning, TEMPERATURE_INTERVAL);
     }
 
+    private void logAtTemperatureThreshold(float temp) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("currentTemp=").append(temp)
+                .append(",thresholdTemp=").append(mThresholdTemp)
+                .append(",batteryStatus=").append(mBatteryStatus)
+                .append(",recentTemps=");
+        for (int i = 0; i < mNumTemps; i++) {
+            sb.append(mRecentTemps[i]).append(',');
+        }
+        Slog.i(TAG, sb.toString());
+    }
+
+    /**
+     * Calculates and logs min, max, and average
+     * {@link HardwarePropertiesManager#DEVICE_TEMPERATURE_SKIN} over the past
+     * {@link #TEMPERATURE_LOGGING_INTERVAL}.
+     */
+    private void logTemperatureStats() {
+        if (mNextLogTime > System.currentTimeMillis() && mNumTemps != MAX_RECENT_TEMPS) {
+            return;
+        }
+
+        if (mNumTemps > 0) {
+            float sum = mRecentTemps[0], min = mRecentTemps[0], max = mRecentTemps[0];
+            for (int i = 1; i < mNumTemps; i++) {
+                float temp = mRecentTemps[i];
+                sum += temp;
+                if (temp > max) {
+                    max = temp;
+                }
+                if (temp < min) {
+                    min = temp;
+                }
+            }
+
+            float avg = sum / mNumTemps;
+            Slog.i(TAG, "avg=" + avg + ",min=" + min + ",max=" + max);
+            MetricsLogger.histogram(mContext, "device_skin_temp_avg", (int) avg);
+            MetricsLogger.histogram(mContext, "device_skin_temp_min", (int) min);
+            MetricsLogger.histogram(mContext, "device_skin_temp_max", (int) max);
+        }
+        setNextLogTime();
+        mNumTemps = 0;
+    }
+
+    private void setNextLogTime() {
+        mNextLogTime = System.currentTimeMillis() + TEMPERATURE_LOGGING_INTERVAL;
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.print("mLowBatteryAlertCloseLevel=");
         pw.println(mLowBatteryAlertCloseLevel);
@@ -302,8 +353,10 @@
                 Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
         pw.print("bucket: ");
         pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
-        pw.print("mThrottlingTemp=");
-        pw.println(Float.toString(mThrottlingTemp));
+        pw.print("mThresholdTemp=");
+        pw.println(Float.toString(mThresholdTemp));
+        pw.print("mNextLogTime=");
+        pw.println(Long.toString(mNextLogTime));
         mWarnings.dump(pw);
     }