Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5f650fe authored by Evan Laird's avatar Evan Laird Committed by Android (Google) Code Review
Browse files

Merge changes I581ec376,Ic8b15286,I5ad19ac9 into main

* changes:
  [Battery] RTL support
  [Battery] Define layout rects as insets
  [Sb] Properly inflate the estimate view
parents 347dede4 0daea65b
Loading
Loading
Loading
Loading
+34 −26
Original line number Diff line number Diff line
@@ -345,11 +345,25 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
        }
    }

    private TextView loadPercentView() {
    private TextView inflatePercentView() {
        return (TextView) LayoutInflater.from(getContext())
                .inflate(R.layout.battery_percentage_view, null);
    }

    private void addPercentView(TextView inflatedPercentView) {
        mBatteryPercentView = inflatedPercentView;

        if (mPercentageStyleId != 0) { // Only set if specified as attribute
            mBatteryPercentView.setTextAppearance(mPercentageStyleId);
        }
        float fontHeight = mBatteryPercentView.getPaint().getFontMetricsInt(null);
        mBatteryPercentView.setLineHeight(TypedValue.COMPLEX_UNIT_PX, fontHeight);
        if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
        addView(mBatteryPercentView, new LayoutParams(
                LayoutParams.WRAP_CONTENT,
                (int) Math.ceil(fontHeight)));
    }

    /**
     * Updates percent view by removing old one and reinflating if necessary
     */
@@ -388,7 +402,9 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
            mBatteryEstimateFetcher.fetchBatteryTimeRemainingEstimate(
                    (String estimate) -> {
                        if (mBatteryPercentView == null) {
                            mBatteryPercentView = loadPercentView();
                            // Similar to the legacy behavior, inflate and add the view. We will
                            // only use it for the estimate text
                            addPercentView(inflatePercentView());
                        }
                        if (estimate != null && mShowPercentMode == MODE_ESTIMATE) {
                            mEstimateText = estimate;
@@ -401,6 +417,10 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
                        }
                    });
        } else {
            if (mBatteryPercentView != null) {
                mEstimateText = null;
                mBatteryPercentView.setText(null);
            }
            updateContentDescription();
        }
    }
@@ -485,21 +505,18 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
            return;
        }

        if (mUnifiedBattery == null) {
            return;
        }
        if (!mShowPercentAvailable || mUnifiedBattery == null) return;

        boolean shouldShow = mShowPercentMode == MODE_ON || mShowPercentMode == MODE_ESTIMATE;
        if (!mBatteryStateUnknown && !shouldShow && (mShowPercentMode != MODE_OFF)) {
            // Slow case: fall back to the system setting
            // TODO(b/140051051)
        final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
            shouldShow = 0 != whitelistIpcs(() -> Settings.System
                    .getIntForUser(getContext().getContentResolver(),
                    SHOW_BATTERY_PERCENT, getContext().getResources().getBoolean(
                    com.android.internal.R.bool.config_defaultBatteryPercentageSetting)
                    ? 1 : 0, UserHandle.USER_CURRENT));

        boolean shouldShow =
                (mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
                        || mShowPercentMode == MODE_ON;
        shouldShow = shouldShow && !mBatteryStateUnknown;
        }

        setBatteryDrawableState(
                new BatteryDrawableState(
@@ -534,17 +551,8 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {

        if (shouldShow) {
            if (!showing) {
                mBatteryPercentView = loadPercentView();
                if (mPercentageStyleId != 0) { // Only set if specified as attribute
                    mBatteryPercentView.setTextAppearance(mPercentageStyleId);
                }
                float fontHeight = mBatteryPercentView.getPaint().getFontMetricsInt(null);
                mBatteryPercentView.setLineHeight(TypedValue.COMPLEX_UNIT_PX, fontHeight);
                if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
                addPercentView(inflatePercentView());
                updatePercentText();
                addView(mBatteryPercentView, new LayoutParams(
                        LayoutParams.WRAP_CONTENT,
                        (int) Math.ceil(fontHeight)));
            }
        } else {
            if (showing) {
+4 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.graphics.drawable.DrawableWrapper
import android.view.Gravity
import kotlin.math.ceil
import kotlin.math.min
import kotlin.math.roundToInt

@@ -36,7 +37,7 @@ import kotlin.math.roundToInt
 */
@Suppress("RtlHardcoded")
class BatteryAttributionDrawable(dr: Drawable?) : DrawableWrapper(dr) {
    /** One of [CENTER, LEFT]. Note that RTL is handled in the parent */
    /** One of [CENTER, LEFT]. Note that number text does not RTL. */
    var gravity = Gravity.CENTER
        set(value) {
            field = value
@@ -67,8 +68,8 @@ class BatteryAttributionDrawable(dr: Drawable?) : DrawableWrapper(dr) {
            dr.setBounds(
                bounds.left,
                bounds.top,
                (bounds.left + dw).roundToInt(),
                (bounds.top + dh).roundToInt()
                ceil(bounds.left + dw).toInt(),
                ceil(bounds.top + dh).toInt()
            )
        }
    }
+6 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.graphics.PixelFormat
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.view.View
import com.android.systemui.battery.unified.BatteryLayersDrawable.Companion.Metrics
import kotlin.math.floor
import kotlin.math.roundToInt
@@ -103,6 +104,11 @@ class BatteryFillDrawable(private val framePath: Path) : Drawable() {
        // saveLayer is needed here so we don't clip the other layers of our drawable
        canvas.saveLayer(null, null)

        // Fill from the opposite direction in rtl mode
        if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
            canvas.scale(-1f, 1f, bounds.width() / 2f, bounds.height() / 2f)
        }

        // We need to use 3 draw commands:
        // 1. Clip to the current level
        // 2. Clip anything outside of the path
+93 −30
Original line number Diff line number Diff line
@@ -26,7 +26,10 @@ import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.util.PathParser
import android.view.Gravity
import android.view.View
import com.android.systemui.res.R
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.roundToInt

/**
@@ -69,8 +72,11 @@ class BatteryLayersDrawable(
) : LayerDrawable(arrayOf(frameBg, frame, fill, textOnly, spaceSharingText, attribution)) {

    private val scaleMatrix = Matrix().also { it.setScale(1f, 1f) }
    private val scaledAttrFullCanvas = RectF(Metrics.AttrFullCanvas)
    private val scaledAttrRightCanvas = RectF(Metrics.AttrRightCanvas)

    private val attrFullCanvas = RectF()
    private val attrRightCanvas = RectF()
    private val scaledAttrFullCanvas = RectF()
    private val scaledAttrRightCanvas = RectF()

    var batteryState = batteryState
        set(value) {
@@ -88,6 +94,12 @@ class BatteryLayersDrawable(
            updateColors(batteryState.showErrorState, value)
        }

    init {
        isAutoMirrored = true
        // Initialize the canvas rects since they are not static
        setAttrRects(layoutDirection == View.LAYOUT_DIRECTION_RTL)
    }

    private fun handleUpdateState(old: BatteryDrawableState, new: BatteryDrawableState) {
        if (new.showErrorState != old.showErrorState) {
            updateColors(new.showErrorState, colors)
@@ -144,9 +156,42 @@ class BatteryLayersDrawable(
            bounds.height() / Metrics.ViewportHeight
        )

        // Scale the attribution bounds
        scaleMatrix.mapRect(scaledAttrFullCanvas, Metrics.AttrFullCanvas)
        scaleMatrix.mapRect(scaledAttrRightCanvas, Metrics.AttrRightCanvas)
        scaleAttributionBounds()
    }

    override fun onLayoutDirectionChanged(layoutDirection: Int): Boolean {
        setAttrRects(layoutDirection == View.LAYOUT_DIRECTION_RTL)
        scaleAttributionBounds()

        return super.onLayoutDirectionChanged(layoutDirection)
    }

    private fun setAttrRects(rtl: Boolean) {
        // Local refs make the math easier to parse
        val full = Metrics.AttrFullCanvasInsets
        val side = Metrics.AttrRightCanvasInsets
        val sideRtl = Metrics.AttrRightCanvasInsetsRtl
        val vh = Metrics.ViewportHeight
        val vw = Metrics.ViewportWidth

        attrFullCanvas.set(
            if (rtl) full.right else full.left,
            full.top,
            vw - if (rtl) full.left else full.right,
            vh - full.bottom,
        )
        attrRightCanvas.set(
            if (rtl) sideRtl.left else side.left,
            side.top,
            vw - (if (rtl) sideRtl.right else side.right),
            vh - side.bottom,
        )
    }

    /** If bounds (i.e., scale), or RTL properties change, we have to recalculate the attr bounds */
    private fun scaleAttributionBounds() {
        scaleMatrix.mapRect(scaledAttrFullCanvas, attrFullCanvas)
        scaleMatrix.mapRect(scaledAttrRightCanvas, attrRightCanvas)
    }

    override fun draw(canvas: Canvas) {
@@ -163,13 +208,14 @@ class BatteryLayersDrawable(
        if (batteryState.showPercent && batteryState.attribution != null) {
            // 4a. percent & attribution. Implies space-sharing

            // Configure the attribute to draw in a smaller bounding box and align left
            // Configure the attribute to draw in a smaller bounding box and align left and use
            // floor/ceil math to make sure we get every available pixel
            attribution.gravity = Gravity.LEFT
            attribution.setBounds(
                scaledAttrRightCanvas.left.roundToInt(),
                scaledAttrRightCanvas.top.roundToInt(),
                scaledAttrRightCanvas.right.roundToInt(),
                scaledAttrRightCanvas.bottom.roundToInt(),
                floor(scaledAttrRightCanvas.left).toInt(),
                floor(scaledAttrRightCanvas.top).toInt(),
                ceil(scaledAttrRightCanvas.right).toInt(),
                ceil(scaledAttrRightCanvas.bottom).toInt(),
            )
            attribution.draw(canvas)

@@ -196,16 +242,44 @@ class BatteryLayersDrawable(
     */
    override fun setAlpha(alpha: Int) {}

    /**
     * Interface that describes relevant top-level metrics for the proper rendering of this icon.
     * The overall canvas is defined as ViewportWidth x ViewportHeight, which is hard coded to 24x14
     * points.
     *
     * The attr canvas insets are rect inset definitions. That is, they are defined as l,t,r,b
     * points from the nearest edge. Note that for RTL, we don't actually flip the text since
     * numbers do not reverse for RTL locales.
     */
    interface M {
        val ViewportWidth: Float
        val ViewportHeight: Float

        // Bounds, oriented in the above viewport, where we will fit-center and center-align
        // an attribution that is the sole foreground element
        val AttrFullCanvas: RectF
        // Bounds, oriented in the above viewport, where we will fit-center and left-align
        // an attribution that is sharing space with the percent text of the drawable
        val AttrRightCanvas: RectF
        /**
         * Insets, oriented in the above viewport in LTR, that define the full canvas for a single
         * foreground element. The element will be fit-center and center-aligned on this canvas
         *
         * 18x8 point size
         */
        val AttrFullCanvasInsets: RectF

        /**
         * Insets, oriented in the above viewport in LTR, that define the partial canvas for a
         * foreground element that shares space with the percent text. The element will be
         * fit-center and left-aligned on this canvas.
         *
         * 6x6 point size
         */
        val AttrRightCanvasInsets: RectF

        /**
         * Insets, oriented in the above viewport in RTL, that define the partial canvas for a
         * foreground element that shares space with the percent text. The element will be
         * fit-center and left-aligned on this canvas.
         *
         * 6x6 point size
         */
        val AttrRightCanvasInsetsRtl: RectF
    }

    companion object {
@@ -220,20 +294,9 @@ class BatteryLayersDrawable(
                override val ViewportWidth: Float = 24f
                override val ViewportHeight: Float = 14f

                /**
                 * Bounds, oriented in the above viewport, where we will fit-center and center-align
                 * an attribution that is the sole foreground element
                 *
                 * 18x8 point size
                 */
                override val AttrFullCanvas: RectF = RectF(4f, 3f, 22f, 11f)
                /**
                 * Bounds, oriented in the above viewport, where we will fit-center and left-align
                 * an attribution that is sharing space with the percent text of the drawable
                 *
                 * 6x6 point size
                 */
                override val AttrRightCanvas: RectF = RectF(16f, 4f, 22f, 10f)
                override val AttrFullCanvasInsets = RectF(4f, 3f, 2f, 3f)
                override val AttrRightCanvasInsets = RectF(16f, 4f, 2f, 4f)
                override val AttrRightCanvasInsetsRtl = RectF(14f, 4f, 4f, 4f)
            }

        /**
+4 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.graphics.PixelFormat
import android.graphics.Rect
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.view.View
import com.android.systemui.battery.unified.BatteryLayersDrawable.Companion.Metrics

/**
@@ -71,6 +72,7 @@ class BatteryPercentTextOnlyDrawable(font: Typeface) : Drawable() {
    }

    override fun draw(canvas: Canvas) {
        val rtl = layoutDirection == View.LAYOUT_DIRECTION_RTL
        val totalAvailableHeight = CanvasHeight * vScale

        // Distribute the vertical whitespace around the text. This is a simplified version of
@@ -81,11 +83,12 @@ class BatteryPercentTextOnlyDrawable(font: Typeface) : Drawable() {
        val totalAvailableWidth = CanvasWidth * hScale
        val textWidth = textPaint.measureText(percentText)
        val offsetX = (totalAvailableWidth - textWidth) / 2
        val startOffset = if (rtl) ViewportInsetRight else ViewportInsetLeft

        // Draw the text centered in the available area
        canvas.drawText(
            percentText,
            (ViewportInsetLeft * hScale) + offsetX,
            (startOffset * hScale) + offsetX,
            (ViewportInsetTop * vScale) + offsetY,
            textPaint
        )
Loading