Merge changes from topic "caitlinshk-dock-defend-initial" into tm-qpr-dev am: 879714254a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20454811 Change-Id: I74e233d2b3f566108a29752e78e9a37327314166 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -412,14 +412,13 @@ open class ThemedBatteryDrawable(private val context: Context, frameColor: Int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "ThemedBatteryDrawable"
|
const val WIDTH = 12f
|
||||||
private const val WIDTH = 12f
|
const val HEIGHT = 20f
|
||||||
private const val HEIGHT = 20f
|
|
||||||
private const val CRITICAL_LEVEL = 15
|
private const val CRITICAL_LEVEL = 15
|
||||||
// On a 12x20 grid, how wide to make the fill protection stroke.
|
// On a 12x20 grid, how wide to make the fill protection stroke.
|
||||||
// Scales when our size changes
|
// Scales when our size changes
|
||||||
private const val PROTECTION_STROKE_WIDTH = 3f
|
private const val PROTECTION_STROKE_WIDTH = 3f
|
||||||
// Arbitrarily chosen for visibility at small sizes
|
// Arbitrarily chosen for visibility at small sizes
|
||||||
private const val PROTECTION_MIN_STROKE_WIDTH = 6f
|
const val PROTECTION_MIN_STROKE_WIDTH = 6f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -485,6 +485,12 @@
|
|||||||
<!-- Whether to show a severe low battery dialog. -->
|
<!-- Whether to show a severe low battery dialog. -->
|
||||||
<bool name="config_severe_battery_dialog">false</bool>
|
<bool name="config_severe_battery_dialog">false</bool>
|
||||||
|
|
||||||
|
<!-- A path representing a shield. Will sometimes be displayed with the battery icon when
|
||||||
|
needed. This path is a 10px wide and 13px tall. -->
|
||||||
|
<string name="config_batterymeterShieldPath" translatable="false">
|
||||||
|
M5 0L0 1.88V6.19C0 9.35 2.13 12.29 5 13.01C7.87 12.29 10 9.35 10 6.19V1.88L5 0Z
|
||||||
|
</string>
|
||||||
|
|
||||||
<!-- A path similar to frameworks/base/core/res/res/values/config.xml
|
<!-- A path similar to frameworks/base/core/res/res/values/config.xml
|
||||||
config_mainBuiltInDisplayCutout that describes a path larger than the exact path of a display
|
config_mainBuiltInDisplayCutout that describes a path larger than the exact path of a display
|
||||||
cutout. If present as well as config_enableDisplayCutoutProtection is set to true, then
|
cutout. If present as well as config_enableDisplayCutoutProtection is set to true, then
|
||||||
|
|||||||
@@ -105,6 +105,12 @@
|
|||||||
so the width of the icon should be 13.0dp * (12.0 / 20.0) -->
|
so the width of the icon should be 13.0dp * (12.0 / 20.0) -->
|
||||||
<dimen name="status_bar_battery_icon_width">7.8dp</dimen>
|
<dimen name="status_bar_battery_icon_width">7.8dp</dimen>
|
||||||
|
|
||||||
|
<!-- The battery icon is 13dp tall, but the other system icons are 15dp tall (see
|
||||||
|
@*android:dimen/status_bar_system_icon_size) with some top and bottom padding embedded in
|
||||||
|
the drawables themselves. So, the battery icon may need an extra 1dp of spacing so that its
|
||||||
|
bottom still aligns with the bottom of all the other system icons. See b/258672854. -->
|
||||||
|
<dimen name="status_bar_battery_extra_vertical_spacing">1dp</dimen>
|
||||||
|
|
||||||
<!-- The font size for the clock in the status bar. -->
|
<!-- The font size for the clock in the status bar. -->
|
||||||
<dimen name="status_bar_clock_size">14sp</dimen>
|
<dimen name="status_bar_clock_size">14sp</dimen>
|
||||||
|
|
||||||
|
|||||||
@@ -439,11 +439,17 @@
|
|||||||
<string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
|
<string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
|
||||||
|
|
||||||
<!-- Content description of the battery level icon for accessibility, including the estimated time remaining before the phone runs out of battery (not shown on the screen). [CHAR LIMIT=NONE] -->
|
<!-- Content description of the battery level icon for accessibility, including the estimated time remaining before the phone runs out of battery (not shown on the screen). [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$s</xliff:g> percent, about <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g> left based on your usage</string>
|
<string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$d</xliff:g> percent, about <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g> left based on your usage</string>
|
||||||
|
|
||||||
<!-- Content description of the battery level icon for accessibility while the device is charging (not shown on the screen). [CHAR LIMIT=NONE] -->
|
<!-- Content description of the battery level icon for accessibility while the device is charging (not shown on the screen). [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_battery_level_charging">Battery charging, <xliff:g id="battery_percentage">%d</xliff:g> percent.</string>
|
<string name="accessibility_battery_level_charging">Battery charging, <xliff:g id="battery_percentage">%d</xliff:g> percent.</string>
|
||||||
|
|
||||||
|
<!-- Content description of the battery level icon for accessibility, with information that the device charging is paused in order to protect the lifetime of the battery (not shown on screen). [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="accessibility_battery_level_charging_paused">Battery <xliff:g id="percentage" example="90%">%d</xliff:g> percent. Charging paused for battery protection.</string>
|
||||||
|
|
||||||
|
<!-- Content description of the battery level icon for accessibility, including the estimated time remaining before the phone runs out of battery *and* information that the device charging is paused in order to protect the lifetime of the battery (not shown on screen). [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="accessibility_battery_level_charging_paused_with_estimate">Battery <xliff:g id="percentage" example="90%">%1$d</xliff:g> percent, about <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g> left based on your usage. Charging paused for battery protection.</string>
|
||||||
|
|
||||||
<!-- Content description of overflow icon container of the notifications for accessibility (not shown on the screen)[CHAR LIMIT=NONE] -->
|
<!-- Content description of overflow icon container of the notifications for accessibility (not shown on the screen)[CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_overflow_action">See all notifications</string>
|
<string name="accessibility_overflow_action">See all notifications</string>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.battery
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.ColorFilter
|
||||||
|
import android.graphics.Matrix
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Path
|
||||||
|
import android.graphics.PixelFormat
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.graphics.PorterDuffXfermode
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.graphics.drawable.DrawableWrapper
|
||||||
|
import android.util.PathParser
|
||||||
|
import com.android.settingslib.graph.ThemedBatteryDrawable
|
||||||
|
import com.android.systemui.R
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT_WITH_SHIELD
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH_WITH_SHIELD
|
||||||
|
import com.android.systemui.battery.BatterySpecs.SHIELD_LEFT_OFFSET
|
||||||
|
import com.android.systemui.battery.BatterySpecs.SHIELD_STROKE
|
||||||
|
import com.android.systemui.battery.BatterySpecs.SHIELD_TOP_OFFSET
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A battery drawable that accessorizes [ThemedBatteryDrawable] with additional information if
|
||||||
|
* necessary.
|
||||||
|
*
|
||||||
|
* For now, it adds a shield in the bottom-right corner when [displayShield] is true.
|
||||||
|
*/
|
||||||
|
class AccessorizedBatteryDrawable(
|
||||||
|
private val context: Context,
|
||||||
|
frameColor: Int,
|
||||||
|
) : DrawableWrapper(ThemedBatteryDrawable(context, frameColor)) {
|
||||||
|
private val mainBatteryDrawable: ThemedBatteryDrawable
|
||||||
|
get() = drawable as ThemedBatteryDrawable
|
||||||
|
|
||||||
|
private val shieldPath = Path()
|
||||||
|
private val scaledShield = Path()
|
||||||
|
private val scaleMatrix = Matrix()
|
||||||
|
|
||||||
|
private var shieldLeftOffsetScaled = SHIELD_LEFT_OFFSET
|
||||||
|
private var shieldTopOffsetScaled = SHIELD_TOP_OFFSET
|
||||||
|
|
||||||
|
private var density = context.resources.displayMetrics.density
|
||||||
|
|
||||||
|
private val dualTone =
|
||||||
|
context.resources.getBoolean(com.android.internal.R.bool.config_batterymeterDualTone)
|
||||||
|
|
||||||
|
private val shieldTransparentOutlinePaint =
|
||||||
|
Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
|
||||||
|
p.color = Color.TRANSPARENT
|
||||||
|
p.strokeWidth = ThemedBatteryDrawable.PROTECTION_MIN_STROKE_WIDTH
|
||||||
|
p.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
|
||||||
|
p.style = Paint.Style.FILL_AND_STROKE
|
||||||
|
}
|
||||||
|
|
||||||
|
private val shieldPaint =
|
||||||
|
Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
|
||||||
|
p.color = Color.MAGENTA
|
||||||
|
p.style = Paint.Style.FILL
|
||||||
|
p.isDither = true
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
loadPaths()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBoundsChange(bounds: Rect) {
|
||||||
|
super.onBoundsChange(bounds)
|
||||||
|
updateSizes()
|
||||||
|
}
|
||||||
|
|
||||||
|
var displayShield: Boolean = false
|
||||||
|
|
||||||
|
private fun updateSizes() {
|
||||||
|
val b = bounds
|
||||||
|
if (b.isEmpty) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val mainWidth = BatterySpecs.getMainBatteryWidth(b.width().toFloat(), displayShield)
|
||||||
|
val mainHeight = BatterySpecs.getMainBatteryHeight(b.height().toFloat(), displayShield)
|
||||||
|
|
||||||
|
drawable?.setBounds(
|
||||||
|
b.left,
|
||||||
|
b.top,
|
||||||
|
/* right= */ b.left + mainWidth.toInt(),
|
||||||
|
/* bottom= */ b.top + mainHeight.toInt()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (displayShield) {
|
||||||
|
val sx = b.right / BATTERY_WIDTH_WITH_SHIELD
|
||||||
|
val sy = b.bottom / BATTERY_HEIGHT_WITH_SHIELD
|
||||||
|
scaleMatrix.setScale(sx, sy)
|
||||||
|
shieldPath.transform(scaleMatrix, scaledShield)
|
||||||
|
|
||||||
|
shieldLeftOffsetScaled = sx * SHIELD_LEFT_OFFSET
|
||||||
|
shieldTopOffsetScaled = sy * SHIELD_TOP_OFFSET
|
||||||
|
|
||||||
|
val scaledStrokeWidth =
|
||||||
|
(sx * SHIELD_STROKE).coerceAtLeast(
|
||||||
|
ThemedBatteryDrawable.PROTECTION_MIN_STROKE_WIDTH
|
||||||
|
)
|
||||||
|
shieldTransparentOutlinePaint.strokeWidth = scaledStrokeWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIntrinsicHeight(): Int {
|
||||||
|
val height =
|
||||||
|
if (displayShield) {
|
||||||
|
BATTERY_HEIGHT_WITH_SHIELD
|
||||||
|
} else {
|
||||||
|
BATTERY_HEIGHT
|
||||||
|
}
|
||||||
|
return (height * density).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIntrinsicWidth(): Int {
|
||||||
|
val width =
|
||||||
|
if (displayShield) {
|
||||||
|
BATTERY_WIDTH_WITH_SHIELD
|
||||||
|
} else {
|
||||||
|
BATTERY_WIDTH
|
||||||
|
}
|
||||||
|
return (width * density).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun draw(c: Canvas) {
|
||||||
|
c.saveLayer(null, null)
|
||||||
|
// Draw the main battery icon
|
||||||
|
super.draw(c)
|
||||||
|
|
||||||
|
if (displayShield) {
|
||||||
|
c.translate(shieldLeftOffsetScaled, shieldTopOffsetScaled)
|
||||||
|
// We need a transparent outline around the shield, so first draw the transparent-ness
|
||||||
|
// then draw the shield
|
||||||
|
c.drawPath(scaledShield, shieldTransparentOutlinePaint)
|
||||||
|
c.drawPath(scaledShield, shieldPaint)
|
||||||
|
}
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOpacity(): Int {
|
||||||
|
return PixelFormat.OPAQUE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setAlpha(p0: Int) {
|
||||||
|
// Unused internally -- see [ThemedBatteryDrawable.setAlpha].
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setColorFilter(colorfilter: ColorFilter?) {
|
||||||
|
super.setColorFilter(colorFilter)
|
||||||
|
shieldPaint.colorFilter = colorFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets whether the battery is currently charging. */
|
||||||
|
fun setCharging(charging: Boolean) {
|
||||||
|
mainBatteryDrawable.charging = charging
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the current level (out of 100) of the battery. */
|
||||||
|
fun setBatteryLevel(level: Int) {
|
||||||
|
mainBatteryDrawable.setBatteryLevel(level)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets whether power save is enabled. */
|
||||||
|
fun setPowerSaveEnabled(powerSaveEnabled: Boolean) {
|
||||||
|
mainBatteryDrawable.powerSaveEnabled = powerSaveEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether power save is currently enabled. */
|
||||||
|
fun getPowerSaveEnabled(): Boolean {
|
||||||
|
return mainBatteryDrawable.powerSaveEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the colors to use for the icon. */
|
||||||
|
fun setColors(fgColor: Int, bgColor: Int, singleToneColor: Int) {
|
||||||
|
shieldPaint.color = if (dualTone) fgColor else singleToneColor
|
||||||
|
mainBatteryDrawable.setColors(fgColor, bgColor, singleToneColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Notifies this drawable that the density might have changed. */
|
||||||
|
fun notifyDensityChanged() {
|
||||||
|
density = context.resources.displayMetrics.density
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadPaths() {
|
||||||
|
val shieldPathString = context.resources.getString(R.string.config_batterymeterShieldPath)
|
||||||
|
shieldPath.set(PathParser.createPathFromPathData(shieldPathString))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,6 @@ import android.widget.TextView;
|
|||||||
import androidx.annotation.StyleRes;
|
import androidx.annotation.StyleRes;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.settingslib.graph.ThemedBatteryDrawable;
|
|
||||||
import com.android.systemui.DualToneHandler;
|
import com.android.systemui.DualToneHandler;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.animation.Interpolators;
|
import com.android.systemui.animation.Interpolators;
|
||||||
@@ -68,7 +67,7 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
public static final int MODE_OFF = 2;
|
public static final int MODE_OFF = 2;
|
||||||
public static final int MODE_ESTIMATE = 3;
|
public static final int MODE_ESTIMATE = 3;
|
||||||
|
|
||||||
private final ThemedBatteryDrawable mDrawable;
|
private final AccessorizedBatteryDrawable mDrawable;
|
||||||
private final ImageView mBatteryIconView;
|
private final ImageView mBatteryIconView;
|
||||||
private TextView mBatteryPercentView;
|
private TextView mBatteryPercentView;
|
||||||
|
|
||||||
@@ -77,7 +76,10 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
private int mLevel;
|
private int mLevel;
|
||||||
private int mShowPercentMode = MODE_DEFAULT;
|
private int mShowPercentMode = MODE_DEFAULT;
|
||||||
private boolean mShowPercentAvailable;
|
private boolean mShowPercentAvailable;
|
||||||
|
private String mEstimateText = null;
|
||||||
private boolean mCharging;
|
private boolean mCharging;
|
||||||
|
private boolean mIsOverheated;
|
||||||
|
private boolean mDisplayShieldEnabled;
|
||||||
// Error state where we know nothing about the current battery state
|
// Error state where we know nothing about the current battery state
|
||||||
private boolean mBatteryStateUnknown;
|
private boolean mBatteryStateUnknown;
|
||||||
// Lazily-loaded since this is expected to be a rare-if-ever state
|
// Lazily-loaded since this is expected to be a rare-if-ever state
|
||||||
@@ -106,7 +108,7 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
|
final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
|
||||||
context.getColor(R.color.meter_background_color));
|
context.getColor(R.color.meter_background_color));
|
||||||
mPercentageStyleId = atts.getResourceId(R.styleable.BatteryMeterView_textAppearance, 0);
|
mPercentageStyleId = atts.getResourceId(R.styleable.BatteryMeterView_textAppearance, 0);
|
||||||
mDrawable = new ThemedBatteryDrawable(context, frameColor);
|
mDrawable = new AccessorizedBatteryDrawable(context, frameColor);
|
||||||
atts.recycle();
|
atts.recycle();
|
||||||
|
|
||||||
mShowPercentAvailable = context.getResources().getBoolean(
|
mShowPercentAvailable = context.getResources().getBoolean(
|
||||||
@@ -170,12 +172,14 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
if (mode == mShowPercentMode) return;
|
if (mode == mShowPercentMode) return;
|
||||||
mShowPercentMode = mode;
|
mShowPercentMode = mode;
|
||||||
updateShowPercent();
|
updateShowPercent();
|
||||||
|
updatePercentText();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onConfigurationChanged(Configuration newConfig) {
|
protected void onConfigurationChanged(Configuration newConfig) {
|
||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
updatePercentView();
|
updatePercentView();
|
||||||
|
mDrawable.notifyDensityChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColorsFromContext(Context context) {
|
public void setColorsFromContext(Context context) {
|
||||||
@@ -203,6 +207,17 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
mDrawable.setPowerSaveEnabled(isPowerSave);
|
mDrawable.setPowerSaveEnabled(isPowerSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onIsOverheatedChanged(boolean isOverheated) {
|
||||||
|
boolean valueChanged = mIsOverheated != isOverheated;
|
||||||
|
mIsOverheated = isOverheated;
|
||||||
|
if (valueChanged) {
|
||||||
|
updateContentDescription();
|
||||||
|
// The battery drawable is a different size depending on whether it's currently
|
||||||
|
// overheated or not, so we need to re-scale the view when overheated changes.
|
||||||
|
scaleBatteryMeterViews();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private TextView loadPercentView() {
|
private TextView loadPercentView() {
|
||||||
return (TextView) LayoutInflater.from(getContext())
|
return (TextView) LayoutInflater.from(getContext())
|
||||||
.inflate(R.layout.battery_percentage_view, null);
|
.inflate(R.layout.battery_percentage_view, null);
|
||||||
@@ -227,13 +242,17 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
mBatteryEstimateFetcher = fetcher;
|
mBatteryEstimateFetcher = fetcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setDisplayShieldEnabled(boolean displayShieldEnabled) {
|
||||||
|
mDisplayShieldEnabled = displayShieldEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
void updatePercentText() {
|
void updatePercentText() {
|
||||||
if (mBatteryStateUnknown) {
|
if (mBatteryStateUnknown) {
|
||||||
setContentDescription(getContext().getString(R.string.accessibility_battery_unknown));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBatteryEstimateFetcher == null) {
|
if (mBatteryEstimateFetcher == null) {
|
||||||
|
setPercentTextAtCurrentLevel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,10 +264,9 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (estimate != null && mShowPercentMode == MODE_ESTIMATE) {
|
if (estimate != null && mShowPercentMode == MODE_ESTIMATE) {
|
||||||
|
mEstimateText = estimate;
|
||||||
mBatteryPercentView.setText(estimate);
|
mBatteryPercentView.setText(estimate);
|
||||||
setContentDescription(getContext().getString(
|
updateContentDescription();
|
||||||
R.string.accessibility_battery_level_with_estimate,
|
|
||||||
mLevel, estimate));
|
|
||||||
} else {
|
} else {
|
||||||
setPercentTextAtCurrentLevel();
|
setPercentTextAtCurrentLevel();
|
||||||
}
|
}
|
||||||
@@ -257,28 +275,49 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
setPercentTextAtCurrentLevel();
|
setPercentTextAtCurrentLevel();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setContentDescription(
|
updateContentDescription();
|
||||||
getContext().getString(mCharging ? R.string.accessibility_battery_level_charging
|
|
||||||
: R.string.accessibility_battery_level, mLevel));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPercentTextAtCurrentLevel() {
|
private void setPercentTextAtCurrentLevel() {
|
||||||
if (mBatteryPercentView == null) {
|
if (mBatteryPercentView != null) {
|
||||||
return;
|
mEstimateText = null;
|
||||||
|
String percentText = NumberFormat.getPercentInstance().format(mLevel / 100f);
|
||||||
|
// Setting text actually triggers a layout pass (because the text view is set to
|
||||||
|
// wrap_content width and TextView always relayouts for this). Avoid needless
|
||||||
|
// relayout if the text didn't actually change.
|
||||||
|
if (!TextUtils.equals(mBatteryPercentView.getText(), percentText)) {
|
||||||
|
mBatteryPercentView.setText(percentText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String percentText = NumberFormat.getPercentInstance().format(mLevel / 100f);
|
updateContentDescription();
|
||||||
// Setting text actually triggers a layout pass (because the text view is set to
|
}
|
||||||
// wrap_content width and TextView always relayouts for this). Avoid needless
|
|
||||||
// relayout if the text didn't actually change.
|
private void updateContentDescription() {
|
||||||
if (!TextUtils.equals(mBatteryPercentView.getText(), percentText)) {
|
Context context = getContext();
|
||||||
mBatteryPercentView.setText(percentText);
|
|
||||||
|
String contentDescription;
|
||||||
|
if (mBatteryStateUnknown) {
|
||||||
|
contentDescription = context.getString(R.string.accessibility_battery_unknown);
|
||||||
|
} else if (mShowPercentMode == MODE_ESTIMATE && !TextUtils.isEmpty(mEstimateText)) {
|
||||||
|
contentDescription = context.getString(
|
||||||
|
mIsOverheated
|
||||||
|
? R.string.accessibility_battery_level_charging_paused_with_estimate
|
||||||
|
: R.string.accessibility_battery_level_with_estimate,
|
||||||
|
mLevel,
|
||||||
|
mEstimateText);
|
||||||
|
} else if (mIsOverheated) {
|
||||||
|
contentDescription =
|
||||||
|
context.getString(R.string.accessibility_battery_level_charging_paused, mLevel);
|
||||||
|
} else if (mCharging) {
|
||||||
|
contentDescription =
|
||||||
|
context.getString(R.string.accessibility_battery_level_charging, mLevel);
|
||||||
|
} else {
|
||||||
|
contentDescription = context.getString(R.string.accessibility_battery_level, mLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentDescription(
|
setContentDescription(contentDescription);
|
||||||
getContext().getString(mCharging ? R.string.accessibility_battery_level_charging
|
|
||||||
: R.string.accessibility_battery_level, mLevel));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateShowPercent() {
|
void updateShowPercent() {
|
||||||
@@ -329,6 +368,7 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mBatteryStateUnknown = isUnknown;
|
mBatteryStateUnknown = isUnknown;
|
||||||
|
updateContentDescription();
|
||||||
|
|
||||||
if (mBatteryStateUnknown) {
|
if (mBatteryStateUnknown) {
|
||||||
mBatteryIconView.setImageDrawable(getUnknownStateDrawable());
|
mBatteryIconView.setImageDrawable(getUnknownStateDrawable());
|
||||||
@@ -349,15 +389,43 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
|
|||||||
res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
|
res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
|
||||||
float iconScaleFactor = typedValue.getFloat();
|
float iconScaleFactor = typedValue.getFloat();
|
||||||
|
|
||||||
int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
|
float mainBatteryHeight =
|
||||||
int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
|
res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height) * iconScaleFactor;
|
||||||
|
float mainBatteryWidth =
|
||||||
|
res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width) * iconScaleFactor;
|
||||||
|
|
||||||
|
// If the battery is marked as overheated, we should display a shield indicating that the
|
||||||
|
// battery is being "defended".
|
||||||
|
boolean displayShield = mDisplayShieldEnabled && mIsOverheated;
|
||||||
|
float fullBatteryIconHeight =
|
||||||
|
BatterySpecs.getFullBatteryHeight(mainBatteryHeight, displayShield);
|
||||||
|
float fullBatteryIconWidth =
|
||||||
|
BatterySpecs.getFullBatteryWidth(mainBatteryWidth, displayShield);
|
||||||
|
|
||||||
|
int marginTop;
|
||||||
|
if (displayShield) {
|
||||||
|
// If the shield is displayed, we need some extra marginTop so that the bottom of the
|
||||||
|
// main icon is still aligned with the bottom of all the other system icons.
|
||||||
|
int shieldHeightAddition = Math.round(fullBatteryIconHeight - mainBatteryHeight);
|
||||||
|
// However, the other system icons have some embedded bottom padding that the battery
|
||||||
|
// doesn't have, so we shouldn't move the battery icon down by the full amount.
|
||||||
|
// See b/258672854.
|
||||||
|
marginTop = shieldHeightAddition
|
||||||
|
- res.getDimensionPixelSize(R.dimen.status_bar_battery_extra_vertical_spacing);
|
||||||
|
} else {
|
||||||
|
marginTop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
|
int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
|
||||||
|
|
||||||
LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
|
LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
|
||||||
(int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
|
Math.round(fullBatteryIconWidth),
|
||||||
scaledLayoutParams.setMargins(0, 0, 0, marginBottom);
|
Math.round(fullBatteryIconHeight));
|
||||||
|
scaledLayoutParams.setMargins(0, marginTop, 0, marginBottom);
|
||||||
|
|
||||||
|
mDrawable.setDisplayShield(displayShield);
|
||||||
mBatteryIconView.setLayoutParams(scaledLayoutParams);
|
mBatteryIconView.setLayoutParams(scaledLayoutParams);
|
||||||
|
mBatteryIconView.invalidateDrawable(mDrawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import android.view.View;
|
|||||||
|
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
|
import com.android.systemui.flags.Flags;
|
||||||
import com.android.systemui.settings.CurrentUserTracker;
|
import com.android.systemui.settings.CurrentUserTracker;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||||
import com.android.systemui.statusbar.policy.BatteryController;
|
import com.android.systemui.statusbar.policy.BatteryController;
|
||||||
@@ -84,6 +86,11 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
|
|||||||
public void onBatteryUnknownStateChanged(boolean isUnknown) {
|
public void onBatteryUnknownStateChanged(boolean isUnknown) {
|
||||||
mView.onBatteryUnknownStateChanged(isUnknown);
|
mView.onBatteryUnknownStateChanged(isUnknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onIsOverheatedChanged(boolean isOverheated) {
|
||||||
|
mView.onIsOverheatedChanged(isOverheated);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Some places may need to show the battery conditionally, and not obey the tuner
|
// Some places may need to show the battery conditionally, and not obey the tuner
|
||||||
@@ -98,6 +105,7 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
|
|||||||
BroadcastDispatcher broadcastDispatcher,
|
BroadcastDispatcher broadcastDispatcher,
|
||||||
@Main Handler mainHandler,
|
@Main Handler mainHandler,
|
||||||
ContentResolver contentResolver,
|
ContentResolver contentResolver,
|
||||||
|
FeatureFlags featureFlags,
|
||||||
BatteryController batteryController) {
|
BatteryController batteryController) {
|
||||||
super(view);
|
super(view);
|
||||||
mConfigurationController = configurationController;
|
mConfigurationController = configurationController;
|
||||||
@@ -106,6 +114,7 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
|
|||||||
mBatteryController = batteryController;
|
mBatteryController = batteryController;
|
||||||
|
|
||||||
mView.setBatteryEstimateFetcher(mBatteryController::getEstimatedTimeRemainingString);
|
mView.setBatteryEstimateFetcher(mBatteryController::getEstimatedTimeRemainingString);
|
||||||
|
mView.setDisplayShieldEnabled(featureFlags.isEnabled(Flags.BATTERY_SHIELD_ICON));
|
||||||
|
|
||||||
mSlotBattery = getResources().getString(com.android.internal.R.string.status_bar_battery);
|
mSlotBattery = getResources().getString(com.android.internal.R.string.status_bar_battery);
|
||||||
mSettingObserver = new SettingObserver(mainHandler);
|
mSettingObserver = new SettingObserver(mainHandler);
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.battery
|
||||||
|
|
||||||
|
import com.android.settingslib.graph.ThemedBatteryDrawable
|
||||||
|
|
||||||
|
/** An object storing specs related to the battery icon in the status bar. */
|
||||||
|
object BatterySpecs {
|
||||||
|
|
||||||
|
/** Width of the main battery icon, not including the shield. */
|
||||||
|
const val BATTERY_WIDTH = ThemedBatteryDrawable.WIDTH
|
||||||
|
/** Height of the main battery icon, not including the shield. */
|
||||||
|
const val BATTERY_HEIGHT = ThemedBatteryDrawable.HEIGHT
|
||||||
|
|
||||||
|
private const val SHIELD_WIDTH = 10f
|
||||||
|
private const val SHIELD_HEIGHT = 13f
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount that the left side of the shield should be offset from the left side of the battery.
|
||||||
|
*/
|
||||||
|
const val SHIELD_LEFT_OFFSET = 8f
|
||||||
|
/** Amount that the top of the shield should be offset from the top of the battery. */
|
||||||
|
const val SHIELD_TOP_OFFSET = 10f
|
||||||
|
|
||||||
|
const val SHIELD_STROKE = 4f
|
||||||
|
|
||||||
|
/** The full width of the battery icon, including the main battery icon *and* the shield. */
|
||||||
|
const val BATTERY_WIDTH_WITH_SHIELD = SHIELD_LEFT_OFFSET + SHIELD_WIDTH
|
||||||
|
/** The full height of the battery icon, including the main battery icon *and* the shield. */
|
||||||
|
const val BATTERY_HEIGHT_WITH_SHIELD = SHIELD_TOP_OFFSET + SHIELD_HEIGHT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the desired height of the main battery icon in pixels, returns the height that the full
|
||||||
|
* battery icon will take up in pixels.
|
||||||
|
*
|
||||||
|
* If there's no shield, this will just return [mainBatteryHeight]. Otherwise, the shield
|
||||||
|
* extends slightly below the bottom of the main battery icon so we need some extra height.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getFullBatteryHeight(mainBatteryHeight: Float, displayShield: Boolean): Float {
|
||||||
|
return if (!displayShield) {
|
||||||
|
mainBatteryHeight
|
||||||
|
} else {
|
||||||
|
val verticalScaleFactor = mainBatteryHeight / BATTERY_HEIGHT
|
||||||
|
verticalScaleFactor * BATTERY_HEIGHT_WITH_SHIELD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the desired width of the main battery icon in pixels, returns the width that the full
|
||||||
|
* battery icon will take up in pixels.
|
||||||
|
*
|
||||||
|
* If there's no shield, this will just return [mainBatteryWidth]. Otherwise, the shield extends
|
||||||
|
* past the right side of the main battery icon so we need some extra width.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getFullBatteryWidth(mainBatteryWidth: Float, displayShield: Boolean): Float {
|
||||||
|
return if (!displayShield) {
|
||||||
|
mainBatteryWidth
|
||||||
|
} else {
|
||||||
|
val horizontalScaleFactor = mainBatteryWidth / BATTERY_WIDTH
|
||||||
|
horizontalScaleFactor * BATTERY_WIDTH_WITH_SHIELD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the height of the full battery icon, return how tall the main battery icon should be.
|
||||||
|
*
|
||||||
|
* If there's no shield, this will just return [fullBatteryHeight]. Otherwise, the shield takes
|
||||||
|
* up some of the view's height so the main battery width will be just a portion of
|
||||||
|
* [fullBatteryHeight].
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getMainBatteryHeight(fullBatteryHeight: Float, displayShield: Boolean): Float {
|
||||||
|
return if (!displayShield) {
|
||||||
|
fullBatteryHeight
|
||||||
|
} else {
|
||||||
|
return (BATTERY_HEIGHT / BATTERY_HEIGHT_WITH_SHIELD) * fullBatteryHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the width of the full battery icon, return how wide the main battery icon should be.
|
||||||
|
*
|
||||||
|
* If there's no shield, this will just return [fullBatteryWidth]. Otherwise, the shield takes
|
||||||
|
* up some of the view's width so the main battery width will be just a portion of
|
||||||
|
* [fullBatteryWidth].
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getMainBatteryWidth(fullBatteryWidth: Float, displayShield: Boolean): Float {
|
||||||
|
return if (!displayShield) {
|
||||||
|
fullBatteryWidth
|
||||||
|
} else {
|
||||||
|
return (BATTERY_WIDTH / BATTERY_WIDTH_WITH_SHIELD) * fullBatteryWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -239,6 +239,9 @@ object Flags {
|
|||||||
// TODO(b/256613548): Tracking Bug
|
// TODO(b/256613548): Tracking Bug
|
||||||
val NEW_STATUS_BAR_WIFI_ICON_BACKEND = unreleasedFlag(609, "new_status_bar_wifi_icon_backend")
|
val NEW_STATUS_BAR_WIFI_ICON_BACKEND = unreleasedFlag(609, "new_status_bar_wifi_icon_backend")
|
||||||
|
|
||||||
|
// TODO(b/256623670): Tracking Bug
|
||||||
|
@JvmField val BATTERY_SHIELD_ICON = unreleasedFlag(610, "battery_shield_icon")
|
||||||
|
|
||||||
// 700 - dialer/calls
|
// 700 - dialer/calls
|
||||||
// TODO(b/254512734): Tracking Bug
|
// TODO(b/254512734): Tracking Bug
|
||||||
val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag(700, "ongoing_call_status_bar_chip")
|
val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag(700, "ongoing_call_status_bar_chip")
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ public abstract class StatusBarViewModule {
|
|||||||
BroadcastDispatcher broadcastDispatcher,
|
BroadcastDispatcher broadcastDispatcher,
|
||||||
@Main Handler mainHandler,
|
@Main Handler mainHandler,
|
||||||
ContentResolver contentResolver,
|
ContentResolver contentResolver,
|
||||||
|
FeatureFlags featureFlags,
|
||||||
BatteryController batteryController
|
BatteryController batteryController
|
||||||
) {
|
) {
|
||||||
return new BatteryMeterViewController(
|
return new BatteryMeterViewController(
|
||||||
@@ -235,6 +236,7 @@ public abstract class StatusBarViewModule {
|
|||||||
broadcastDispatcher,
|
broadcastDispatcher,
|
||||||
mainHandler,
|
mainHandler,
|
||||||
contentResolver,
|
contentResolver,
|
||||||
|
featureFlags,
|
||||||
batteryController);
|
batteryController);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,6 +155,9 @@ public interface BatteryController extends DemoMode,
|
|||||||
|
|
||||||
default void onWirelessChargingChanged(boolean isWirlessCharging) {
|
default void onWirelessChargingChanged(boolean isWirlessCharging) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void onIsOverheatedChanged(boolean isOverheated) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.policy;
|
package com.android.systemui.statusbar.policy;
|
||||||
|
|
||||||
|
import static android.os.BatteryManager.BATTERY_HEALTH_OVERHEAT;
|
||||||
|
import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
|
||||||
|
import static android.os.BatteryManager.EXTRA_HEALTH;
|
||||||
import static android.os.BatteryManager.EXTRA_PRESENT;
|
import static android.os.BatteryManager.EXTRA_PRESENT;
|
||||||
|
|
||||||
import android.annotation.WorkerThread;
|
import android.annotation.WorkerThread;
|
||||||
@@ -87,6 +90,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
protected boolean mPowerSave;
|
protected boolean mPowerSave;
|
||||||
private boolean mAodPowerSave;
|
private boolean mAodPowerSave;
|
||||||
private boolean mWirelessCharging;
|
private boolean mWirelessCharging;
|
||||||
|
private boolean mIsOverheated = false;
|
||||||
private boolean mTestMode = false;
|
private boolean mTestMode = false;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean mHasReceivedBattery = false;
|
boolean mHasReceivedBattery = false;
|
||||||
@@ -184,6 +188,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
cb.onPowerSaveChanged(mPowerSave);
|
cb.onPowerSaveChanged(mPowerSave);
|
||||||
cb.onBatteryUnknownStateChanged(mStateUnknown);
|
cb.onBatteryUnknownStateChanged(mStateUnknown);
|
||||||
cb.onWirelessChargingChanged(mWirelessCharging);
|
cb.onWirelessChargingChanged(mWirelessCharging);
|
||||||
|
cb.onIsOverheatedChanged(mIsOverheated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -222,6 +227,13 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
fireBatteryUnknownStateChanged();
|
fireBatteryUnknownStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int batteryHealth = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
|
||||||
|
boolean isOverheated = batteryHealth == BATTERY_HEALTH_OVERHEAT;
|
||||||
|
if (isOverheated != mIsOverheated) {
|
||||||
|
mIsOverheated = isOverheated;
|
||||||
|
fireIsOverheatedChanged();
|
||||||
|
}
|
||||||
|
|
||||||
fireBatteryLevelChanged();
|
fireBatteryLevelChanged();
|
||||||
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
|
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
|
||||||
updatePowerSave();
|
updatePowerSave();
|
||||||
@@ -292,6 +304,10 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
return mPluggedChargingSource == BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
return mPluggedChargingSource == BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOverheated() {
|
||||||
|
return mIsOverheated;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getEstimatedTimeRemainingString(EstimateFetchCompletion completion) {
|
public void getEstimatedTimeRemainingString(EstimateFetchCompletion completion) {
|
||||||
// Need to fetch or refresh the estimate, but it may involve binder calls so offload the
|
// Need to fetch or refresh the estimate, but it may involve binder calls so offload the
|
||||||
@@ -402,6 +418,15 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fireIsOverheatedChanged() {
|
||||||
|
synchronized (mChangeCallbacks) {
|
||||||
|
final int n = mChangeCallbacks.size();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
mChangeCallbacks.get(i).onIsOverheatedChanged(mIsOverheated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispatchDemoCommand(String command, Bundle args) {
|
public void dispatchDemoCommand(String command, Bundle args) {
|
||||||
if (!mDemoModeController.isInDemoMode()) {
|
if (!mDemoModeController.isInDemoMode()) {
|
||||||
@@ -412,6 +437,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
String plugged = args.getString("plugged");
|
String plugged = args.getString("plugged");
|
||||||
String powerSave = args.getString("powersave");
|
String powerSave = args.getString("powersave");
|
||||||
String present = args.getString("present");
|
String present = args.getString("present");
|
||||||
|
String overheated = args.getString("overheated");
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
|
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
|
||||||
}
|
}
|
||||||
@@ -426,6 +452,10 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
mStateUnknown = !present.equals("true");
|
mStateUnknown = !present.equals("true");
|
||||||
fireBatteryUnknownStateChanged();
|
fireBatteryUnknownStateChanged();
|
||||||
}
|
}
|
||||||
|
if (overheated != null) {
|
||||||
|
mIsOverheated = overheated.equals("true");
|
||||||
|
fireIsOverheatedChanged();
|
||||||
|
}
|
||||||
fireBatteryLevelChanged();
|
fireBatteryLevelChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.battery
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT_WITH_SHIELD
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH_WITH_SHIELD
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
class AccessorizedBatteryDrawableTest : SysuiTestCase() {
|
||||||
|
@Test
|
||||||
|
fun intrinsicSize_shieldFalse_isBatterySize() {
|
||||||
|
val drawable = AccessorizedBatteryDrawable(context, frameColor = 0)
|
||||||
|
drawable.displayShield = false
|
||||||
|
|
||||||
|
val density = context.resources.displayMetrics.density
|
||||||
|
assertThat(drawable.intrinsicHeight).isEqualTo((BATTERY_HEIGHT * density).toInt())
|
||||||
|
assertThat(drawable.intrinsicWidth).isEqualTo((BATTERY_WIDTH * density).toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun intrinsicSize_shieldTrue_isBatteryPlusShieldSize() {
|
||||||
|
val drawable = AccessorizedBatteryDrawable(context, frameColor = 0)
|
||||||
|
drawable.displayShield = true
|
||||||
|
|
||||||
|
val density = context.resources.displayMetrics.density
|
||||||
|
assertThat(drawable.intrinsicHeight)
|
||||||
|
.isEqualTo((BATTERY_HEIGHT_WITH_SHIELD * density).toInt())
|
||||||
|
assertThat(drawable.intrinsicWidth).isEqualTo((BATTERY_WIDTH_WITH_SHIELD * density).toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(b/255625888): Screenshot tests for this drawable would be amazing!
|
||||||
|
}
|
||||||
@@ -35,6 +35,8 @@ import androidx.test.filters.SmallTest;
|
|||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
|
import com.android.systemui.flags.FakeFeatureFlags;
|
||||||
|
import com.android.systemui.flags.Flags;
|
||||||
import com.android.systemui.statusbar.policy.BatteryController;
|
import com.android.systemui.statusbar.policy.BatteryController;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.tuner.TunerService;
|
import com.android.systemui.tuner.TunerService;
|
||||||
@@ -59,6 +61,7 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
|
|||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
@Mock
|
@Mock
|
||||||
private ContentResolver mContentResolver;
|
private ContentResolver mContentResolver;
|
||||||
|
private FakeFeatureFlags mFeatureFlags;
|
||||||
@Mock
|
@Mock
|
||||||
private BatteryController mBatteryController;
|
private BatteryController mBatteryController;
|
||||||
|
|
||||||
@@ -71,19 +74,13 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
|
|||||||
when(mBatteryMeterView.getContext()).thenReturn(mContext);
|
when(mBatteryMeterView.getContext()).thenReturn(mContext);
|
||||||
when(mBatteryMeterView.getResources()).thenReturn(mContext.getResources());
|
when(mBatteryMeterView.getResources()).thenReturn(mContext.getResources());
|
||||||
|
|
||||||
mController = new BatteryMeterViewController(
|
mFeatureFlags = new FakeFeatureFlags();
|
||||||
mBatteryMeterView,
|
mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, false);
|
||||||
mConfigurationController,
|
|
||||||
mTunerService,
|
|
||||||
mBroadcastDispatcher,
|
|
||||||
mHandler,
|
|
||||||
mContentResolver,
|
|
||||||
mBatteryController
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onViewAttached_callbacksRegistered() {
|
public void onViewAttached_callbacksRegistered() {
|
||||||
|
initController();
|
||||||
mController.onViewAttached();
|
mController.onViewAttached();
|
||||||
|
|
||||||
verify(mConfigurationController).addCallback(any());
|
verify(mConfigurationController).addCallback(any());
|
||||||
@@ -101,6 +98,7 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onViewDetached_callbacksUnregistered() {
|
public void onViewDetached_callbacksUnregistered() {
|
||||||
|
initController();
|
||||||
// Set everything up first.
|
// Set everything up first.
|
||||||
mController.onViewAttached();
|
mController.onViewAttached();
|
||||||
|
|
||||||
@@ -114,6 +112,7 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ignoreTunerUpdates_afterOnViewAttached_callbackUnregistered() {
|
public void ignoreTunerUpdates_afterOnViewAttached_callbackUnregistered() {
|
||||||
|
initController();
|
||||||
// Start out receiving tuner updates
|
// Start out receiving tuner updates
|
||||||
mController.onViewAttached();
|
mController.onViewAttached();
|
||||||
|
|
||||||
@@ -124,10 +123,43 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ignoreTunerUpdates_beforeOnViewAttached_callbackNeverRegistered() {
|
public void ignoreTunerUpdates_beforeOnViewAttached_callbackNeverRegistered() {
|
||||||
|
initController();
|
||||||
|
|
||||||
mController.ignoreTunerUpdates();
|
mController.ignoreTunerUpdates();
|
||||||
|
|
||||||
mController.onViewAttached();
|
mController.onViewAttached();
|
||||||
|
|
||||||
verify(mTunerService, never()).addTunable(any(), any());
|
verify(mTunerService, never()).addTunable(any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shieldFlagDisabled_viewNotified() {
|
||||||
|
mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, false);
|
||||||
|
|
||||||
|
initController();
|
||||||
|
|
||||||
|
verify(mBatteryMeterView).setDisplayShieldEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shieldFlagEnabled_viewNotified() {
|
||||||
|
mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, true);
|
||||||
|
|
||||||
|
initController();
|
||||||
|
|
||||||
|
verify(mBatteryMeterView).setDisplayShieldEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initController() {
|
||||||
|
mController = new BatteryMeterViewController(
|
||||||
|
mBatteryMeterView,
|
||||||
|
mConfigurationController,
|
||||||
|
mTunerService,
|
||||||
|
mBroadcastDispatcher,
|
||||||
|
mHandler,
|
||||||
|
mContentResolver,
|
||||||
|
mFeatureFlags,
|
||||||
|
mBatteryController
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ package com.android.systemui.battery
|
|||||||
|
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper.RunWithLooper
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
|
import android.widget.ImageView
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.battery.BatteryMeterView.BatteryEstimateFetcher
|
import com.android.systemui.battery.BatteryMeterView.BatteryEstimateFetcher
|
||||||
import com.android.systemui.statusbar.policy.BatteryController.EstimateFetchCompletion
|
import com.android.systemui.statusbar.policy.BatteryController.EstimateFetchCompletion
|
||||||
@@ -58,6 +60,182 @@ class BatteryMeterViewTest : SysuiTestCase() {
|
|||||||
// No assert needed
|
// No assert needed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun contentDescription_unknown() {
|
||||||
|
mBatteryMeterView.onBatteryUnknownStateChanged(true)
|
||||||
|
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(R.string.accessibility_battery_unknown)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun contentDescription_estimate() {
|
||||||
|
mBatteryMeterView.onBatteryLevelChanged(15, false)
|
||||||
|
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
||||||
|
mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
|
||||||
|
|
||||||
|
mBatteryMeterView.updatePercentText()
|
||||||
|
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(
|
||||||
|
R.string.accessibility_battery_level_with_estimate, 15, ESTIMATE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun contentDescription_estimateAndOverheated() {
|
||||||
|
mBatteryMeterView.onBatteryLevelChanged(17, false)
|
||||||
|
mBatteryMeterView.onIsOverheatedChanged(true)
|
||||||
|
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
||||||
|
mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
|
||||||
|
|
||||||
|
mBatteryMeterView.updatePercentText()
|
||||||
|
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(
|
||||||
|
R.string.accessibility_battery_level_charging_paused_with_estimate,
|
||||||
|
17,
|
||||||
|
ESTIMATE,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun contentDescription_overheated() {
|
||||||
|
mBatteryMeterView.onBatteryLevelChanged(90, false)
|
||||||
|
mBatteryMeterView.onIsOverheatedChanged(true)
|
||||||
|
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(R.string.accessibility_battery_level_charging_paused, 90)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun contentDescription_charging() {
|
||||||
|
mBatteryMeterView.onBatteryLevelChanged(45, true)
|
||||||
|
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(R.string.accessibility_battery_level_charging, 45)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun contentDescription_notCharging() {
|
||||||
|
mBatteryMeterView.onBatteryLevelChanged(45, false)
|
||||||
|
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(R.string.accessibility_battery_level, 45)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun changesFromEstimateToPercent_textAndContentDescriptionChanges() {
|
||||||
|
mBatteryMeterView.onBatteryLevelChanged(15, false)
|
||||||
|
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
||||||
|
mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
|
||||||
|
|
||||||
|
mBatteryMeterView.updatePercentText()
|
||||||
|
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(
|
||||||
|
R.string.accessibility_battery_level_with_estimate, 15, ESTIMATE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Update the show mode from estimate to percent
|
||||||
|
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON)
|
||||||
|
|
||||||
|
assertThat(mBatteryMeterView.batteryPercentViewText).isEqualTo("15%")
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(R.string.accessibility_battery_level, 15)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun contentDescription_manyUpdates_alwaysUpdated() {
|
||||||
|
// Overheated
|
||||||
|
mBatteryMeterView.onBatteryLevelChanged(90, false)
|
||||||
|
mBatteryMeterView.onIsOverheatedChanged(true)
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(R.string.accessibility_battery_level_charging_paused, 90)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Overheated & estimate
|
||||||
|
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
|
||||||
|
mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
|
||||||
|
mBatteryMeterView.updatePercentText()
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(
|
||||||
|
R.string.accessibility_battery_level_charging_paused_with_estimate,
|
||||||
|
90,
|
||||||
|
ESTIMATE,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Just estimate
|
||||||
|
mBatteryMeterView.onIsOverheatedChanged(false)
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(
|
||||||
|
R.string.accessibility_battery_level_with_estimate,
|
||||||
|
90,
|
||||||
|
ESTIMATE,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Just percent
|
||||||
|
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON)
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(R.string.accessibility_battery_level, 90)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Charging
|
||||||
|
mBatteryMeterView.onBatteryLevelChanged(90, true)
|
||||||
|
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
|
||||||
|
context.getString(R.string.accessibility_battery_level_charging, 90)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isOverheatedChanged_true_drawableGetsTrue() {
|
||||||
|
mBatteryMeterView.setDisplayShieldEnabled(true)
|
||||||
|
val drawable = getBatteryDrawable()
|
||||||
|
|
||||||
|
mBatteryMeterView.onIsOverheatedChanged(true)
|
||||||
|
|
||||||
|
assertThat(drawable.displayShield).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isOverheatedChanged_false_drawableGetsFalse() {
|
||||||
|
mBatteryMeterView.setDisplayShieldEnabled(true)
|
||||||
|
val drawable = getBatteryDrawable()
|
||||||
|
|
||||||
|
// Start as true
|
||||||
|
mBatteryMeterView.onIsOverheatedChanged(true)
|
||||||
|
|
||||||
|
// Update to false
|
||||||
|
mBatteryMeterView.onIsOverheatedChanged(false)
|
||||||
|
|
||||||
|
assertThat(drawable.displayShield).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isOverheatedChanged_true_featureflagOff_drawableGetsFalse() {
|
||||||
|
mBatteryMeterView.setDisplayShieldEnabled(false)
|
||||||
|
val drawable = getBatteryDrawable()
|
||||||
|
|
||||||
|
mBatteryMeterView.onIsOverheatedChanged(true)
|
||||||
|
|
||||||
|
assertThat(drawable.displayShield).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBatteryDrawable(): AccessorizedBatteryDrawable {
|
||||||
|
return (mBatteryMeterView.getChildAt(0) as ImageView)
|
||||||
|
.drawable as AccessorizedBatteryDrawable
|
||||||
|
}
|
||||||
|
|
||||||
private class Fetcher : BatteryEstimateFetcher {
|
private class Fetcher : BatteryEstimateFetcher {
|
||||||
override fun fetchBatteryTimeRemainingEstimate(
|
override fun fetchBatteryTimeRemainingEstimate(
|
||||||
completion: EstimateFetchCompletion) {
|
completion: EstimateFetchCompletion) {
|
||||||
@@ -68,4 +246,4 @@ class BatteryMeterViewTest : SysuiTestCase() {
|
|||||||
private companion object {
|
private companion object {
|
||||||
const val ESTIMATE = "2 hours 2 minutes"
|
const val ESTIMATE = "2 hours 2 minutes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.battery
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_HEIGHT_WITH_SHIELD
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH
|
||||||
|
import com.android.systemui.battery.BatterySpecs.BATTERY_WIDTH_WITH_SHIELD
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
class BatterySpecsTest : SysuiTestCase() {
|
||||||
|
@Test
|
||||||
|
fun getFullBatteryHeight_shieldFalse_returnsMainHeight() {
|
||||||
|
val fullHeight = BatterySpecs.getFullBatteryHeight(56f, displayShield = false)
|
||||||
|
|
||||||
|
assertThat(fullHeight).isEqualTo(56f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getFullBatteryHeight_shieldTrue_returnsMainHeightPlusShield() {
|
||||||
|
val mainHeight = BATTERY_HEIGHT * 5
|
||||||
|
val fullHeight = BatterySpecs.getFullBatteryHeight(mainHeight, displayShield = true)
|
||||||
|
|
||||||
|
// Since the main battery was scaled 5x, the output height should also be scaled 5x
|
||||||
|
val expectedFullHeight = BATTERY_HEIGHT_WITH_SHIELD * 5
|
||||||
|
|
||||||
|
assertThat(fullHeight).isWithin(.0001f).of(expectedFullHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getFullBatteryWidth_shieldFalse_returnsMainWidth() {
|
||||||
|
val fullWidth = BatterySpecs.getFullBatteryWidth(33f, displayShield = false)
|
||||||
|
|
||||||
|
assertThat(fullWidth).isEqualTo(33f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getFullBatteryWidth_shieldTrue_returnsMainWidthPlusShield() {
|
||||||
|
val mainWidth = BATTERY_WIDTH * 3.3f
|
||||||
|
|
||||||
|
val fullWidth = BatterySpecs.getFullBatteryWidth(mainWidth, displayShield = true)
|
||||||
|
|
||||||
|
// Since the main battery was scaled 3.3x, the output width should also be scaled 5x
|
||||||
|
val expectedFullWidth = BATTERY_WIDTH_WITH_SHIELD * 3.3f
|
||||||
|
assertThat(fullWidth).isWithin(.0001f).of(expectedFullWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getMainBatteryHeight_shieldFalse_returnsFullHeight() {
|
||||||
|
val mainHeight = BatterySpecs.getMainBatteryHeight(89f, displayShield = false)
|
||||||
|
|
||||||
|
assertThat(mainHeight).isEqualTo(89f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getMainBatteryHeight_shieldTrue_returnsNotFullHeight() {
|
||||||
|
val fullHeight = BATTERY_HEIGHT_WITH_SHIELD * 7.7f
|
||||||
|
|
||||||
|
val mainHeight = BatterySpecs.getMainBatteryHeight(fullHeight, displayShield = true)
|
||||||
|
|
||||||
|
// Since the full height was scaled 7.7x, the main height should also be scaled 7.7x.
|
||||||
|
val expectedHeight = BATTERY_HEIGHT * 7.7f
|
||||||
|
assertThat(mainHeight).isWithin(.0001f).of(expectedHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getMainBatteryWidth_shieldFalse_returnsFullWidth() {
|
||||||
|
val mainWidth = BatterySpecs.getMainBatteryWidth(2345f, displayShield = false)
|
||||||
|
|
||||||
|
assertThat(mainWidth).isEqualTo(2345f)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getMainBatteryWidth_shieldTrue_returnsNotFullWidth() {
|
||||||
|
val fullWidth = BATTERY_WIDTH_WITH_SHIELD * 0.6f
|
||||||
|
|
||||||
|
val mainWidth = BatterySpecs.getMainBatteryWidth(fullWidth, displayShield = true)
|
||||||
|
|
||||||
|
// Since the full width was scaled 0.6x, the main height should also be scaled 0.6x.
|
||||||
|
val expectedWidth = BATTERY_WIDTH * 0.6f
|
||||||
|
assertThat(mainWidth).isWithin(.0001f).of(expectedWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -221,4 +221,33 @@ public class BatteryControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
Assert.assertFalse(mBatteryController.isChargingSourceDock());
|
Assert.assertFalse(mBatteryController.isChargingSourceDock());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void batteryStateChanged_healthNotOverheated_outputsFalse() {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
intent.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_GOOD);
|
||||||
|
|
||||||
|
mBatteryController.onReceive(getContext(), intent);
|
||||||
|
|
||||||
|
Assert.assertFalse(mBatteryController.isOverheated());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void batteryStateChanged_healthOverheated_outputsTrue() {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
intent.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT);
|
||||||
|
|
||||||
|
mBatteryController.onReceive(getContext(), intent);
|
||||||
|
|
||||||
|
Assert.assertTrue(mBatteryController.isOverheated());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void batteryStateChanged_noHealthGiven_outputsFalse() {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
|
||||||
|
mBatteryController.onReceive(getContext(), intent);
|
||||||
|
|
||||||
|
Assert.assertFalse(mBatteryController.isOverheated());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user