diff options
author | Evan Laird <evanlaird@google.com> | 2018-10-22 14:24:32 -0400 |
---|---|---|
committer | Evan Laird <evanlaird@google.com> | 2018-11-13 10:47:14 -0500 |
commit | 4bf21dffaa09de83d9242e1cd8a73d930eeea780 (patch) | |
tree | 9c88d93529ebb1fdcdf504578d9bbee95d9dfb50 /packages/SystemUI/src | |
parent | b513876655e04eb520d5d9b36558d3a8d3dd49e9 (diff) |
Add estimated time remaining text to QS
- Add an API to BatteryController to get an estimated time remaining
string.
- BatteryController will now check up to once per minute what the
estimated time will be and builds the string using PowerUtil.
- If the "show percentage" setting is on, the estimated time remaining
string (and battery icon) will show next to the system icons in QS
- Also make the battery percent in QS obey the setting
Test: visual
Bug: 116481529
Change-Id: Iaafa00127c8b8baae40956254a1237c8b7ac079b
Diffstat (limited to 'packages/SystemUI/src')
5 files changed, 147 insertions, 4 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index f6fec5456ed8..053ea67b92c8 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -19,7 +19,10 @@ import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; import static android.app.StatusBarManager.DISABLE_NONE; import static android.provider.Settings.System.SHOW_BATTERY_PERCENT; +import static java.lang.annotation.RetentionPolicy.SOURCE; + import android.animation.ArgbEvaluator; +import android.annotation.IntDef; import android.app.ActivityManager; import android.content.Context; import android.content.res.Resources; @@ -55,15 +58,23 @@ import com.android.systemui.statusbar.policy.IconLogger; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; import com.android.systemui.util.Utils.DisableStateTracker; -import com.android.systemui.R; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.annotation.Retention; import java.text.NumberFormat; public class BatteryMeterView extends LinearLayout implements BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener { + + @Retention(SOURCE) + @IntDef({MODE_DEFAULT, MODE_ON, MODE_OFF}) + public @interface BatteryPercentMode {} + public static final int MODE_DEFAULT = 0; + public static final int MODE_ON = 1; + public static final int MODE_OFF = 2; + private final BatteryMeterDrawableBase mDrawable; private final String mSlotBattery; private final ImageView mBatteryIconView; @@ -74,6 +85,7 @@ public class BatteryMeterView extends LinearLayout implements private SettingObserver mSettingObserver; private int mTextColor; private int mLevel; + private int mShowPercentMode = MODE_DEFAULT; private boolean mForceShowPercent; private boolean mShowPercentAvailable; @@ -154,7 +166,19 @@ public class BatteryMeterView extends LinearLayout implements } public void setForceShowPercent(boolean show) { - mForceShowPercent = show; + setPercentShowMode(show ? MODE_ON : MODE_DEFAULT); + } + + /** + * Force a particular mode of showing percent + * + * 0 - No preference + * 1 - Force on + * 2 - Force off + * @param mode desired mode (none, on, off) + */ + public void setPercentShowMode(@BatteryPercentMode int mode) { + mShowPercentMode = mode; updateShowPercent(); } @@ -273,7 +297,8 @@ public class BatteryMeterView extends LinearLayout implements .getIntForUser(getContext().getContentResolver(), SHOW_BATTERY_PERCENT, 0, mUser); - if ((mShowPercentAvailable && systemSetting) || mForceShowPercent) { + if ((mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF) + || mShowPercentMode == MODE_ON) { if (!showing) { mBatteryPercentView = loadPercentView(); if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 792909928258..e3f85d93b8da 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -15,6 +15,7 @@ package com.android.systemui.qs; import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS; +import static android.provider.Settings.System.SHOW_BATTERY_PERCENT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -28,12 +29,15 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.content.res.Resources; +import android.database.ContentObserver; import android.graphics.Color; import android.graphics.Rect; import android.media.AudioManager; +import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.provider.AlarmClock; +import android.provider.Settings; import android.service.notification.ZenModeConfig; import android.text.format.DateUtils; import android.util.AttributeSet; @@ -68,6 +72,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager; import com.android.systemui.statusbar.phone.StatusIconContainer; import com.android.systemui.statusbar.phone.SystemUIDialog; +import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.Clock; import com.android.systemui.statusbar.policy.DarkIconDispatcher; import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver; @@ -132,6 +137,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements private DateView mDateView; private OngoingPrivacyChip mPrivacyChip; private Space mSpace; + private BatteryMeterView mBatteryRemainingIcon; + private TextView mBatteryRemainingText; + private boolean mShowBatteryPercentAndEstimate; private NextAlarmController mAlarmController; private ZenModeController mZenController; @@ -148,6 +156,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements }; private boolean mHasTopCutout = false; + private final PercentSettingObserver mPercentSettingObserver = + new PercentSettingObserver(new Handler(mContext.getMainLooper())); + /** * Runnable for automatically fading out the long press tooltip (as if it were animating away). */ @@ -204,8 +215,12 @@ public class QuickStatusBarHeader extends RelativeLayout implements // Set the correct tint for the status icons so they contrast mIconManager.setTint(fillColor); + mShowBatteryPercentAndEstimate = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_battery_percentage_setting_available); + mBatteryMeterView = findViewById(R.id.battery); - mBatteryMeterView.setForceShowPercent(true); + mBatteryMeterView.setPercentShowMode(mShowBatteryPercentAndEstimate + ? BatteryMeterView.MODE_ON : BatteryMeterView.MODE_OFF); mBatteryMeterView.setOnClickListener(this); mClockView = findViewById(R.id.clock); mClockView.setOnClickListener(this); @@ -213,6 +228,15 @@ public class QuickStatusBarHeader extends RelativeLayout implements mPrivacyChip = findViewById(R.id.privacy_chip); mPrivacyChip.setOnClickListener(this); mSpace = findViewById(R.id.space); + + // Tint for the battery icons are handled in setupHost() + mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon); + mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_OFF); + + mBatteryRemainingText = findViewById(R.id.batteryRemainingText); + mBatteryRemainingText.setTextColor(fillColor); + + updateShowPercent(); } private void updateStatusText() { @@ -371,6 +395,14 @@ public class QuickStatusBarHeader extends RelativeLayout implements .build(); } + private void updateBatteryRemainingText() { + if (!mShowBatteryPercentAndEstimate) { + return; + } + mBatteryRemainingText.setText( + Dependency.get(BatteryController.class).getEstimatedTimeRemainingString()); + } + public void setExpanded(boolean expanded) { if (mExpanded == expanded) return; mExpanded = expanded; @@ -436,6 +468,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements super.onAttachedToWindow(); Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager); requestApplyInsets(); + mContext.getContentResolver().registerContentObserver( + Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mPercentSettingObserver, + ActivityManager.getCurrentUser()); } @Override @@ -475,6 +510,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements public void onDetachedFromWindow() { setListening(false); Dependency.get(StatusBarIconController.class).removeIconGroup(mIconManager); + mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver); super.onDetachedFromWindow(); } @@ -491,6 +527,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements mAlarmController.addCallback(this); mContext.registerReceiver(mRingerReceiver, new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)); + updateBatteryRemainingText(); } else { mZenController.removeCallback(this); mAlarmController.removeCallback(this); @@ -660,6 +697,14 @@ public class QuickStatusBarHeader extends RelativeLayout implements // Use SystemUI context to get battery meter colors, and let it use the default tint (white) mBatteryMeterView.setColorsFromContext(mHost.getContext()); mBatteryMeterView.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT); + + Rect tintArea = new Rect(0, 0, 0, 0); + int colorForeground = Utils.getColorAttrDefaultColor(getContext(), + android.R.attr.colorForeground); + float intensity = getColorIntensity(colorForeground); + int fillColor = fillColorForIntensity(intensity, getContext()); + mBatteryRemainingIcon.setColorsFromContext(mHost.getContext()); + mBatteryRemainingIcon.onDarkChanged(tintArea, intensity, fillColor); } public void setCallback(Callback qsPanelCallback) { @@ -692,4 +737,39 @@ public class QuickStatusBarHeader extends RelativeLayout implements lp.rightMargin = sideMargins; } } + + private void updateShowPercent() { + final boolean systemSetting = 0 != Settings.System + .getIntForUser(getContext().getContentResolver(), + SHOW_BATTERY_PERCENT, 0, ActivityManager.getCurrentUser()); + + mShowBatteryPercentAndEstimate = systemSetting; + + updateBatteryViews(); + } + + private void updateBatteryViews() { + if (mShowBatteryPercentAndEstimate) { + mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON); + mBatteryRemainingIcon.setVisibility(View.VISIBLE); + mBatteryRemainingText.setVisibility(View.VISIBLE); + updateBatteryRemainingText(); + } else { + mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_OFF); + mBatteryRemainingIcon.setVisibility(View.GONE); + mBatteryRemainingText.setVisibility(View.GONE); + } + } + + private final class PercentSettingObserver extends ContentObserver { + PercentSettingObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + updateShowPercent(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java index 7f3537c2d41d..da2828eae7da 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.graphics.drawable.Drawable; import android.service.quicksettings.Tile; import android.widget.Switch; + import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settingslib.graph.BatteryMeterDrawableBase; import com.android.systemui.Dependency; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index 6f4026db5633..f65f8261dcfb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -55,4 +55,11 @@ public interface BatteryController extends DemoMode, Dumpable, default void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {} default void onPowerSaveChanged(boolean isPowerSave) {} } + + /** + * If available, get the estimated battery time remaining as a string + */ + default String getEstimatedTimeRemainingString() { + return null; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index 7221efab0bb2..ddcfbf6f3c31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -29,9 +29,14 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.fuelgauge.BatterySaverUtils; +import com.android.settingslib.utils.PowerUtil; +import com.android.systemui.Dependency; +import com.android.systemui.power.EnhancedEstimates; +import com.android.systemui.power.Estimate; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.text.NumberFormat; import java.util.ArrayList; /** @@ -44,7 +49,9 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final int UPDATE_GRANULARITY_MSEC = 1000 * 60; + private final EnhancedEstimates mEstimates = Dependency.get(EnhancedEstimates.class); private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>(); private final PowerManager mPowerManager; private final Handler mHandler; @@ -58,6 +65,8 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC protected boolean mAodPowerSave; private boolean mTestmode = false; private boolean mHasReceivedBattery = false; + private Estimate mEstimate; + private long mLastEstimateTimestamp = -1; public BatteryControllerImpl(Context context) { this(context, context.getSystemService(PowerManager.class)); @@ -71,6 +80,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC registerReceiver(); updatePowerSave(); + updateEstimate(); } private void registerReceiver() { @@ -180,6 +190,26 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC return mAodPowerSave; } + @Override + public String getEstimatedTimeRemainingString() { + if (mEstimate == null + || System.currentTimeMillis() > mLastEstimateTimestamp + UPDATE_GRANULARITY_MSEC) { + updateEstimate(); + } + // Estimates may not exist yet even if we've checked + if (mEstimate == null) { + return null; + } + final String percentage = NumberFormat.getPercentInstance().format((double) mLevel / 100.0); + return PowerUtil.getBatteryRemainingShortStringFormatted( + mContext, mEstimate.estimateMillis); + } + + private void updateEstimate() { + mEstimate = mEstimates.getEstimate(); + mLastEstimateTimestamp = System.currentTimeMillis(); + } + private void updatePowerSave() { setPowerSave(mPowerManager.isPowerSaveMode()); } |