Show notif when device reaches throttling temp
am: 67e97053c5
Change-Id: I44639cb19b7fa9547dc1e579a5beb34f923da2a7
This commit is contained in:
25
packages/SystemUI/res/drawable/ic_device_thermostat_24.xml
Normal file
25
packages/SystemUI/res/drawable/ic_device_thermostat_24.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M15,13L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v8c-1.21,0.91 -2,2.37 -2,4 0,2.76 2.24,5 5,5s5,-2.24 5,-5c0,-1.63 -0.79,-3.09 -2,-4zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1h-1v1h1v2h-1v1h1v2h-2L11,5z"/>
|
||||
</vector>
|
||||
@@ -284,4 +284,6 @@
|
||||
|
||||
<bool name="quick_settings_show_full_alarm">false</bool>
|
||||
|
||||
<bool name="config_showTemperatureWarning">false</bool>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<item type="id" name="notification_screenshot"/>
|
||||
<item type="id" name="notification_hidden"/>
|
||||
<item type="id" name="notification_volumeui"/>
|
||||
<item type="id" name="notification_temperature"/>
|
||||
<item type="id" name="transformation_start_x_tag"/>
|
||||
<item type="id" name="transformation_start_y_tag"/>
|
||||
<item type="id" name="transformation_start_scale_x_tag"/>
|
||||
|
||||
@@ -1694,4 +1694,12 @@
|
||||
<!-- Label that replaces other notification controls when the notification is from the system
|
||||
and cannot be silenced (see @string/show_silently) or blocked (see @string/block) -->
|
||||
<string name="cant_silence_or_block">Notifications can\'t be silenced or blocked</string>
|
||||
|
||||
<!-- Title for notification (and dialog) that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=30] -->
|
||||
<string name="high_temp_title">Phone is getting warm</string>
|
||||
<!-- Message body for notification that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=70] -->
|
||||
<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>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -49,7 +49,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
private static final String TAG = PowerUI.TAG + ".Notification";
|
||||
private static final boolean DEBUG = PowerUI.DEBUG;
|
||||
|
||||
private static final String TAG_NOTIFICATION = "low_battery";
|
||||
private static final String TAG_NOTIFICATION_BATTERY = "low_battery";
|
||||
private static final String TAG_NOTIFICATION_TEMPERATURE = "high_temp";
|
||||
|
||||
private static final int SHOWING_NOTHING = 0;
|
||||
private static final int SHOWING_WARNING = 1;
|
||||
@@ -64,6 +65,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings";
|
||||
private static final String ACTION_START_SAVER = "PNW.startSaver";
|
||||
private static final String ACTION_DISMISSED_WARNING = "PNW.dismissedWarning";
|
||||
private static final String ACTION_CLICKED_TEMP_WARNING = "PNW.clickedTempWarning";
|
||||
private static final String ACTION_DISMISSED_TEMP_WARNING = "PNW.dismissedTempWarning";
|
||||
|
||||
private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||
@@ -88,6 +91,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
private boolean mPlaySound;
|
||||
private boolean mInvalidCharger;
|
||||
private SystemUIDialog mSaverConfirmation;
|
||||
private boolean mTempWarning;
|
||||
private SystemUIDialog mHighTempDialog;
|
||||
|
||||
public PowerNotificationWarnings(Context context, PhoneStatusBar phoneStatusBar) {
|
||||
mContext = context;
|
||||
@@ -103,6 +108,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
pw.print("mInvalidCharger="); pw.println(mInvalidCharger);
|
||||
pw.print("mShowing="); pw.println(SHOWING_STRINGS[mShowing]);
|
||||
pw.print("mSaverConfirmation="); pw.println(mSaverConfirmation != null ? "not null" : null);
|
||||
pw.print("mTempWarning="); pw.println(mTempWarning);
|
||||
pw.print("mHighTempDialog="); pw.println(mHighTempDialog != null ? "not null" : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,7 +134,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
showWarningNotification();
|
||||
mShowing = SHOWING_WARNING;
|
||||
} else {
|
||||
mNoMan.cancelAsUser(TAG_NOTIFICATION, R.id.notification_power, UserHandle.ALL);
|
||||
mNoMan.cancelAsUser(TAG_NOTIFICATION_BATTERY, R.id.notification_power, UserHandle.ALL);
|
||||
mShowing = SHOWING_NOTHING;
|
||||
}
|
||||
}
|
||||
@@ -146,7 +153,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
com.android.internal.R.color.system_notification_accent_color));
|
||||
SystemUI.overrideNotificationAppName(mContext, nb);
|
||||
final Notification n = nb.build();
|
||||
mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
|
||||
mNoMan.notifyAsUser(TAG_NOTIFICATION_BATTERY, R.id.notification_power, n, UserHandle.ALL);
|
||||
}
|
||||
|
||||
private void showWarningNotification() {
|
||||
@@ -176,12 +183,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
mPlaySound = false;
|
||||
}
|
||||
SystemUI.overrideNotificationAppName(mContext, nb);
|
||||
mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, nb.build(), UserHandle.ALL);
|
||||
}
|
||||
|
||||
private PendingIntent pendingActivity(Intent intent) {
|
||||
return PendingIntent.getActivityAsUser(mContext,
|
||||
0, intent, 0, null, UserHandle.CURRENT);
|
||||
mNoMan.notifyAsUser(
|
||||
TAG_NOTIFICATION_BATTERY, R.id.notification_power, nb.build(), UserHandle.ALL);
|
||||
}
|
||||
|
||||
private PendingIntent pendingBroadcast(String action) {
|
||||
@@ -202,6 +205,53 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
return mInvalidCharger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissTemperatureWarning() {
|
||||
if (!mTempWarning) {
|
||||
return;
|
||||
}
|
||||
mTempWarning = false;
|
||||
mNoMan.cancelAsUser(
|
||||
TAG_NOTIFICATION_TEMPERATURE, R.id.notification_temperature, UserHandle.ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTemperatureWarning() {
|
||||
if (mTempWarning) {
|
||||
return;
|
||||
}
|
||||
mTempWarning = true;
|
||||
final Notification.Builder nb = new Notification.Builder(mContext)
|
||||
.setSmallIcon(R.drawable.ic_device_thermostat_24)
|
||||
.setWhen(0)
|
||||
.setShowWhen(false)
|
||||
.setContentTitle(mContext.getString(R.string.high_temp_title))
|
||||
.setContentText(mContext.getString(R.string.high_temp_notif_message))
|
||||
.setPriority(Notification.PRIORITY_HIGH)
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
|
||||
.setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
|
||||
.setColor(mContext.getColor(
|
||||
com.android.internal.R.color.battery_saver_mode_color));
|
||||
SystemUI.overrideNotificationAppName(mContext, nb);
|
||||
final Notification n = nb.build();
|
||||
mNoMan.notifyAsUser(
|
||||
TAG_NOTIFICATION_TEMPERATURE, R.id.notification_temperature, n, UserHandle.ALL);
|
||||
|
||||
}
|
||||
|
||||
private void showTemperatureDialog() {
|
||||
if (mHighTempDialog != null) return;
|
||||
final SystemUIDialog d = new SystemUIDialog(mContext);
|
||||
d.setTitle(R.string.high_temp_title);
|
||||
d.setMessage(R.string.high_temp_dialog_message);
|
||||
d.setPositiveButton(com.android.internal.R.string.ok, null);
|
||||
d.setShowForAllUsers(true);
|
||||
d.setOnDismissListener(dialog -> mHighTempDialog = null);
|
||||
d.show();
|
||||
mHighTempDialog = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLowBatteryWarning() {
|
||||
updateNotification();
|
||||
@@ -315,6 +365,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
filter.addAction(ACTION_SHOW_BATTERY_SETTINGS);
|
||||
filter.addAction(ACTION_START_SAVER);
|
||||
filter.addAction(ACTION_DISMISSED_WARNING);
|
||||
filter.addAction(ACTION_CLICKED_TEMP_WARNING);
|
||||
filter.addAction(ACTION_DISMISSED_TEMP_WARNING);
|
||||
mContext.registerReceiverAsUser(this, UserHandle.ALL, filter,
|
||||
android.Manifest.permission.STATUS_BAR_SERVICE, mHandler);
|
||||
}
|
||||
@@ -331,6 +383,11 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
|
||||
showStartSaverConfirmation();
|
||||
} else if (action.equals(ACTION_DISMISSED_WARNING)) {
|
||||
dismissLowBatteryWarning();
|
||||
} else if (ACTION_CLICKED_TEMP_WARNING.equals(action)) {
|
||||
dismissTemperatureWarning();
|
||||
showTemperatureDialog();
|
||||
} else if (ACTION_DISMISSED_TEMP_WARNING.equals(action)) {
|
||||
dismissTemperatureWarning();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,15 @@ import android.content.IntentFilter;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HardwarePropertiesManager;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SystemUI;
|
||||
import com.android.systemui.statusbar.phone.PhoneStatusBar;
|
||||
|
||||
@@ -41,11 +43,13 @@ import java.util.Arrays;
|
||||
public class PowerUI extends SystemUI {
|
||||
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 final Handler mHandler = new Handler();
|
||||
private final Receiver mReceiver = new Receiver();
|
||||
|
||||
private PowerManager mPowerManager;
|
||||
private HardwarePropertiesManager mHardwarePropertiesManager;
|
||||
private WarningsUI mWarnings;
|
||||
private int mBatteryLevel = 100;
|
||||
private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
|
||||
@@ -57,8 +61,12 @@ public class PowerUI extends SystemUI {
|
||||
|
||||
private long mScreenOffTime = -1;
|
||||
|
||||
private float mThrottlingTemp;
|
||||
|
||||
public void start() {
|
||||
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
mHardwarePropertiesManager = (HardwarePropertiesManager)
|
||||
mContext.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE);
|
||||
mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
|
||||
mWarnings = new PowerNotificationWarnings(mContext, getComponent(PhoneStatusBar.class));
|
||||
|
||||
@@ -74,6 +82,8 @@ public class PowerUI extends SystemUI {
|
||||
false, obs, UserHandle.USER_ALL);
|
||||
updateBatteryWarningLevels();
|
||||
mReceiver.init();
|
||||
|
||||
initTemperatureWarning();
|
||||
}
|
||||
|
||||
void updateBatteryWarningLevels() {
|
||||
@@ -209,6 +219,47 @@ public class PowerUI extends SystemUI {
|
||||
}
|
||||
};
|
||||
|
||||
private void initTemperatureWarning() {
|
||||
if (!mContext.getResources().getBoolean(R.bool.config_showTemperatureWarning)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the throttling temperature. No need to check if we're not throttling.
|
||||
float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
|
||||
HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
|
||||
HardwarePropertiesManager.TEMPERATURE_THROTTLING);
|
||||
if (throttlingTemps == null
|
||||
|| throttlingTemps.length == 0
|
||||
|| throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
|
||||
return;
|
||||
}
|
||||
mThrottlingTemp = throttlingTemps[0];
|
||||
|
||||
// We have passed all of the checks, start checking the temp
|
||||
updateTemperatureWarning();
|
||||
}
|
||||
|
||||
private void updateTemperatureWarning() {
|
||||
// TODO: Add VR mode check
|
||||
float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
|
||||
HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
|
||||
HardwarePropertiesManager.TEMPERATURE_CURRENT);
|
||||
boolean shouldShowTempWarning = false;
|
||||
for (float temp : temps) {
|
||||
if (temp >= mThrottlingTemp) {
|
||||
shouldShowTempWarning = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shouldShowTempWarning) {
|
||||
mWarnings.showTemperatureWarning();
|
||||
} else {
|
||||
mWarnings.dismissTemperatureWarning();
|
||||
}
|
||||
|
||||
mHandler.postDelayed(this::updateTemperatureWarning, TEMPERATURE_INTERVAL);
|
||||
}
|
||||
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.print("mLowBatteryAlertCloseLevel=");
|
||||
pw.println(mLowBatteryAlertCloseLevel);
|
||||
@@ -235,6 +286,8 @@ public class PowerUI extends SystemUI {
|
||||
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
|
||||
pw.print("bucket: ");
|
||||
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
|
||||
pw.print("mThrottlingTemp=");
|
||||
pw.println(Float.toString(mThrottlingTemp));
|
||||
mWarnings.dump(pw);
|
||||
}
|
||||
|
||||
@@ -246,6 +299,8 @@ public class PowerUI extends SystemUI {
|
||||
void showInvalidChargerWarning();
|
||||
void updateLowBatteryWarning();
|
||||
boolean isInvalidChargerWarningShowing();
|
||||
void dismissTemperatureWarning();
|
||||
void showTemperatureWarning();
|
||||
void dump(PrintWriter pw);
|
||||
void userSwitched();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -80,8 +82,9 @@ public class HardwarePropertiesManagerService extends IHardwarePropertiesManager
|
||||
*
|
||||
* @param callingPackage The calling package name.
|
||||
*
|
||||
* @throws SecurityException if something other than the profile or device owner, or the
|
||||
* current VR service tries to retrieve information provided by this service.
|
||||
* @throws SecurityException if something other than the profile or device owner, the
|
||||
* current VR service, or a caller holding the {@link Manifest.permission#DEVICE_POWER}
|
||||
* permission tries to retrieve information provided by this service.
|
||||
*/
|
||||
private void enforceHardwarePropertiesRetrievalAllowed(String callingPackage)
|
||||
throws SecurityException {
|
||||
@@ -100,9 +103,11 @@ public class HardwarePropertiesManagerService extends IHardwarePropertiesManager
|
||||
final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
|
||||
final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
|
||||
if (!dpm.isDeviceOwnerApp(callingPackage) && !dpm.isProfileOwnerApp(callingPackage)
|
||||
&& !vrService.isCurrentVrListener(callingPackage, userId)) {
|
||||
throw new SecurityException("The caller is not a device or profile owner or bound "
|
||||
+ "VrListenerService.");
|
||||
&& !vrService.isCurrentVrListener(callingPackage, userId)
|
||||
&& mContext.checkCallingOrSelfPermission(Manifest.permission.DEVICE_POWER)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("The caller is not a device or profile owner, bound "
|
||||
+ "VrListenerService, or holding the DEVICE_POWER permission.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user