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

Commit 22de74f8 authored by Bruno Martins's avatar Bruno Martins
Browse files

SystemUI: Bring back good ol' circle battery style

Drawable java implementation inspired by Ian and Danesh's work on
the old forward ports:

Author: Ian Roy <ian.t.roy@gmail.com>
Co-author: Danesh M <daneshm90@gmail.com>
Date:   Tue Oct 27 18:19:02 2015 -0700

    BatteryMeterDrawable: add battery styles

    Change-Id: Icfc14d989eebde9014538291c24aa76d328df234

Author: camcory <camcory1@gmail.com>
Date:   Mon Aug 13 14:03:14 2018 -0400

    Add the powersave hint to the circle battery

    Change-Id: I00443130c758397a8a288b5f23ddfd824d778e38

Partially squashed with:

Author: Hendrik Hagendorn <git@finnq.de>
Date:   Sun Jan 15 08:47:10 2017 +0100

    SystemUI: Refactor battery icon options

    * Use the icon blacklist for hiding
    * Combine options for hiding status bar icons in system tuner settings

    Change-Id: I3924bae6c2f65015ed9b6e3e4038a1fc36951867

Change-Id: I5c1cfec6d08deb6f4205356dd2bbc03e04d0ee3a
parent af472956
Loading
Loading
Loading
Loading
+117 −6
Original line number Diff line number Diff line
@@ -44,6 +44,10 @@ public class BatteryMeterDrawableBase extends Drawable {
    public static final String TAG = BatteryMeterDrawableBase.class.getSimpleName();
    private static final float RADIUS_RATIO = 1.0f / 17f;

    public static final int BATTERY_STYLE_PORTRAIT = 0;
    public static final int BATTERY_STYLE_CIRCLE = 1;
    public static final int BATTERY_STYLE_TEXT = 2;

    protected final Context mContext;
    protected final Paint mFramePaint;
    protected final Paint mBatteryPaint;
@@ -55,6 +59,7 @@ public class BatteryMeterDrawableBase extends Drawable {
    protected float mButtonHeightFraction;

    private int mLevel = -1;
    private int mMeterStyle;
    private boolean mCharging;
    private boolean mPowerSaveEnabled;
    protected boolean mPowerSaveAsColorError = true;
@@ -67,8 +72,8 @@ public class BatteryMeterDrawableBase extends Drawable {
    private static final float BOLT_LEVEL_THRESHOLD = 0.3f;  // opaque bolt below this fraction

    private final int[] mColors;
    private final int mIntrinsicWidth;
    private final int mIntrinsicHeight;
    private int mIntrinsicWidth;
    private int mIntrinsicHeight;

    private float mSubpixelSmoothingLeft;
    private float mSubpixelSmoothingRight;
@@ -97,7 +102,13 @@ public class BatteryMeterDrawableBase extends Drawable {
    private final Path mTextPath = new Path();

    public BatteryMeterDrawableBase(Context context, int frameColor) {
        // Portrait is the default drawable style
        this(context, frameColor, BATTERY_STYLE_PORTRAIT);
    }

    public BatteryMeterDrawableBase(Context context, int frameColor, int style) {
        mContext = context;
        mMeterStyle = style;
        final Resources res = context.getResources();
        TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
        TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
@@ -128,13 +139,9 @@ public class BatteryMeterDrawableBase extends Drawable {
        mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mFramePaint.setColor(frameColor);
        mFramePaint.setDither(true);
        mFramePaint.setStrokeWidth(0);
        mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBatteryPaint.setDither(true);
        mBatteryPaint.setStrokeWidth(0);
        mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
@@ -211,6 +218,12 @@ public class BatteryMeterDrawableBase extends Drawable {
        mPowerSaveAsColorError = asError;
    }

    public void setMeterStyle(int style) {
        mMeterStyle = style;
        updateSize();
        postInvalidate();
    }

    // an approximation of View.postInvalidate()
    protected void postInvalidate() {
        unscheduleSelf(this::invalidateSelf);
@@ -245,6 +258,11 @@ public class BatteryMeterDrawableBase extends Drawable {
        mWidth = (bounds.right - mPadding.right) - (bounds.left + mPadding.left);
        mWarningTextPaint.setTextSize(mHeight * 0.75f);
        mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;

        mIntrinsicHeight = mContext.getResources().getDimensionPixelSize(R.dimen.battery_height);
        mIntrinsicWidth = mMeterStyle == BATTERY_STYLE_PORTRAIT ?
                mContext.getResources().getDimensionPixelSize(R.dimen.battery_width) :
                mContext.getResources().getDimensionPixelSize(R.dimen.battery_height);
    }

    @Override
@@ -303,6 +321,93 @@ public class BatteryMeterDrawableBase extends Drawable {

    @Override
    public void draw(Canvas c) {
        if (mMeterStyle == BATTERY_STYLE_CIRCLE) {
            drawCircle(c);
        } else {
            drawRectangle(c);
        }
    }

    private void drawCircle(Canvas c) {
        final int level = mLevel;

        if (level == -1) return;

        final int circleSize = Math.min(mWidth, mHeight);
        float strokeWidth = circleSize / 6.5f;

        mFramePaint.setStrokeWidth(strokeWidth);
        mFramePaint.setStyle(Paint.Style.STROKE);

        mBatteryPaint.setStrokeWidth(strokeWidth);
        mBatteryPaint.setStyle(Paint.Style.STROKE);

        mFrame.set(
                strokeWidth / 2.0f + mPadding.left,
                strokeWidth / 2.0f,
                circleSize - strokeWidth / 2.0f + mPadding.left,
                circleSize - strokeWidth / 2.0f);

        // set the battery charging color
        mBatteryPaint.setColor(batteryColorForLevel(level));

        if (mCharging) {
            // define the bolt shape
            final float bl = mFrame.left + mFrame.width() / 3.0f;
            final float bt = mFrame.top + mFrame.height() / 3.4f;
            final float br = mFrame.right - mFrame.width() / 4.0f;
            final float bb = mFrame.bottom - mFrame.height() / 5.6f;
            if (mBoltFrame.left != bl || mBoltFrame.top != bt
                    || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
                mBoltFrame.set(bl, bt, br, bb);
                mBoltPath.reset();
                mBoltPath.moveTo(
                        mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
                        mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
                for (int i = 2; i < mBoltPoints.length; i += 2) {
                    mBoltPath.lineTo(
                            mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
                            mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
                }
                mBoltPath.lineTo(
                        mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
                        mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
            }
            c.drawPath(mBoltPath, mBoltPaint);
        }

        // draw thin gray ring first
        c.drawArc(mFrame, 270, 360, false, mFramePaint);

        // draw colored arc representing charge level
        if (level > 0) {
            c.drawArc(mFrame, 270, 3.6f * level, false, mBatteryPaint);
        }

        // compute percentage text
        float pctX = 0, pctY = 0;
        String pctText = null;
        if (!mCharging && level != 100 && mShowPercent) {
            mTextPaint.setColor(getColorForLevel(level));
            mTextPaint.setTextSize(mHeight * (SINGLE_DIGIT_PERCENT ? 0.86f : 0.52f));
            mTextHeight = -mTextPaint.getFontMetrics().ascent;
            pctText = level > mCriticalLevel ?
                    String.valueOf(SINGLE_DIGIT_PERCENT ? (level / 10) : level) : mWarningString;
            pctX = mWidth * 0.5f;
            pctY = (mHeight + mTextHeight) * 0.47f;

            c.drawText(pctText, pctX, pctY, mTextPaint);
        }

        // Draw the powersave outline last
        if (!mCharging && mPowerSaveEnabled && mPowerSaveAsColorError) {
            if (level > 0) {
                c.drawArc(mFrame, 270, 3.6f * level, false, mPowersavePaint);
            }
        }
    }

    private void drawRectangle(Canvas c) {
        final int level = mLevel;
        final Rect bounds = getBounds();

@@ -316,6 +421,12 @@ public class BatteryMeterDrawableBase extends Drawable {
        final int left = mPadding.left + bounds.left;
        final int top = bounds.bottom - mPadding.bottom - height;

        mFramePaint.setStrokeWidth(0);
        mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mBatteryPaint.setStrokeWidth(0);
        mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mFrame.set(left, top, width + left, height + top);
        mFrame.offset(px, 0);

+3 −0
Original line number Diff line number Diff line
@@ -139,4 +139,7 @@
    <string name="quick_settings_location_detail_mode_battery_saving_description">Use Wi\u2011Fi, Bluetooth, or cellular networks to determine location</string>
    <!-- [CHAR LIMIT=130] Location detail panel, description for sensors only mode -->
    <string name="quick_settings_location_detail_mode_sensors_only_description">Use GPS to determine your location</string>

    <!-- Name of the battery status bar icon. -->
    <string name="status_bar_battery">Battery</string>
</resources>
+4 −1
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2016 The CyanogenMod Project
     Copyright (C) 2018 The LineageOS Project
     Copyright (C) 2018-2019 The LineageOS Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -18,4 +18,7 @@
<resources>
    <!-- Largest size an avatar might need to be drawn in the power menu user picker -->
    <dimen name="global_actions_avatar_size">24dp</dimen>

    <!-- Width of the battery icon in the status bar when set to circle style. -->
    <dimen name="status_bar_battery_icon_circle_width">14.5dp</dimen>
</resources>
+3 −4
Original line number Diff line number Diff line
@@ -78,10 +78,9 @@

    <!-- other weird signal stuff -->

    <com.android.systemui.tuner.BatteryPreference
        android:title="@string/battery"
        android:summary="%s"
        android:entries="@array/battery_options" />
    <com.android.systemui.tuner.StatusBarSwitch
        android:key="battery"
        android:title="@string/status_bar_battery" />

    <com.android.systemui.tuner.StatusBarSwitch
        android:key="alarm_clock"
+52 −15
Original line number Diff line number Diff line
@@ -17,7 +17,12 @@ package com.android.systemui;

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 com.android.settingslib.graph.BatteryMeterDrawableBase.BATTERY_STYLE_PORTRAIT;
import static com.android.settingslib.graph.BatteryMeterDrawableBase.BATTERY_STYLE_CIRCLE;
import static com.android.settingslib.graph.BatteryMeterDrawableBase.BATTERY_STYLE_TEXT;

import static lineageos.providers.LineageSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT;

import android.animation.ArgbEvaluator;
import android.app.ActivityManager;
@@ -55,25 +60,31 @@ 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 lineageos.providers.LineageSettings;

import java.text.NumberFormat;

public class BatteryMeterView extends LinearLayout implements
        BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {

    public static final String STATUS_BAR_BATTERY_STYLE =
            "lineagesystem:" + LineageSettings.System.STATUS_BAR_BATTERY_STYLE;

    private final BatteryMeterDrawableBase mDrawable;
    private final String mSlotBattery;
    private final ImageView mBatteryIconView;
    private final CurrentUserTracker mUserTracker;
    private TextView mBatteryPercentView;

    private boolean mCharging;
    private int mBatteryStyle = BATTERY_STYLE_PORTRAIT;

    private BatteryController mBatteryController;
    private SettingObserver mSettingObserver;
    private int mTextColor;
    private int mLevel;
    private boolean mForceShowPercent;
    private boolean mShowPercentAvailable;

    private int mDarkModeBackgroundColor;
    private int mDarkModeFillColor;
@@ -113,9 +124,6 @@ public class BatteryMeterView extends LinearLayout implements
        atts.recycle();

        mSettingObserver = new SettingObserver(new Handler(context.getMainLooper()));
        mShowPercentAvailable = context.getResources().getBoolean(
                com.android.internal.R.bool.config_battery_percentage_setting_available);


        addOnAttachStateChangeListener(
                new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS));
@@ -142,8 +150,8 @@ public class BatteryMeterView extends LinearLayout implements
                mUser = newUserId;
                getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
                getContext().getContentResolver().registerContentObserver(
                        Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver,
                        newUserId);
                        LineageSettings.System.getUriFor(STATUS_BAR_SHOW_BATTERY_PERCENT),
                        false, mSettingObserver, newUserId);
            }
        };

@@ -206,6 +214,10 @@ public class BatteryMeterView extends LinearLayout implements
            boolean hidden = icons.contains(mSlotBattery);
            Dependency.get(IconLogger.class).onIconVisibility(mSlotBattery, !hidden);
            setVisibility(hidden ? View.GONE : View.VISIBLE);
        } else if (STATUS_BAR_BATTERY_STYLE.equals(key) && newValue != null) {
            mBatteryStyle = Integer.parseInt(newValue);
            updateBatteryStyle();
            updateShowPercent();
        }
    }

@@ -216,10 +228,11 @@ public class BatteryMeterView extends LinearLayout implements
        mBatteryController.addCallback(this);
        mUser = ActivityManager.getCurrentUser();
        getContext().getContentResolver().registerContentObserver(
                Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver, mUser);
                LineageSettings.System.getUriFor(STATUS_BAR_SHOW_BATTERY_PERCENT),
                false, mSettingObserver, mUser);
        updateShowPercent();
        Dependency.get(TunerService.class)
                .addTunable(this, StatusBarIconController.ICON_BLACKLIST);
                .addTunable(this, StatusBarIconController.ICON_BLACKLIST, STATUS_BAR_BATTERY_STYLE);
        Dependency.get(ConfigurationController.class).addCallback(this);
        mUserTracker.startTracking();
    }
@@ -243,6 +256,10 @@ public class BatteryMeterView extends LinearLayout implements
        setContentDescription(
                getContext().getString(charging ? R.string.accessibility_battery_level_charging
                        : R.string.accessibility_battery_level, level));
        if (mCharging != charging) {
            mCharging = charging;
            updateShowPercent();
        }
    }

    @Override
@@ -264,11 +281,15 @@ public class BatteryMeterView extends LinearLayout implements

    private void updateShowPercent() {
        final boolean showing = mBatteryPercentView != null;
        final boolean systemSetting = 0 != Settings.System
        final boolean drawPercentInside = 1 == LineageSettings.System
                .getIntForUser(getContext().getContentResolver(),
                SHOW_BATTERY_PERCENT, 0, mUser);

        if ((mShowPercentAvailable && systemSetting) || mForceShowPercent) {
                STATUS_BAR_SHOW_BATTERY_PERCENT, 0, mUser);
        final boolean showPercent = 2 == LineageSettings.System
                .getIntForUser(getContext().getContentResolver(),
                STATUS_BAR_SHOW_BATTERY_PERCENT, 0, mUser);
        if ((showPercent || mForceShowPercent) &&
                (!drawPercentInside || mCharging) || mBatteryStyle == BATTERY_STYLE_TEXT) {
            mDrawable.setShowPercent(false);
            if (!showing) {
                mBatteryPercentView = loadPercentView();
                if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
@@ -279,6 +300,7 @@ public class BatteryMeterView extends LinearLayout implements
                                LayoutParams.MATCH_PARENT));
            }
        } else {
            mDrawable.setShowPercent(drawPercentInside);
            if (showing) {
                removeView(mBatteryPercentView);
                mBatteryPercentView = null;
@@ -302,7 +324,9 @@ public class BatteryMeterView extends LinearLayout implements
        float iconScaleFactor = typedValue.getFloat();

        int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
        int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
        int batteryWidth = mBatteryStyle == BATTERY_STYLE_CIRCLE ?
                res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_circle_width) :
                res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
        int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);

        LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
@@ -313,6 +337,19 @@ public class BatteryMeterView extends LinearLayout implements
        FontSizeUtils.updateFontSize(mBatteryPercentView, R.dimen.qs_time_expanded_size);
    }

    private void updateBatteryStyle() {
        if (mBatteryStyle == BATTERY_STYLE_TEXT) {
            mBatteryIconView.setVisibility(View.GONE);
            mBatteryIconView.setImageDrawable(null);
        } else {
            mDrawable.setMeterStyle(mBatteryStyle);
            mBatteryIconView.setVisibility(View.VISIBLE);
            mBatteryIconView.setImageDrawable(mDrawable);
            scaleBatteryMeterViews();
        }
        setVisibility(View.VISIBLE);
    }

    @Override
    public void onDarkChanged(Rect area, float darkIntensity, int tint) {
        mDarkIntensity = darkIntensity;
Loading