blob: 66804bef8f5316301a91157a243e28d397d2f1a4 [file] [log] [blame]
Joe Onorato10523b4d2010-10-25 10:42:46 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.power;
18
Joe Onorato10523b4d2010-10-25 10:42:46 -070019import android.content.BroadcastReceiver;
Dianne Hackborn14272302014-06-10 23:13:02 -070020import android.content.ContentResolver;
Joe Onorato10523b4d2010-10-25 10:42:46 -070021import android.content.Context;
Joe Onorato10523b4d2010-10-25 10:42:46 -070022import android.content.Intent;
23import android.content.IntentFilter;
Adam Lesinski1aab3fa2017-07-31 13:42:00 -070024import android.content.pm.ActivityInfo;
25import android.content.res.Configuration;
Dianne Hackborn14272302014-06-10 23:13:02 -070026import android.database.ContentObserver;
Joe Onorato4ca7f1e2010-10-27 15:32:23 -070027import android.os.BatteryManager;
Joe Onorato10523b4d2010-10-25 10:42:46 -070028import android.os.Handler;
Todd Poynorfb95e122017-10-04 13:00:32 -070029import android.os.IThermalEventListener;
30import android.os.IThermalService;
Daniel Sandlerdea64622013-09-23 16:05:57 -040031import android.os.PowerManager;
Todd Poynorfb95e122017-10-04 13:00:32 -070032import android.os.RemoteException;
33import android.os.ServiceManager;
Daniel Sandlerdea64622013-09-23 16:05:57 -040034import android.os.SystemClock;
Todd Poynorfb95e122017-10-04 13:00:32 -070035import android.os.Temperature;
Dianne Hackborn14272302014-06-10 23:13:02 -070036import android.os.UserHandle;
Joe Onorato10523b4d2010-10-25 10:42:46 -070037import android.provider.Settings;
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -080038import android.text.format.DateUtils;
John Spurlock1bb480a2014-08-02 17:12:43 -040039import android.util.Log;
Daniel Sandlerdea64622013-09-23 16:05:57 -040040import android.util.Slog;
Jason Monkd819c312017-08-11 12:53:36 -040041
42import com.android.internal.annotations.VisibleForTesting;
Salvador Martinez580098fe2019-04-11 10:42:15 -070043import com.android.settingslib.fuelgauge.Estimate;
Salvador Martinez110f9a12018-01-31 09:57:17 -080044import com.android.settingslib.utils.ThreadUtils;
Jason Monkd819c312017-08-11 12:53:36 -040045import com.android.systemui.Dependency;
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -080046import com.android.systemui.R;
Joe Onorato10523b4d2010-10-25 10:42:46 -070047import com.android.systemui.SystemUI;
Fabian Kozynskiff5e91f2019-09-24 15:38:08 -040048import com.android.systemui.broadcast.BroadcastDispatcher;
Robert Horvath121e0252019-11-19 14:09:48 +010049import com.android.systemui.statusbar.CommandQueue;
Jason Monk2a6ea9c2017-01-26 11:14:51 -050050import com.android.systemui.statusbar.phone.StatusBar;
Jason Monkd819c312017-08-11 12:53:36 -040051
John Spurlockde84f0e2013-06-12 12:41:00 -040052import java.io.FileDescriptor;
53import java.io.PrintWriter;
Salvador Martinezfd38aa52018-03-28 23:56:59 -070054import java.time.Duration;
John Spurlockde84f0e2013-06-12 12:41:00 -040055import java.util.Arrays;
Salvador Martinez7ad2c172019-02-11 16:09:28 -080056import java.util.concurrent.Future;
John Spurlockde84f0e2013-06-12 12:41:00 -040057
Fabian Kozynskiff5e91f2019-09-24 15:38:08 -040058import javax.inject.Inject;
Dave Mankoff9a22a2f2019-10-23 16:12:30 -040059import javax.inject.Singleton;
Fabian Kozynskiff5e91f2019-09-24 15:38:08 -040060
Dave Mankoff9a22a2f2019-10-23 16:12:30 -040061import dagger.Lazy;
62
63@Singleton
Robert Horvath121e0252019-11-19 14:09:48 +010064public class PowerUI extends SystemUI implements CommandQueue.Callbacks {
Salvador Martinez4387bd52019-02-21 16:16:28 -080065
Joe Onorato10523b4d2010-10-25 10:42:46 -070066 static final String TAG = "PowerUI";
John Spurlock1bb480a2014-08-02 17:12:43 -040067 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -080068 private static final long TEMPERATURE_INTERVAL = 30 * DateUtils.SECOND_IN_MILLIS;
Andrew Sappersteina6ed7f82017-02-01 17:13:08 -080069 private static final long TEMPERATURE_LOGGING_INTERVAL = DateUtils.HOUR_IN_MILLIS;
70 private static final int MAX_RECENT_TEMPS = 125; // TEMPERATURE_LOGGING_INTERVAL plus a buffer
Salvador Martinezf9e47502018-01-04 13:45:48 -080071 static final long THREE_HOURS_IN_MILLIS = DateUtils.HOUR_IN_MILLIS * 3;
Salvador Martinezfd38aa52018-03-28 23:56:59 -070072 private static final int CHARGE_CYCLE_PERCENT_RESET = 45;
73 private static final long SIX_HOURS_MILLIS = Duration.ofHours(6).toMillis();
Salvador Martinez4387bd52019-02-21 16:16:28 -080074 public static final int NO_ESTIMATE_AVAILABLE = -1;
Sherry Huang9b786732019-08-03 02:36:44 +080075 private static final String BOOT_COUNT_KEY = "boot_count";
76 private static final String PREFS = "powerui_prefs";
Joe Onorato10523b4d2010-10-25 10:42:46 -070077
John Spurlocked452c52014-03-06 12:02:31 -050078 private final Handler mHandler = new Handler();
Amin Shaikh2f6c45c2018-04-16 14:00:09 -040079 @VisibleForTesting
80 final Receiver mReceiver = new Receiver();
Joe Onorato4ca7f1e2010-10-27 15:32:23 -070081
John Spurlock3332ba52014-03-10 17:44:07 -040082 private PowerManager mPowerManager;
83 private WarningsUI mWarnings;
Robert Horvath121e0252019-11-19 14:09:48 +010084 private InattentiveSleepWarningView mOverlayView;
Adam Lesinski1aab3fa2017-07-31 13:42:00 -070085 private final Configuration mLastConfiguration = new Configuration();
John Spurlocked452c52014-03-06 12:02:31 -050086 private int mPlugType = 0;
87 private int mInvalidCharger = 0;
Salvador Martinezf9e47502018-01-04 13:45:48 -080088 private EnhancedEstimates mEnhancedEstimates;
Salvador Martinez7ad2c172019-02-11 16:09:28 -080089 private Future mLastShowWarningTask;
Sherry Huangce02ed32019-01-17 20:37:29 +080090 private boolean mEnableSkinTemperatureWarning;
91 private boolean mEnableUsbTemperatureAlarm;
Joe Onorato4ca7f1e2010-10-27 15:32:23 -070092
John Spurlocked452c52014-03-06 12:02:31 -050093 private int mLowBatteryAlertCloseLevel;
94 private final int[] mLowBatteryReminderLevels = new int[2];
Joe Onorato10523b4d2010-10-25 10:42:46 -070095
Daniel Sandlerdea64622013-09-23 16:05:57 -040096 private long mScreenOffTime = -1;
97
Salvador Martinez4387bd52019-02-21 16:16:28 -080098 @VisibleForTesting boolean mLowWarningShownThisChargeCycle;
99 @VisibleForTesting boolean mSevereWarningShownThisChargeCycle;
100 @VisibleForTesting BatteryStateSnapshot mCurrentBatteryStateSnapshot;
101 @VisibleForTesting BatteryStateSnapshot mLastBatteryStateSnapshot;
Wei Wangbf05e602018-11-21 11:46:48 -0800102 @VisibleForTesting IThermalService mThermalService;
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800103
Salvador Martinezfd38aa52018-03-28 23:56:59 -0700104 @VisibleForTesting int mBatteryLevel = 100;
Salvador Martinez36307962018-02-08 14:29:08 -0800105 @VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
106
Sherry Huang18d27042019-03-19 21:45:28 +0800107 private IThermalEventListener mSkinThermalEventListener;
108 private IThermalEventListener mUsbThermalEventListener;
Fabian Kozynskiff5e91f2019-09-24 15:38:08 -0400109 private final BroadcastDispatcher mBroadcastDispatcher;
Robert Horvath121e0252019-11-19 14:09:48 +0100110 private final CommandQueue mCommandQueue;
Dave Mankoff9a22a2f2019-10-23 16:12:30 -0400111 private final Lazy<StatusBar> mStatusBarLazy;
Fabian Kozynskiff5e91f2019-09-24 15:38:08 -0400112
113 @Inject
Dave Mankoff9a22a2f2019-10-23 16:12:30 -0400114 public PowerUI(Context context, BroadcastDispatcher broadcastDispatcher,
Robert Horvath121e0252019-11-19 14:09:48 +0100115 CommandQueue commandQueue, Lazy<StatusBar> statusBarLazy) {
Dave Mankoffa5d8a392019-10-10 12:21:09 -0400116 super(context);
Fabian Kozynskiff5e91f2019-09-24 15:38:08 -0400117 mBroadcastDispatcher = broadcastDispatcher;
Robert Horvath121e0252019-11-19 14:09:48 +0100118 mCommandQueue = commandQueue;
Dave Mankoff9a22a2f2019-10-23 16:12:30 -0400119 mStatusBarLazy = statusBarLazy;
Fabian Kozynskiff5e91f2019-09-24 15:38:08 -0400120 }
Sherry Huang18d27042019-03-19 21:45:28 +0800121
Joe Onorato10523b4d2010-10-25 10:42:46 -0700122 public void start() {
John Spurlock3332ba52014-03-10 17:44:07 -0400123 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
124 mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
Jason Monkd819c312017-08-11 12:53:36 -0400125 mWarnings = Dependency.get(WarningsUI.class);
Salvador Martinezf9e47502018-01-04 13:45:48 -0800126 mEnhancedEstimates = Dependency.get(EnhancedEstimates.class);
Adam Lesinski1aab3fa2017-07-31 13:42:00 -0700127 mLastConfiguration.setTo(mContext.getResources().getConfiguration());
Daniel Sandlerdea64622013-09-23 16:05:57 -0400128
Dianne Hackborn14272302014-06-10 23:13:02 -0700129 ContentObserver obs = new ContentObserver(mHandler) {
130 @Override
131 public void onChange(boolean selfChange) {
132 updateBatteryWarningLevels();
133 }
134 };
135 final ContentResolver resolver = mContext.getContentResolver();
136 resolver.registerContentObserver(Settings.Global.getUriFor(
137 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
138 false, obs, UserHandle.USER_ALL);
139 updateBatteryWarningLevels();
John Spurlock3332ba52014-03-10 17:44:07 -0400140 mReceiver.init();
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800141
Salvador Martineza6f7b252017-04-10 10:46:15 -0700142 // Check to see if we need to let the user know that the phone previously shut down due
143 // to the temperature being too high.
Sherry Huang9b786732019-08-03 02:36:44 +0800144 showWarnOnThermalShutdown();
Salvador Martineza6f7b252017-04-10 10:46:15 -0700145
Sherry Huang18d27042019-03-19 21:45:28 +0800146 // Register an observer to configure mEnableSkinTemperatureWarning and perform the
147 // registration of skin thermal event listener upon Settings change.
148 resolver.registerContentObserver(
149 Settings.Global.getUriFor(Settings.Global.SHOW_TEMPERATURE_WARNING),
150 false /*notifyForDescendants*/,
151 new ContentObserver(mHandler) {
152 @Override
153 public void onChange(boolean selfChange) {
154 doSkinThermalEventListenerRegistration();
155 }
156 });
157 // Register an observer to configure mEnableUsbTemperatureAlarm and perform the
158 // registration of usb thermal event listener upon Settings change.
159 resolver.registerContentObserver(
160 Settings.Global.getUriFor(Settings.Global.SHOW_USB_TEMPERATURE_ALARM),
161 false /*notifyForDescendants*/,
162 new ContentObserver(mHandler) {
163 @Override
164 public void onChange(boolean selfChange) {
165 doUsbThermalEventListenerRegistration();
166 }
167 });
168 initThermalEventListeners();
Robert Horvath121e0252019-11-19 14:09:48 +0100169 mCommandQueue.addCallback(this);
John Spurlock3332ba52014-03-10 17:44:07 -0400170 }
Dianne Hackborn14272302014-06-10 23:13:02 -0700171
Adam Lesinski1aab3fa2017-07-31 13:42:00 -0700172 @Override
173 protected void onConfigurationChanged(Configuration newConfig) {
174 final int mask = ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
175
176 // Safe to modify mLastConfiguration here as it's only updated by the main thread (here).
177 if ((mLastConfiguration.updateFrom(newConfig) & mask) != 0) {
Sherry Huang18d27042019-03-19 21:45:28 +0800178 mHandler.post(this::initThermalEventListeners);
Adam Lesinski1aab3fa2017-07-31 13:42:00 -0700179 }
180 }
181
Dianne Hackborn14272302014-06-10 23:13:02 -0700182 void updateBatteryWarningLevels() {
183 int critLevel = mContext.getResources().getInteger(
184 com.android.internal.R.integer.config_criticalBatteryWarningLevel);
Makoto Onuki16a0dd22018-03-20 10:40:37 -0700185 int warnLevel = mContext.getResources().getInteger(
Dianne Hackborn14272302014-06-10 23:13:02 -0700186 com.android.internal.R.integer.config_lowBatteryWarningLevel);
Makoto Onuki4a9036b2018-01-11 14:48:20 -0800187
Dianne Hackborn14272302014-06-10 23:13:02 -0700188 if (warnLevel < critLevel) {
189 warnLevel = critLevel;
190 }
191
192 mLowBatteryReminderLevels[0] = warnLevel;
193 mLowBatteryReminderLevels[1] = critLevel;
194 mLowBatteryAlertCloseLevel = mLowBatteryReminderLevels[0]
195 + mContext.getResources().getInteger(
196 com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
197 }
198
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700199 /**
200 * Buckets the battery level.
201 *
202 * The code in this function is a little weird because I couldn't comprehend
203 * the bucket going up when the battery level was going down. --joeo
204 *
205 * 1 means that the battery is "ok"
206 * 0 means that the battery is between "ok" and what we should warn about.
207 * less than 0 means that the battery is low
208 */
209 private int findBatteryLevelBucket(int level) {
210 if (level >= mLowBatteryAlertCloseLevel) {
211 return 1;
212 }
Dianne Hackborn14272302014-06-10 23:13:02 -0700213 if (level > mLowBatteryReminderLevels[0]) {
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700214 return 0;
215 }
216 final int N = mLowBatteryReminderLevels.length;
217 for (int i=N-1; i>=0; i--) {
218 if (level <= mLowBatteryReminderLevels[i]) {
219 return -1-i;
220 }
221 }
222 throw new RuntimeException("not possible!");
223 }
224
Amin Shaikh2f6c45c2018-04-16 14:00:09 -0400225 @VisibleForTesting
226 final class Receiver extends BroadcastReceiver {
John Spurlock3332ba52014-03-10 17:44:07 -0400227
Fabian Kozynski99abb712020-06-25 16:12:31 -0400228 private boolean mHasReceivedBattery = false;
229
John Spurlock3332ba52014-03-10 17:44:07 -0400230 public void init() {
231 // Register for Intent broadcasts for...
232 IntentFilter filter = new IntentFilter();
Amin Shaikh2f6c45c2018-04-16 14:00:09 -0400233 filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
John Spurlock3332ba52014-03-10 17:44:07 -0400234 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
235 filter.addAction(Intent.ACTION_SCREEN_OFF);
236 filter.addAction(Intent.ACTION_SCREEN_ON);
John Spurlockecbc5e82014-10-22 09:05:51 -0400237 filter.addAction(Intent.ACTION_USER_SWITCHED);
Fabian Kozynski5e92c6f2020-01-03 13:56:17 -0500238 mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mHandler);
Fabian Kozynski99abb712020-06-25 16:12:31 -0400239 // Force get initial values. Relying on Sticky behavior until API for getting info.
240 if (!mHasReceivedBattery) {
241 // Get initial state
242 Intent intent = mContext.registerReceiver(
243 null,
244 new IntentFilter(Intent.ACTION_BATTERY_CHANGED)
245 );
246 if (intent != null) {
247 onReceive(mContext, intent);
248 }
249 }
John Spurlock3332ba52014-03-10 17:44:07 -0400250 }
251
Joe Onorato10523b4d2010-10-25 10:42:46 -0700252 @Override
253 public void onReceive(Context context, Intent intent) {
254 String action = intent.getAction();
Amin Shaikh2f6c45c2018-04-16 14:00:09 -0400255 if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
256 ThreadUtils.postOnBackgroundThread(() -> {
257 if (mPowerManager.isPowerSaveMode()) {
258 mWarnings.dismissLowBatteryWarning();
259 }
260 });
261 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
Fabian Kozynski99abb712020-06-25 16:12:31 -0400262 mHasReceivedBattery = true;
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700263 final int oldBatteryLevel = mBatteryLevel;
264 mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
265 final int oldBatteryStatus = mBatteryStatus;
266 mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
267 BatteryManager.BATTERY_STATUS_UNKNOWN);
268 final int oldPlugType = mPlugType;
269 mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
270 final int oldInvalidCharger = mInvalidCharger;
271 mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
Salvador Martinez4387bd52019-02-21 16:16:28 -0800272 mLastBatteryStateSnapshot = mCurrentBatteryStateSnapshot;
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700273
274 final boolean plugged = mPlugType != 0;
275 final boolean oldPlugged = oldPlugType != 0;
276
277 int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
278 int bucket = findBatteryLevelBucket(mBatteryLevel);
279
Daniel Sandler71986622011-07-26 13:06:49 -0400280 if (DEBUG) {
Daniel Sandlerdea64622013-09-23 16:05:57 -0400281 Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700282 + " .. " + mLowBatteryReminderLevels[0]
283 + " .. " + mLowBatteryReminderLevels[1]);
Daniel Sandlerdea64622013-09-23 16:05:57 -0400284 Slog.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel);
285 Slog.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus);
286 Slog.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType);
287 Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
288 Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket);
289 Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700290 }
291
John Spurlocked452c52014-03-06 12:02:31 -0500292 mWarnings.update(mBatteryLevel, bucket, mScreenOffTime);
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700293 if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
Daniel Sandlerdea64622013-09-23 16:05:57 -0400294 Slog.d(TAG, "showing invalid charger warning");
John Spurlocked452c52014-03-06 12:02:31 -0500295 mWarnings.showInvalidChargerWarning();
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700296 return;
297 } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
John Spurlocked452c52014-03-06 12:02:31 -0500298 mWarnings.dismissInvalidChargerWarning();
299 } else if (mWarnings.isInvalidChargerWarningShowing()) {
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700300 // if invalid charger is showing, don't show low battery
Salvador Martinez4387bd52019-02-21 16:16:28 -0800301 if (DEBUG) {
302 Slog.d(TAG, "Bad Charger");
303 }
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700304 return;
305 }
306
Salvador Martinezf9e47502018-01-04 13:45:48 -0800307 // Show the correct version of low battery warning if needed
Salvador Martinez7ad2c172019-02-11 16:09:28 -0800308 if (mLastShowWarningTask != null) {
309 mLastShowWarningTask.cancel(true);
Salvador Martinez4387bd52019-02-21 16:16:28 -0800310 if (DEBUG) {
311 Slog.d(TAG, "cancelled task");
312 }
Salvador Martinez7ad2c172019-02-11 16:09:28 -0800313 }
314 mLastShowWarningTask = ThreadUtils.postOnBackgroundThread(() -> {
Salvador Martinez4387bd52019-02-21 16:16:28 -0800315 maybeShowBatteryWarningV2(
316 plugged, bucket);
Salvador Martinez110f9a12018-01-31 09:57:17 -0800317 });
Beverly334bc5f2017-07-31 10:37:17 -0400318
Daniel Sandlerdea64622013-09-23 16:05:57 -0400319 } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
320 mScreenOffTime = SystemClock.elapsedRealtime();
321 } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
322 mScreenOffTime = -1;
John Spurlockecbc5e82014-10-22 09:05:51 -0400323 } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
324 mWarnings.userSwitched();
Joe Onorato10523b4d2010-10-25 10:42:46 -0700325 } else {
Daniel Sandlerdea64622013-09-23 16:05:57 -0400326 Slog.w(TAG, "unknown intent: " + intent);
Joe Onorato10523b4d2010-10-25 10:42:46 -0700327 }
328 }
Salvador Martinezf9e47502018-01-04 13:45:48 -0800329 }
330
Salvador Martinez4387bd52019-02-21 16:16:28 -0800331 protected void maybeShowBatteryWarningV2(boolean plugged, int bucket) {
Salvador Martinezfd38aa52018-03-28 23:56:59 -0700332 final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();
Salvador Martinez4387bd52019-02-21 16:16:28 -0800333 final boolean isPowerSaverMode = mPowerManager.isPowerSaveMode();
Salvador Martinezfd38aa52018-03-28 23:56:59 -0700334
Salvador Martinez4387bd52019-02-21 16:16:28 -0800335 // Stick current battery state into an immutable container to determine if we should show
336 // a warning.
337 if (DEBUG) {
338 Slog.d(TAG, "evaluating which notification to show");
339 }
340 if (hybridEnabled) {
341 if (DEBUG) {
342 Slog.d(TAG, "using hybrid");
343 }
344 Estimate estimate = refreshEstimateIfNeeded();
345 mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
346 plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
347 mLowBatteryReminderLevels[0], estimate.getEstimateMillis(),
Salvador Martinez580098fe2019-04-11 10:42:15 -0700348 estimate.getAverageDischargeTime(),
Salvador Martinez4387bd52019-02-21 16:16:28 -0800349 mEnhancedEstimates.getSevereWarningThreshold(),
Salvador Martinezd73c5aa2019-03-26 12:38:09 -0700350 mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage(),
351 mEnhancedEstimates.getLowWarningEnabled());
Salvador Martinez4387bd52019-02-21 16:16:28 -0800352 } else {
353 if (DEBUG) {
354 Slog.d(TAG, "using standard");
355 }
356 mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
357 plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
358 mLowBatteryReminderLevels[0]);
359 }
360
361 mWarnings.updateSnapshot(mCurrentBatteryStateSnapshot);
362 if (mCurrentBatteryStateSnapshot.isHybrid()) {
363 maybeShowHybridWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
364 } else {
365 maybeShowBatteryWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
366 }
367 }
368
369 // updates the time estimate if we don't have one or battery level has changed.
370 @VisibleForTesting
371 Estimate refreshEstimateIfNeeded() {
372 if (mLastBatteryStateSnapshot == null
373 || mLastBatteryStateSnapshot.getTimeRemainingMillis() == NO_ESTIMATE_AVAILABLE
374 || mBatteryLevel != mLastBatteryStateSnapshot.getBatteryLevel()) {
375 final Estimate estimate = mEnhancedEstimates.getEstimate();
376 if (DEBUG) {
377 Slog.d(TAG, "updated estimate: " + estimate.getEstimateMillis());
378 }
379 return estimate;
380 }
381 return new Estimate(mLastBatteryStateSnapshot.getTimeRemainingMillis(),
Salvador Martinez580098fe2019-04-11 10:42:15 -0700382 mLastBatteryStateSnapshot.isBasedOnUsage(),
383 mLastBatteryStateSnapshot.getAverageTimeToDischargeMillis());
Salvador Martinez4387bd52019-02-21 16:16:28 -0800384 }
385
386 @VisibleForTesting
387 void maybeShowHybridWarning(BatteryStateSnapshot currentSnapshot,
388 BatteryStateSnapshot lastSnapshot) {
389 // if we are now over 45% battery & 6 hours remaining so we can trigger hybrid
390 // notification again
Mill Chen5a558b92020-06-03 23:41:47 +0800391 final long timeRemainingMillis = currentSnapshot.getTimeRemainingMillis();
Salvador Martinez4387bd52019-02-21 16:16:28 -0800392 if (currentSnapshot.getBatteryLevel() >= CHARGE_CYCLE_PERCENT_RESET
Mill Chen5a558b92020-06-03 23:41:47 +0800393 && (timeRemainingMillis > SIX_HOURS_MILLIS
394 || timeRemainingMillis == NO_ESTIMATE_AVAILABLE)) {
Salvador Martinez4387bd52019-02-21 16:16:28 -0800395 mLowWarningShownThisChargeCycle = false;
396 mSevereWarningShownThisChargeCycle = false;
397 if (DEBUG) {
398 Slog.d(TAG, "Charge cycle reset! Can show warnings again");
Salvador Martinezf9e47502018-01-04 13:45:48 -0800399 }
400 }
401
Salvador Martinez4387bd52019-02-21 16:16:28 -0800402 final boolean playSound = currentSnapshot.getBucket() != lastSnapshot.getBucket()
403 || lastSnapshot.getPlugged();
Salvador Martinez36307962018-02-08 14:29:08 -0800404
Salvador Martinez4387bd52019-02-21 16:16:28 -0800405 if (shouldShowHybridWarning(currentSnapshot)) {
406 mWarnings.showLowBatteryWarning(playSound);
Salvador Martinezfd38aa52018-03-28 23:56:59 -0700407 // mark if we've already shown a warning this cycle. This will prevent the notification
408 // trigger from spamming users by only showing low/critical warnings once per cycle
Mill Chen5a558b92020-06-03 23:41:47 +0800409 if ((timeRemainingMillis != NO_ESTIMATE_AVAILABLE
410 && timeRemainingMillis <= currentSnapshot.getSevereThresholdMillis())
Salvador Martinez290496e2019-04-04 10:30:19 -0700411 || currentSnapshot.getBatteryLevel()
412 <= currentSnapshot.getSevereLevelThreshold()) {
Salvador Martinez4387bd52019-02-21 16:16:28 -0800413 mSevereWarningShownThisChargeCycle = true;
414 mLowWarningShownThisChargeCycle = true;
415 if (DEBUG) {
416 Slog.d(TAG, "Severe warning marked as shown this cycle");
Salvador Martinezfd38aa52018-03-28 23:56:59 -0700417 }
Salvador Martinez4387bd52019-02-21 16:16:28 -0800418 } else {
419 Slog.d(TAG, "Low warning marked as shown this cycle");
420 mLowWarningShownThisChargeCycle = true;
Salvador Martinez36307962018-02-08 14:29:08 -0800421 }
Salvador Martinez4387bd52019-02-21 16:16:28 -0800422 } else if (shouldDismissHybridWarning(currentSnapshot)) {
423 if (DEBUG) {
424 Slog.d(TAG, "Dismissing warning");
425 }
426 mWarnings.dismissLowBatteryWarning();
427 } else {
428 if (DEBUG) {
429 Slog.d(TAG, "Updating warning");
430 }
431 mWarnings.updateLowBatteryWarning();
432 }
433 }
434
435 @VisibleForTesting
436 boolean shouldShowHybridWarning(BatteryStateSnapshot snapshot) {
437 if (snapshot.getPlugged()
438 || snapshot.getBatteryStatus() == BatteryManager.BATTERY_STATUS_UNKNOWN) {
439 Slog.d(TAG, "can't show warning due to - plugged: " + snapshot.getPlugged()
440 + " status unknown: "
441 + (snapshot.getBatteryStatus() == BatteryManager.BATTERY_STATUS_UNKNOWN));
442 return false;
443 }
444
Mill Chen5a558b92020-06-03 23:41:47 +0800445 final long timeRemainingMillis = snapshot.getTimeRemainingMillis();
Salvador Martinezd73c5aa2019-03-26 12:38:09 -0700446 // Only show the low warning if enabled once per charge cycle & no battery saver
447 final boolean canShowWarning = snapshot.isLowWarningEnabled()
448 && !mLowWarningShownThisChargeCycle && !snapshot.isPowerSaver()
Mill Chen5a558b92020-06-03 23:41:47 +0800449 && ((timeRemainingMillis != NO_ESTIMATE_AVAILABLE
450 && timeRemainingMillis < snapshot.getLowThresholdMillis())
Salvador Martinez4387bd52019-02-21 16:16:28 -0800451 || snapshot.getBatteryLevel() <= snapshot.getLowLevelThreshold());
452
453 // Only show the severe warning once per charge cycle
454 final boolean canShowSevereWarning = !mSevereWarningShownThisChargeCycle
Mill Chen5a558b92020-06-03 23:41:47 +0800455 && ((timeRemainingMillis != NO_ESTIMATE_AVAILABLE
456 && timeRemainingMillis < snapshot.getSevereThresholdMillis())
Salvador Martinez4387bd52019-02-21 16:16:28 -0800457 || snapshot.getBatteryLevel() <= snapshot.getSevereLevelThreshold());
458
459 final boolean canShow = canShowWarning || canShowSevereWarning;
Salvador Martinezd73c5aa2019-03-26 12:38:09 -0700460
Salvador Martinez4387bd52019-02-21 16:16:28 -0800461 if (DEBUG) {
462 Slog.d(TAG, "Enhanced trigger is: " + canShow + "\nwith battery snapshot:"
463 + " mLowWarningShownThisChargeCycle: " + mLowWarningShownThisChargeCycle
464 + " mSevereWarningShownThisChargeCycle: " + mSevereWarningShownThisChargeCycle
465 + "\n" + snapshot.toString());
466 }
467 return canShow;
468 }
469
470 @VisibleForTesting
471 boolean shouldDismissHybridWarning(BatteryStateSnapshot snapshot) {
472 return snapshot.getPlugged()
473 || snapshot.getTimeRemainingMillis() > snapshot.getLowThresholdMillis();
474 }
475
476 protected void maybeShowBatteryWarning(
477 BatteryStateSnapshot currentSnapshot,
478 BatteryStateSnapshot lastSnapshot) {
479 final boolean playSound = currentSnapshot.getBucket() != lastSnapshot.getBucket()
480 || lastSnapshot.getPlugged();
481
482 if (shouldShowLowBatteryWarning(currentSnapshot, lastSnapshot)) {
483 mWarnings.showLowBatteryWarning(playSound);
484 } else if (shouldDismissLowBatteryWarning(currentSnapshot, lastSnapshot)) {
Salvador Martinezf9e47502018-01-04 13:45:48 -0800485 mWarnings.dismissLowBatteryWarning();
486 } else {
487 mWarnings.updateLowBatteryWarning();
488 }
489 }
490
491 @VisibleForTesting
Salvador Martinez4387bd52019-02-21 16:16:28 -0800492 boolean shouldShowLowBatteryWarning(
493 BatteryStateSnapshot currentSnapshot,
494 BatteryStateSnapshot lastSnapshot) {
495 return !currentSnapshot.getPlugged()
496 && !currentSnapshot.isPowerSaver()
497 && (((currentSnapshot.getBucket() < lastSnapshot.getBucket()
498 || lastSnapshot.getPlugged())
499 && currentSnapshot.getBucket() < 0))
500 && currentSnapshot.getBatteryStatus() != BatteryManager.BATTERY_STATUS_UNKNOWN;
Salvador Martinezf9e47502018-01-04 13:45:48 -0800501 }
502
Salvador Martinezf9e47502018-01-04 13:45:48 -0800503 @VisibleForTesting
Salvador Martinez4387bd52019-02-21 16:16:28 -0800504 boolean shouldDismissLowBatteryWarning(
505 BatteryStateSnapshot currentSnapshot,
506 BatteryStateSnapshot lastSnapshot) {
507 return currentSnapshot.isPowerSaver()
508 || currentSnapshot.getPlugged()
509 || (currentSnapshot.getBucket() > lastSnapshot.getBucket()
510 && currentSnapshot.getBucket() > 0);
Salvador Martinez36307962018-02-08 14:29:08 -0800511 }
512
Sherry Huang18d27042019-03-19 21:45:28 +0800513 private void initThermalEventListeners() {
514 doSkinThermalEventListenerRegistration();
515 doUsbThermalEventListenerRegistration();
516 }
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800517
Sherry Huang18d27042019-03-19 21:45:28 +0800518 @VisibleForTesting
519 synchronized void doSkinThermalEventListenerRegistration() {
520 final boolean oldEnableSkinTemperatureWarning = mEnableSkinTemperatureWarning;
521 boolean ret = false;
Adam Lesinski1aab3fa2017-07-31 13:42:00 -0700522
Sherry Huang18d27042019-03-19 21:45:28 +0800523 mEnableSkinTemperatureWarning = Settings.Global.getInt(mContext.getContentResolver(),
524 Settings.Global.SHOW_TEMPERATURE_WARNING,
525 mContext.getResources().getInteger(R.integer.config_showTemperatureWarning)) != 0;
Todd Poynorfb95e122017-10-04 13:00:32 -0700526
Sherry Huang18d27042019-03-19 21:45:28 +0800527 if (mEnableSkinTemperatureWarning != oldEnableSkinTemperatureWarning) {
528 try {
529 if (mSkinThermalEventListener == null) {
530 mSkinThermalEventListener = new SkinThermalEventListener();
531 }
532 if (mThermalService == null) {
533 mThermalService = IThermalService.Stub.asInterface(
534 ServiceManager.getService(Context.THERMAL_SERVICE));
535 }
536 if (mEnableSkinTemperatureWarning) {
537 ret = mThermalService.registerThermalEventListenerWithType(
538 mSkinThermalEventListener, Temperature.TYPE_SKIN);
539 } else {
540 ret = mThermalService.unregisterThermalEventListener(mSkinThermalEventListener);
541 }
542 } catch (RemoteException e) {
543 Slog.e(TAG, "Exception while (un)registering skin thermal event listener.", e);
544 }
545
546 if (!ret) {
547 mEnableSkinTemperatureWarning = !mEnableSkinTemperatureWarning;
548 Slog.e(TAG, "Failed to register or unregister skin thermal event listener.");
Todd Poynorfb95e122017-10-04 13:00:32 -0700549 }
550 }
Sherry Huangce02ed32019-01-17 20:37:29 +0800551 }
Todd Poynorfb95e122017-10-04 13:00:32 -0700552
Sherry Huangce02ed32019-01-17 20:37:29 +0800553 @VisibleForTesting
Sherry Huang18d27042019-03-19 21:45:28 +0800554 synchronized void doUsbThermalEventListenerRegistration() {
555 final boolean oldEnableUsbTemperatureAlarm = mEnableUsbTemperatureAlarm;
556 boolean ret = false;
557
558 mEnableUsbTemperatureAlarm = Settings.Global.getInt(mContext.getContentResolver(),
559 Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
560 mContext.getResources().getInteger(R.integer.config_showUsbPortAlarm)) != 0;
561
562 if (mEnableUsbTemperatureAlarm != oldEnableUsbTemperatureAlarm) {
563 try {
564 if (mUsbThermalEventListener == null) {
565 mUsbThermalEventListener = new UsbThermalEventListener();
566 }
567 if (mThermalService == null) {
568 mThermalService = IThermalService.Stub.asInterface(
569 ServiceManager.getService(Context.THERMAL_SERVICE));
570 }
571 if (mEnableUsbTemperatureAlarm) {
572 ret = mThermalService.registerThermalEventListenerWithType(
573 mUsbThermalEventListener, Temperature.TYPE_USB_PORT);
574 } else {
575 ret = mThermalService.unregisterThermalEventListener(mUsbThermalEventListener);
576 }
577 } catch (RemoteException e) {
578 Slog.e(TAG, "Exception while (un)registering usb thermal event listener.", e);
Sherry Huangce02ed32019-01-17 20:37:29 +0800579 }
Sherry Huang18d27042019-03-19 21:45:28 +0800580
581 if (!ret) {
582 mEnableUsbTemperatureAlarm = !mEnableUsbTemperatureAlarm;
583 Slog.e(TAG, "Failed to register or unregister usb thermal event listener.");
Sherry Huangce02ed32019-01-17 20:37:29 +0800584 }
Sherry Huangce02ed32019-01-17 20:37:29 +0800585 }
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800586 }
587
Sherry Huang9b786732019-08-03 02:36:44 +0800588 private void showWarnOnThermalShutdown() {
589 int bootCount = -1;
590 int lastReboot = mContext.getSharedPreferences(PREFS, 0).getInt(BOOT_COUNT_KEY, -1);
591 try {
592 bootCount = Settings.Global.getInt(mContext.getContentResolver(),
593 Settings.Global.BOOT_COUNT);
594 } catch (Settings.SettingNotFoundException e) {
595 Slog.e(TAG, "Failed to read system boot count from Settings.Global.BOOT_COUNT");
596 }
597 // Only show the thermal shutdown warning when there is a thermal reboot.
598 if (bootCount > lastReboot) {
599 mContext.getSharedPreferences(PREFS, 0).edit().putInt(BOOT_COUNT_KEY,
600 bootCount).apply();
601 if (mPowerManager.getLastShutdownReason()
602 == PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN) {
603 mWarnings.showThermalShutdownWarning();
604 }
Salvador Martineza6f7b252017-04-10 10:46:15 -0700605 }
606 }
607
Robert Horvath121e0252019-11-19 14:09:48 +0100608 @Override
609 public void showInattentiveSleepWarning() {
610 if (mOverlayView == null) {
611 mOverlayView = new InattentiveSleepWarningView(mContext);
612 }
613
614 mOverlayView.show();
615 }
616
617 @Override
618 public void dismissInattentiveSleepWarning(boolean animated) {
619 if (mOverlayView != null) {
620 mOverlayView.dismiss(animated);
621 }
622 }
623
Joe Onorato10523b4d2010-10-25 10:42:46 -0700624 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700625 pw.print("mLowBatteryAlertCloseLevel=");
626 pw.println(mLowBatteryAlertCloseLevel);
627 pw.print("mLowBatteryReminderLevels=");
628 pw.println(Arrays.toString(mLowBatteryReminderLevels));
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700629 pw.print("mBatteryLevel=");
630 pw.println(Integer.toString(mBatteryLevel));
631 pw.print("mBatteryStatus=");
632 pw.println(Integer.toString(mBatteryStatus));
633 pw.print("mPlugType=");
634 pw.println(Integer.toString(mPlugType));
635 pw.print("mInvalidCharger=");
636 pw.println(Integer.toString(mInvalidCharger));
Daniel Sandlerdea64622013-09-23 16:05:57 -0400637 pw.print("mScreenOffTime=");
638 pw.print(mScreenOffTime);
639 if (mScreenOffTime >= 0) {
640 pw.print(" (");
641 pw.print(SystemClock.elapsedRealtime() - mScreenOffTime);
642 pw.print(" ago)");
643 }
644 pw.println();
645 pw.print("soundTimeout=");
646 pw.println(Settings.Global.getInt(mContext.getContentResolver(),
647 Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
Joe Onorato4ca7f1e2010-10-27 15:32:23 -0700648 pw.print("bucket: ");
649 pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
Sherry Huangce02ed32019-01-17 20:37:29 +0800650 pw.print("mEnableSkinTemperatureWarning=");
651 pw.println(mEnableSkinTemperatureWarning);
652 pw.print("mEnableUsbTemperatureAlarm=");
653 pw.println(mEnableUsbTemperatureAlarm);
John Spurlocked452c52014-03-06 12:02:31 -0500654 mWarnings.dump(pw);
655 }
656
Salvador Martinez4387bd52019-02-21 16:16:28 -0800657 /**
658 * The interface to allow PowerUI to communicate with whatever implementation of WarningsUI
659 * is being used by the system.
660 */
John Spurlocked452c52014-03-06 12:02:31 -0500661 public interface WarningsUI {
Salvador Martinez4387bd52019-02-21 16:16:28 -0800662
663 /**
664 * Updates battery and screen info for determining whether to trigger battery warnings or
665 * not.
666 * @param batteryLevel The current battery level
667 * @param bucket The current battery bucket
668 * @param screenOffTime How long the screen has been off in millis
669 */
John Spurlocked452c52014-03-06 12:02:31 -0500670 void update(int batteryLevel, int bucket, long screenOffTime);
Sherry Huangce02ed32019-01-17 20:37:29 +0800671
John Spurlocked452c52014-03-06 12:02:31 -0500672 void dismissLowBatteryWarning();
Sherry Huangce02ed32019-01-17 20:37:29 +0800673
John Spurlocked452c52014-03-06 12:02:31 -0500674 void showLowBatteryWarning(boolean playSound);
Sherry Huangce02ed32019-01-17 20:37:29 +0800675
John Spurlocked452c52014-03-06 12:02:31 -0500676 void dismissInvalidChargerWarning();
Sherry Huangce02ed32019-01-17 20:37:29 +0800677
John Spurlocked452c52014-03-06 12:02:31 -0500678 void showInvalidChargerWarning();
Sherry Huangce02ed32019-01-17 20:37:29 +0800679
John Spurlocked452c52014-03-06 12:02:31 -0500680 void updateLowBatteryWarning();
Sherry Huangce02ed32019-01-17 20:37:29 +0800681
John Spurlocked452c52014-03-06 12:02:31 -0500682 boolean isInvalidChargerWarningShowing();
Sherry Huangce02ed32019-01-17 20:37:29 +0800683
Salvador Martineza6f7b252017-04-10 10:46:15 -0700684 void dismissHighTemperatureWarning();
Sherry Huangce02ed32019-01-17 20:37:29 +0800685
Salvador Martineza6f7b252017-04-10 10:46:15 -0700686 void showHighTemperatureWarning();
Sherry Huangce02ed32019-01-17 20:37:29 +0800687
688 /**
Sherry Huang18d27042019-03-19 21:45:28 +0800689 * Display USB port overheat alarm
Sherry Huangce02ed32019-01-17 20:37:29 +0800690 */
691 void showUsbHighTemperatureAlarm();
692
Salvador Martineza6f7b252017-04-10 10:46:15 -0700693 void showThermalShutdownWarning();
Sherry Huangce02ed32019-01-17 20:37:29 +0800694
John Spurlocked452c52014-03-06 12:02:31 -0500695 void dump(PrintWriter pw);
Sherry Huangce02ed32019-01-17 20:37:29 +0800696
John Spurlockecbc5e82014-10-22 09:05:51 -0400697 void userSwitched();
Salvador Martinez4387bd52019-02-21 16:16:28 -0800698
699 /**
700 * Updates the snapshot of battery state used for evaluating battery warnings
701 * @param snapshot object containing relevant values for making battery warning decisions.
702 */
703 void updateSnapshot(BatteryStateSnapshot snapshot);
Joe Onorato10523b4d2010-10-25 10:42:46 -0700704 }
Joe Onorato10523b4d2010-10-25 10:42:46 -0700705
Sherry Huang18d27042019-03-19 21:45:28 +0800706 // Skin thermal event received from thermal service manager subsystem
Sherry Huangce02ed32019-01-17 20:37:29 +0800707 @VisibleForTesting
Sherry Huang18d27042019-03-19 21:45:28 +0800708 final class SkinThermalEventListener extends IThermalEventListener.Stub {
Wei Wangbad7c202018-11-01 11:57:39 -0700709 @Override public void notifyThrottling(Temperature temp) {
Sherry Huangce02ed32019-01-17 20:37:29 +0800710 int status = temp.getStatus();
711
712 if (status >= Temperature.THROTTLING_EMERGENCY) {
Dave Mankoff9a22a2f2019-10-23 16:12:30 -0400713 if (!mStatusBarLazy.get().isDeviceInVrMode()) {
Sherry Huangce02ed32019-01-17 20:37:29 +0800714 mWarnings.showHighTemperatureWarning();
Sherry Huang18d27042019-03-19 21:45:28 +0800715 Slog.d(TAG, "SkinThermalEventListener: notifyThrottling was called "
Sherry Huangce02ed32019-01-17 20:37:29 +0800716 + ", current skin status = " + status
717 + ", temperature = " + temp.getValue());
718 }
719 } else {
720 mWarnings.dismissHighTemperatureWarning();
721 }
722 }
723 }
724
Sherry Huang18d27042019-03-19 21:45:28 +0800725 // Usb thermal event received from thermal service manager subsystem
Sherry Huangce02ed32019-01-17 20:37:29 +0800726 @VisibleForTesting
Sherry Huang18d27042019-03-19 21:45:28 +0800727 final class UsbThermalEventListener extends IThermalEventListener.Stub {
Sherry Huangce02ed32019-01-17 20:37:29 +0800728 @Override public void notifyThrottling(Temperature temp) {
729 int status = temp.getStatus();
730
731 if (status >= Temperature.THROTTLING_EMERGENCY) {
732 mWarnings.showUsbHighTemperatureAlarm();
Sherry Huang18d27042019-03-19 21:45:28 +0800733 Slog.d(TAG, "UsbThermalEventListener: notifyThrottling was called "
Sherry Huangce02ed32019-01-17 20:37:29 +0800734 + ", current usb port status = " + status
735 + ", temperature = " + temp.getValue());
736 }
Todd Poynorfb95e122017-10-04 13:00:32 -0700737 }
738 }
739}