Implement USB-C overheat warning
When device USB-C port is susceptible to short circuits and
overheating, pop up a warning dialog and keep showing until
user clicks OK button or see care steps.
Test: manually set the emulated temperature to trigger warning
Test: atest SystemUITests
Change-Id: I4f6080187196a9716f12a9817dc10d3265dc202b
Bug: 110134720
Bug: 116866524
Bug: 77790357
Bug: 117178820
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 452d09d..c181691 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14056,18 +14056,17 @@
public static final String SHOW_TEMPERATURE_WARNING = "show_temperature_warning";
/**
+ * Whether to show the usb high temperature alarm notification.
+ * @hide
+ */
+ public static final String SHOW_USB_TEMPERATURE_ALARM = "show_usb_temperature_alarm";
+
+ /**
* Temperature at which the high temperature warning notification should be shown.
* @hide
*/
public static final String WARNING_TEMPERATURE = "warning_temperature";
-
- /**
- * USB Temperature at which the high temperature alarm notification should be shown.
- * @hide
- */
- public static final String USB_ALARM_TEMPERATURE = "usb_alarm_temperature";
-
/**
* Whether the diskstats logging task is enabled/disabled.
* @hide
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index c9957f3..c37c9dc 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -918,8 +918,7 @@
// Temperature at which the high temperature warning notification should
// be shown.
optional SettingProto warning_temperature_level = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // USB temperature at which the high temperature alarm notification should be shown.
- optional SettingProto usb_alarm_temperature_level = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_usb_temperature_alarm = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional TemperatureWarning temperature_warning = 119;
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index c57b609..dc9cc0f 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -428,6 +428,7 @@
Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
Settings.Global.SHOW_TEMPERATURE_WARNING,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
Settings.Global.SIGNED_CONFIG_VERSION,
Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
@@ -502,7 +503,6 @@
Settings.Global.USER_SWITCHER_ENABLED,
Settings.Global.NETWORK_ACCESS_TIMEOUT_MS,
Settings.Global.WARNING_TEMPERATURE,
- Settings.Global.USB_ALARM_TEMPERATURE,
Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED,
Settings.Global.WEBVIEW_MULTIPROCESS,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index db4b131..2b8a136 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1350,11 +1350,11 @@
Settings.Global.SHOW_TEMPERATURE_WARNING,
GlobalSettingsProto.TemperatureWarning.SHOW_TEMPERATURE_WARNING);
dumpSetting(s, p,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
+ GlobalSettingsProto.TemperatureWarning.SHOW_USB_TEMPERATURE_ALARM);
+ dumpSetting(s, p,
Settings.Global.WARNING_TEMPERATURE,
GlobalSettingsProto.TemperatureWarning.WARNING_TEMPERATURE_LEVEL);
- dumpSetting(s, p,
- Settings.Global.USB_ALARM_TEMPERATURE,
- GlobalSettingsProto.TemperatureWarning.USB_ALARM_TEMPERATURE_LEVEL);
p.end(tempWarningToken);
final long tetherToken = p.start(GlobalSettingsProto.TETHER);
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 76eb85e..e7cbc16 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -328,16 +328,11 @@
<bool name="quick_settings_show_full_alarm">false</bool>
- <!-- Whether to show a warning notification when the device reaches a certain temperature. -->
+ <!-- Whether to show a warning notification when device's skin temperature is high. -->
<integer name="config_showTemperatureWarning">0</integer>
- <!-- Temp at which to show a warning notification if config_showTemperatureWarning is true.
- If < 0, uses the skin temperature sensor shutdown value from
- HardwarePropertiesManager#getDeviceTemperatures - config_warningTemperatureTolerance. -->
- <integer name="config_warningTemperature">-1</integer>
-
- <!-- Fudge factor for how much below the shutdown temp to show the warning. -->
- <integer name="config_warningTemperatureTolerance">2</integer>
+ <!-- Whether to show a alarm dialog when device's usb port is overheating. -->
+ <integer name="config_showUsbPortAlarm">0</integer>
<!-- Accessibility actions -->
<item type="id" name="action_split_task_to_left" />
@@ -484,4 +479,5 @@
</string-array>
<integer name="ongoing_appops_dialog_max_apps">5</integer>
+
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b4131d7..37ab9c9 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2115,6 +2115,14 @@
<string name="high_temp_notif_message">Some features limited while phone cools down</string>
<!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=300] -->
<string name="high_temp_dialog_message">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
+ <!-- Title for alarm dialog alerting user the usb adapter has reached a certain temperature that should disconnect charging cable immediately. [CHAR LIMIT=30] -->
+ <string name="high_temp_alarm_title">Unplug charger</string>
+ <!-- Text body for dialog alerting user the usb adapter has reached a certain temperature that should disconnect charging cable immediately. [CHAR LIMIT=300] -->
+ <string name="high_temp_alarm_notify_message">There\u2019s an issue charging this device. Unplug the power adapter, and take care as the cable may be warm.</string>
+ <!-- Text for See care steps button [CHAR LIMIT=300] -->
+ <string name="high_temp_alarm_help_care_steps">See care steps</string>
+ <!-- Text link directs to usb overheat help page. -->
+ <string name="high_temp_alarm_help_url" translatable="false">help_uri_usb_warm</string>
<!-- SysUI Tuner: Button to select lock screen shortcut [CHAR LIMIT=60] -->
<string name="lockscreen_shortcut_left">Left shortcut</string>
@@ -2375,5 +2383,4 @@
<string name="no_bubbles">Block</string>
<!-- Text used for button allowing user to approve / enable bubbles [CHAR LIMIT=20] -->
<string name="yes_bubbles">Allow</string>
-
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 50dda1c..fdb0b36 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -16,6 +16,7 @@
package com.android.systemui.power;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -41,6 +42,7 @@
import android.util.Log;
import android.util.Slog;
import android.view.View;
+import android.view.WindowManager;
import androidx.annotation.VisibleForTesting;
@@ -48,10 +50,13 @@
import com.android.settingslib.Utils;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.settingslib.utils.PowerUtil;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.util.NotificationChannels;
+import com.android.systemui.volume.Events;
import java.io.PrintWriter;
import java.text.NumberFormat;
@@ -118,6 +123,7 @@
private final Context mContext;
private final NotificationManager mNoMan;
private final PowerManager mPowerMan;
+ private final KeyguardManager mKeyguard;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Receiver mReceiver = new Receiver();
private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
@@ -141,6 +147,7 @@
private boolean mHighTempWarning;
private SystemUIDialog mHighTempDialog;
private SystemUIDialog mThermalShutdownDialog;
+ @VisibleForTesting SystemUIDialog mUsbHighTempDialog;
/**
*/
@@ -149,6 +156,7 @@
mContext = context;
mNoMan = mContext.getSystemService(NotificationManager.class);
mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mKeyguard = mContext.getSystemService(KeyguardManager.class);
mReceiver.init();
}
@@ -165,6 +173,8 @@
pw.print("mHighTempDialog="); pw.println(mHighTempDialog != null ? "not null" : null);
pw.print("mThermalShutdownDialog=");
pw.println(mThermalShutdownDialog != null ? "not null" : null);
+ pw.print("mUsbHighTempDialog=");
+ pw.println(mUsbHighTempDialog != null ? "not null" : null);
}
private int getLowBatteryAutoTriggerDefaultLevel() {
@@ -434,6 +444,53 @@
}
@Override
+ public void showUsbHighTemperatureAlarm() {
+ mHandler.post(() -> showUsbHighTemperatureAlarmInternal());
+ }
+
+ private void showUsbHighTemperatureAlarmInternal() {
+ if (mUsbHighTempDialog != null) {
+ return;
+ }
+
+ final SystemUIDialog d = new SystemUIDialog(mContext, R.style.Theme_SystemUI_Dialog_Alert);
+ d.setCancelable(false);
+ d.setIconAttribute(android.R.attr.alertDialogIcon);
+ d.setTitle(R.string.high_temp_alarm_title);
+ d.setShowForAllUsers(true);
+ d.setMessage(mContext.getString(R.string.high_temp_alarm_notify_message, ""));
+ d.setPositiveButton((com.android.internal.R.string.ok),
+ (dialogInterface, which) -> mUsbHighTempDialog = null);
+ d.setNegativeButton((R.string.high_temp_alarm_help_care_steps),
+ (dialogInterface, which) -> {
+ final String contextString = mContext.getString(
+ R.string.high_temp_alarm_help_url);
+ final Intent helpIntent = new Intent();
+ helpIntent.setClassName("com.android.settings",
+ "com.android.settings.HelpTrampoline");
+ helpIntent.putExtra(Intent.EXTRA_TEXT, contextString);
+ Dependency.get(ActivityStarter.class).startActivity(helpIntent,
+ true /* dismissShade */, resultCode -> {
+ mUsbHighTempDialog = null;
+ });
+ });
+ d.setOnDismissListener(dialogInterface -> {
+ mUsbHighTempDialog = null;
+ Events.writeEvent(mContext, Events.EVENT_DISMISS_USB_OVERHEAT_ALARM,
+ Events.DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED,
+ mKeyguard.isKeyguardLocked());
+ });
+ d.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ d.show();
+ mUsbHighTempDialog = d;
+
+ Events.writeEvent(mContext, Events.EVENT_SHOW_USB_OVERHEAT_ALARM,
+ Events.SHOW_REASON_USB_OVERHEAD_ALARM_CHANGED,
+ mKeyguard.isKeyguardLocked());
+ }
+
+ @Override
public void updateLowBatteryWarning() {
updateNotification();
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index c43f572..7312cbc 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -43,7 +43,6 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -82,26 +81,19 @@
private boolean mLowWarningShownThisChargeCycle;
private boolean mSevereWarningShownThisChargeCycle;
private Future mLastShowWarningTask;
+ private boolean mEnableSkinTemperatureWarning;
+ private boolean mEnableUsbTemperatureAlarm;
private int mLowBatteryAlertCloseLevel;
private final int[] mLowBatteryReminderLevels = new int[2];
private long mScreenOffTime = -1;
- private float mThresholdTemp;
- private float[] mRecentTemps = new float[MAX_RECENT_TEMPS];
- private int mNumTemps;
- private long mNextLogTime;
@VisibleForTesting IThermalService mThermalService;
@VisibleForTesting int mBatteryLevel = 100;
@VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
- // by using the same instance (method references are not guaranteed to be the same object
- // We create a method reference here so that we are guaranteed that we can remove a callback
- // each time they are created).
- private final Runnable mUpdateTempCallback = this::updateTemperatureWarning;
-
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mHardwarePropertiesManager = (HardwarePropertiesManager)
@@ -128,7 +120,7 @@
// to the temperature being too high.
showThermalShutdownDialog();
- initTemperatureWarning();
+ initTemperature();
}
@Override
@@ -137,7 +129,7 @@
// Safe to modify mLastConfiguration here as it's only updated by the main thread (here).
if ((mLastConfiguration.updateFrom(newConfig) & mask) != 0) {
- mHandler.post(this::initTemperatureWarning);
+ mHandler.post(this::initTemperature);
}
}
@@ -383,30 +375,16 @@
return canShowWarning || canShowSevereWarning;
}
- private void initTemperatureWarning() {
+ private void initTemperature() {
ContentResolver resolver = mContext.getContentResolver();
Resources resources = mContext.getResources();
- if (Settings.Global.getInt(resolver, Settings.Global.SHOW_TEMPERATURE_WARNING,
- resources.getInteger(R.integer.config_showTemperatureWarning)) == 0) {
- return;
- }
- mThresholdTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
- resources.getInteger(R.integer.config_warningTemperature));
-
- if (mThresholdTemp < 0f) {
- // Get the shutdown temperature, adjust for warning tolerance.
- float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
- HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
- HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
- if (throttlingTemps == null
- || throttlingTemps.length == 0
- || throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
- return;
- }
- mThresholdTemp = throttlingTemps[0] -
- resources.getInteger(R.integer.config_warningTemperatureTolerance);
- }
+ mEnableSkinTemperatureWarning = Settings.Global.getInt(resolver,
+ Settings.Global.SHOW_TEMPERATURE_WARNING,
+ resources.getInteger(R.integer.config_showTemperatureWarning)) != 0;
+ mEnableUsbTemperatureAlarm = Settings.Global.getInt(resolver,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
+ resources.getInteger(R.integer.config_showUsbPortAlarm)) != 0;
if (mThermalService == null) {
// Enable push notifications of throttling from vendor thermal
@@ -416,21 +394,27 @@
if (b != null) {
mThermalService = IThermalService.Stub.asInterface(b);
- try {
- mThermalService.registerThermalEventListenerWithType(
- new ThermalEventListener(), Temperature.TYPE_SKIN);
- } catch (RemoteException e) {
- // Should never happen.
- }
+ registerThermalEventListener();
} else {
Slog.w(TAG, "cannot find thermalservice, no throttling push notifications");
}
}
+ }
- setNextLogTime();
-
- // We have passed all of the checks, start checking the temp
- mHandler.post(mUpdateTempCallback);
+ @VisibleForTesting
+ void registerThermalEventListener() {
+ try {
+ if (mEnableSkinTemperatureWarning) {
+ mThermalService.registerThermalEventListenerWithType(
+ new ThermalEventSkinListener(), Temperature.TYPE_SKIN);
+ }
+ if (mEnableUsbTemperatureAlarm) {
+ mThermalService.registerThermalEventListenerWithType(
+ new ThermalEventUsbListener(), Temperature.TYPE_USB_PORT);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register thermal callback.", e);
+ }
}
private void showThermalShutdownDialog() {
@@ -440,81 +424,6 @@
}
}
- @VisibleForTesting
- protected void updateTemperatureWarning() {
- float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
- HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
- HardwarePropertiesManager.TEMPERATURE_CURRENT);
- if (temps.length != 0) {
- float temp = temps[0];
- mRecentTemps[mNumTemps++] = temp;
-
- StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null && !statusBar.isDeviceInVrMode()
- && temp >= mThresholdTemp) {
- logAtTemperatureThreshold(temp);
- mWarnings.showHighTemperatureWarning();
- } else {
- mWarnings.dismissHighTemperatureWarning();
- }
- }
-
- logTemperatureStats();
-
- // Remove any pending callbacks as we only want to enable one
- mHandler.removeCallbacks(mUpdateTempCallback);
- mHandler.postDelayed(mUpdateTempCallback, 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);
@@ -541,34 +450,80 @@
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
pw.print("bucket: ");
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
- pw.print("mThresholdTemp=");
- pw.println(Float.toString(mThresholdTemp));
- pw.print("mNextLogTime=");
- pw.println(Long.toString(mNextLogTime));
+ pw.print("mEnableSkinTemperatureWarning=");
+ pw.println(mEnableSkinTemperatureWarning);
+ pw.print("mEnableUsbTemperatureAlarm=");
+ pw.println(mEnableUsbTemperatureAlarm);
mWarnings.dump(pw);
}
public interface WarningsUI {
void update(int batteryLevel, int bucket, long screenOffTime);
+
void updateEstimate(Estimate estimate);
+
void updateThresholds(long lowThreshold, long severeThreshold);
+
void dismissLowBatteryWarning();
+
void showLowBatteryWarning(boolean playSound);
+
void dismissInvalidChargerWarning();
+
void showInvalidChargerWarning();
+
void updateLowBatteryWarning();
+
boolean isInvalidChargerWarningShowing();
+
void dismissHighTemperatureWarning();
+
void showHighTemperatureWarning();
+
+ /**
+ * Display USB overheat alarm
+ */
+ void showUsbHighTemperatureAlarm();
+
void showThermalShutdownWarning();
+
void dump(PrintWriter pw);
+
void userSwitched();
}
- // Thermal event received from vendor thermal management subsystem
- private final class ThermalEventListener extends IThermalEventListener.Stub {
+ // Thermal event received from thermal service manager subsystem
+ @VisibleForTesting
+ final class ThermalEventSkinListener extends IThermalEventListener.Stub {
@Override public void notifyThrottling(Temperature temp) {
- mHandler.post(mUpdateTempCallback);
+ int status = temp.getStatus();
+
+ if (status >= Temperature.THROTTLING_EMERGENCY) {
+ StatusBar statusBar = getComponent(StatusBar.class);
+ if (statusBar != null && !statusBar.isDeviceInVrMode()) {
+ mWarnings.showHighTemperatureWarning();
+ Slog.d(TAG, "ThermalEventSkinListener: notifyThrottling was called "
+ + ", current skin status = " + status
+ + ", temperature = " + temp.getValue());
+ }
+ } else {
+ mWarnings.dismissHighTemperatureWarning();
+ }
+ }
+ }
+
+ // Thermal event received from thermal service manager subsystem
+ @VisibleForTesting
+ final class ThermalEventUsbListener extends IThermalEventListener.Stub {
+ @Override public void notifyThrottling(Temperature temp) {
+ int status = temp.getStatus();
+
+ if (status >= Temperature.THROTTLING_EMERGENCY) {
+ mWarnings.showUsbHighTemperatureAlarm();
+ Slog.d(TAG, "ThermalEventUsbListener: notifyThrottling was called "
+ + ", current usb port status = " + status
+ + ", temperature = " + temp.getValue());
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index ca55e1f..1596ddb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -53,6 +53,8 @@
public static final int EVENT_TOUCH_LEVEL_DONE = 16; // (stream|int) (level|bool)
public static final int EVENT_ZEN_CONFIG_CHANGED = 17; // (allow/disallow|string)
public static final int EVENT_RINGER_TOGGLE = 18; // (ringer_mode)
+ public static final int EVENT_SHOW_USB_OVERHEAT_ALARM = 19; // (reason|int) (keyguard|bool)
+ public static final int EVENT_DISMISS_USB_OVERHEAT_ALARM = 20; // (reason|int) (keyguard|bool)
private static final String[] EVENT_TAGS = {
"show_dialog",
@@ -73,7 +75,9 @@
"mute_changed",
"touch_level_done",
"zen_mode_config_changed",
- "ringer_toggle"
+ "ringer_toggle",
+ "show_usb_overheat_alarm",
+ "dismiss_usb_overheat_alarm"
};
public static final int DISMISS_REASON_UNKNOWN = 0;
@@ -85,6 +89,7 @@
public static final int DISMISS_REASON_DONE_CLICKED = 6;
public static final int DISMISS_STREAM_GONE = 7;
public static final int DISMISS_REASON_OUTPUT_CHOOSER = 8;
+ public static final int DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED = 9;
public static final String[] DISMISS_REASONS = {
"unknown",
"touch_outside",
@@ -94,16 +99,19 @@
"settings_clicked",
"done_clicked",
"a11y_stream_changed",
- "output_chooser"
+ "output_chooser",
+ "usb_temperature_below_threshold"
};
public static final int SHOW_REASON_UNKNOWN = 0;
public static final int SHOW_REASON_VOLUME_CHANGED = 1;
public static final int SHOW_REASON_REMOTE_VOLUME_CHANGED = 2;
+ public static final int SHOW_REASON_USB_OVERHEAD_ALARM_CHANGED = 3;
public static final String[] SHOW_REASONS = {
"unknown",
"volume_changed",
- "remote_volume_changed"
+ "remote_volume_changed",
+ "usb_temperature_above_threshold"
};
public static final int ICON_STATE_UNKNOWN = 0;
@@ -181,6 +189,19 @@
case EVENT_SUPPRESSOR_CHANGED:
sb.append(list[0]).append(' ').append(list[1]);
break;
+ case EVENT_SHOW_USB_OVERHEAT_ALARM:
+ MetricsLogger.visible(context, MetricsEvent.POWER_OVERHEAT_ALARM);
+ MetricsLogger.histogram(context, "show_usb_overheat_alarm",
+ (Boolean) list[1] ? 1 : 0);
+ sb.append(SHOW_REASONS[(Integer) list[0]]).append(" keyguard=").append(list[1]);
+ break;
+ case EVENT_DISMISS_USB_OVERHEAT_ALARM:
+ MetricsLogger.hidden(context, MetricsEvent.POWER_OVERHEAT_ALARM);
+ MetricsLogger.histogram(context, "dismiss_usb_overheat_alarm",
+ (Boolean) list[1] ? 1 : 0);
+ sb.append(DISMISS_REASONS[(Integer) list[0]])
+ .append(" keyguard=").append(list[1]);
+ break;
default:
sb.append(Arrays.asList(list));
break;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index bf6cc53..cd500b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -16,9 +16,8 @@
package com.android.systemui.power;
-import static android.test.MoreAsserts.assertNotEqual;
+import static com.google.common.truth.Truth.assertThat;
-import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -38,7 +37,6 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.NotificationChannels;
-import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -151,4 +149,13 @@
verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
eq(SystemMessage.NOTE_THERMAL_SHUTDOWN), any());
}
+
+ @Test
+ public void testShowUsbHighTemperatureAlarm() {
+ mPowerNotificationWarnings.showUsbHighTemperatureAlarm();
+ waitForIdleSync(mContext.getMainThreadHandler());
+ assertThat(mPowerNotificationWarnings.mUsbHighTempDialog).isNotNull();
+
+ mPowerNotificationWarnings.mUsbHighTempDialog.dismiss();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index c28e74e..4a4e247 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -14,14 +14,14 @@
package com.android.systemui.power;
-import static android.os.HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN;
-import static android.os.HardwarePropertiesManager.TEMPERATURE_CURRENT;
-import static android.os.HardwarePropertiesManager.TEMPERATURE_SHUTDOWN;
import static android.provider.Settings.Global.SHOW_TEMPERATURE_WARNING;
+import static android.provider.Settings.Global.SHOW_USB_TEMPERATURE_ALARM;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -32,8 +32,10 @@
import android.content.Intent;
import android.os.BatteryManager;
import android.os.HardwarePropertiesManager;
+import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.PowerManager;
+import android.os.Temperature;
import android.provider.Settings;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -80,6 +82,8 @@
private EnhancedEstimates mEnhancedEstimates;
@Mock private PowerManager mPowerManager;
@Mock private IThermalService mThermalServiceMock;
+ private IThermalEventListener mThermalEventUsbListener;
+ private IThermalEventListener mThermalEventSkinListener;
@Before
public void setup() {
@@ -93,78 +97,86 @@
mContext.addMockSystemService(Context.POWER_SERVICE, mPowerManager);
createPowerUi();
+ mThermalEventSkinListener = mPowerUI.new ThermalEventSkinListener();
+ mThermalEventUsbListener = mPowerUI.new ThermalEventUsbListener();
}
@Test
- public void testNoConfig_NoWarnings() {
- setOverThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 0);
- resources.addOverride(R.integer.config_warningTemperature, 55);
-
+ public void testSkinWarning_throttlingCritical() throws Exception {
mPowerUI.start();
- verify(mMockWarnings, never()).showHighTemperatureWarning();
- }
- @Test
- public void testConfig_NoWarnings() {
- setUnderThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, 55);
+ final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_SKIN, "skin1");
+ mThermalEventSkinListener.notifyThrottling(temp);
- mPowerUI.start();
- verify(mMockWarnings, never()).showHighTemperatureWarning();
- }
-
- @Test
- public void testConfig_Warnings() {
- setOverThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, 55);
-
- mPowerUI.start();
- // Guarantees mHandler has processed all messages.
+ // dismiss skin high temperature warning when throttling status is critical
TestableLooper.get(this).processAllMessages();
- verify(mMockWarnings).showHighTemperatureWarning();
+ verify(mMockWarnings, never()).showHighTemperatureWarning();
+ verify(mMockWarnings, times(1)).dismissHighTemperatureWarning();
}
@Test
- public void testSettingOverrideConfig() {
- setOverThreshold();
+ public void testSkinWarning_throttlingEmergency() throws Exception {
+ mPowerUI.start();
+
+ final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_SKIN, "skin2");
+ mThermalEventSkinListener.notifyThrottling(temp);
+
+ // show skin high temperature warning when throttling status is emergency
+ TestableLooper.get(this).processAllMessages();
+ verify(mMockWarnings, times(1)).showHighTemperatureWarning();
+ verify(mMockWarnings, never()).dismissHighTemperatureWarning();
+ }
+
+ @Test
+ public void testUsbAlarm_throttlingCritical() throws Exception {
+ mPowerUI.start();
+
+ final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_USB_PORT, "usb1");
+ mThermalEventUsbListener.notifyThrottling(temp);
+
+ // not show usb high temperature alarm when throttling status is critical
+ TestableLooper.get(this).processAllMessages();
+ verify(mMockWarnings, never()).showUsbHighTemperatureAlarm();
+ }
+
+ @Test
+ public void testUsbAlarm_throttlingEmergency() throws Exception {
+ mPowerUI.start();
+
+ final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_USB_PORT, "usb2");
+ mThermalEventUsbListener.notifyThrottling(temp);
+
+ // show usb high temperature alarm when throttling status is emergency
+ TestableLooper.get(this).processAllMessages();
+ verify(mMockWarnings, times(1)).showUsbHighTemperatureAlarm();
+ }
+
+ @Test
+ public void testSettingOverrideConfig_enableSkinTemperatureWarning() throws Exception {
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);
TestableResources resources = mContext.getOrCreateTestableResources();
resources.addOverride(R.integer.config_showTemperatureWarning, 0);
- resources.addOverride(R.integer.config_warningTemperature, 55);
mPowerUI.start();
- // Guarantees mHandler has processed all messages.
+ mPowerUI.registerThermalEventListener();
+
TestableLooper.get(this).processAllMessages();
- verify(mMockWarnings).showHighTemperatureWarning();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
}
@Test
- public void testShutdownBasedThreshold() {
- int tolerance = 2;
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
+ public void testSettingOverrideConfig_enableUsbTemperatureAlarm() throws Exception {
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);
TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, -1);
- resources.addOverride(R.integer.config_warningTemperatureTolerance, tolerance);
- when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_SHUTDOWN))
- .thenReturn(new float[] { 55 + tolerance });
+ resources.addOverride(R.integer.config_showUsbPortAlarm, 0);
- setCurrentTemp(54); // Below threshold.
mPowerUI.start();
- verify(mMockWarnings, never()).showHighTemperatureWarning();
+ mPowerUI.registerThermalEventListener();
- setCurrentTemp(56); // Above threshold.
- mPowerUI.updateTemperatureWarning();
- verify(mMockWarnings).showHighTemperatureWarning();
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
}
@Test
@@ -532,17 +544,14 @@
verify(mEnhancedEstimates, times(2)).getEstimate();
}
- private void setCurrentTemp(float temp) {
- when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_CURRENT))
- .thenReturn(new float[] { temp });
+ private Temperature getEmergencyStatusTemp(int type, String name) {
+ final float value = 65;
+ return new Temperature(value, type, name, Temperature.THROTTLING_EMERGENCY);
}
- private void setOverThreshold() {
- setCurrentTemp(50000);
- }
-
- private void setUnderThreshold() {
- setCurrentTemp(5);
+ private Temperature getCriticalStatusTemp(int type, String name) {
+ final float value = 60;
+ return new Temperature(value, type, name, Temperature.THROTTLING_CRITICAL);
}
private void createPowerUi() {
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index d9adec8..ab8a194 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6162,6 +6162,11 @@
// OS: P
FIELD_AUTOFILL_SESSION_ID = 1456;
+ // FIELD: Device USB overheat alarm trigger.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: P
+ POWER_OVERHEAT_ALARM = 1457;
+
// ---- End P Constants, all P constants go above this line ----
// Time since this notification last interrupted (visibly or audible) the user