diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d8a910233bcc367dd2b3b103729127e324548bc3..ff7288310c8c3b990ef70a3cdf9eaf7a403f846f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5653,6 +5653,25 @@ public final class Settings {
          */
         public static final String CLICK_PARTIAL_SCREENSHOT = "click_partial_screenshot";
 
+        /**
+         * Display style of the status bar battery information
+         * 0: Display the battery an icon in portrait mode
+         * 1: Display the battery as a circle
+         * 2: Display the battery as plain text
+         * default: 0
+         * @hide
+         */
+        public static final String STATUS_BAR_BATTERY_STYLE = "status_bar_battery_style";
+        /**
+         * Status bar battery %
+         * 0: Hide the battery percentage
+         * 1: Display the battery percentage inside the icon
+         * 2: Display the battery percentage next to the icon
+         * @hide
+         */
+        public static final String STATUS_BAR_SHOW_BATTERY_PERCENT =
+                "status_bar_battery_percent";
+
         /**
          * IMPORTANT: If you add a new public settings you also have to add it to
          * PUBLIC_SETTINGS below. If the new setting is hidden you have to add
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/CircleBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/CircleBatteryDrawable.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f1c76b88cb8439e8e559f96b2d6ee13099742e5c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/CircleBatteryDrawable.kt
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 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.
+ * 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.settingslib.graph
+
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.*
+import android.graphics.drawable.Drawable
+import android.util.TypedValue
+import com.android.settingslib.R
+import com.android.settingslib.Utils
+import kotlin.math.max
+import kotlin.math.min
+
+class CircleBatteryDrawable(private val context: Context, frameColor: Int) : Drawable() {
+    private val criticalLevel: Int
+    private val warningString: String
+    private val framePaint: Paint
+    private val batteryPaint: Paint
+    private val warningTextPaint: Paint
+    private val textPaint: Paint
+    private val boltPaint: Paint
+    private val plusPaint: Paint
+    private val powerSavePaint: Paint
+    private val colors: IntArray
+    private val boltPoints: FloatArray
+    private val boltPath = Path()
+    private val padding = Rect()
+    private val frame = RectF()
+    private val boltFrame = RectF()
+
+    private var chargeColor: Int
+    private var iconTint = Color.WHITE
+    private var intrinsicWidth: Int
+    private var intrinsicHeight: Int
+    private var height = 0
+    private var width = 0
+
+    // Dual tone implies that battery level is a clipped overlay over top of the whole shape
+    private var dualTone = false
+
+    override fun getIntrinsicHeight() = intrinsicHeight
+
+    override fun getIntrinsicWidth() = intrinsicWidth
+
+    var charging = false
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
+    var powerSaveEnabled = false
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
+    var showPercent = false
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
+    var batteryLevel = -1
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
+    // an approximation of View.postInvalidate()
+    private fun postInvalidate() {
+        unscheduleSelf { invalidateSelf() }
+        scheduleSelf({ invalidateSelf() }, 0)
+    }
+
+    override fun setBounds(left: Int, top: Int, right: Int, bottom: Int) {
+        super.setBounds(left, top, right, bottom)
+        updateSize()
+    }
+
+    private fun updateSize() {
+        val res = context.resources
+        height = bounds.bottom - padding.bottom - (bounds.top + padding.top)
+        width = bounds.right - padding.right - (bounds.left + padding.left)
+        warningTextPaint.textSize = height * 0.75f
+        intrinsicHeight = res.getDimensionPixelSize(R.dimen.battery_height)
+        intrinsicWidth = res.getDimensionPixelSize(R.dimen.battery_height)
+    }
+
+    override fun getPadding(padding: Rect): Boolean {
+        if (this.padding.left == 0 &&
+            this.padding.top == 0 &&
+            this.padding.right == 0 &&
+            this.padding.bottom == 0
+        ) {
+            return super.getPadding(padding)
+        }
+        padding.set(this.padding)
+        return true
+    }
+
+    private fun getColorForLevel(percent: Int): Int {
+        var thresh: Int
+        var color = 0
+        var i = 0
+        while (i < colors.size) {
+            thresh = colors[i]
+            color = colors[i + 1]
+            if (percent <= thresh) {
+                // Respect tinting for "normal" level
+                return if (i == colors.size - 2) {
+                    iconTint
+                } else {
+                    color
+                }
+            }
+            i += 2
+        }
+        return color
+    }
+
+    private fun batteryColorForLevel(level: Int) =
+        if (charging || powerSaveEnabled)
+            chargeColor
+        else
+            getColorForLevel(level)
+
+    fun setColors(fgColor: Int, bgColor: Int, singleToneColor: Int) {
+        val fillColor = if (dualTone) fgColor else singleToneColor
+
+        iconTint = fillColor
+        framePaint.color = bgColor
+        boltPaint.color = fillColor
+        chargeColor = fillColor
+
+        invalidateSelf()
+    }
+
+    override fun draw(c: Canvas) {
+        if (batteryLevel == -1) return
+        val circleSize = min(width, height)
+        val strokeWidth = circleSize / 6.5f
+        framePaint.strokeWidth = strokeWidth
+        framePaint.style = Paint.Style.STROKE
+        batteryPaint.strokeWidth = strokeWidth
+        batteryPaint.style = Paint.Style.STROKE
+        powerSavePaint.strokeWidth = strokeWidth
+        frame[
+                strokeWidth / 2.0f + padding.left, strokeWidth / 2.0f,
+                circleSize - strokeWidth / 2.0f + padding.left
+        ] = circleSize - strokeWidth / 2.0f
+        // set the battery charging color
+        batteryPaint.color = batteryColorForLevel(batteryLevel)
+        if (charging) { // define the bolt shape
+            val bl = frame.left + frame.width() / 3.0f
+            val bt = frame.top + frame.height() / 3.4f
+            val br = frame.right - frame.width() / 4.0f
+            val bb = frame.bottom - frame.height() / 5.6f
+            if (boltFrame.left != bl ||
+                boltFrame.top != bt ||
+                boltFrame.right != br ||
+                boltFrame.bottom != bb
+            ) {
+                boltFrame[bl, bt, br] = bb
+                boltPath.reset()
+                boltPath.moveTo(
+                    boltFrame.left + boltPoints[0] * boltFrame.width(),
+                    boltFrame.top + boltPoints[1] * boltFrame.height()
+                )
+                var i = 2
+                while (i < boltPoints.size) {
+                    boltPath.lineTo(
+                        boltFrame.left + boltPoints[i] * boltFrame.width(),
+                        boltFrame.top + boltPoints[i + 1] * boltFrame.height()
+                    )
+                    i += 2
+                }
+                boltPath.lineTo(
+                    boltFrame.left + boltPoints[0] * boltFrame.width(),
+                    boltFrame.top + boltPoints[1] * boltFrame.height()
+                )
+            }
+            c.drawPath(boltPath, boltPaint)
+        }
+        // draw thin gray ring first
+        c.drawArc(frame, 270f, 360f, false, framePaint)
+        // draw colored arc representing charge level
+        if (batteryLevel > 0) {
+            if (!charging && powerSaveEnabled) {
+                c.drawArc(frame, 270f, 3.6f * batteryLevel, false, powerSavePaint)
+            } else {
+                c.drawArc(frame, 270f, 3.6f * batteryLevel, false, batteryPaint)
+            }
+        }
+        // compute percentage text
+        if (!charging && batteryLevel != 100 && showPercent) {
+            textPaint.color = getColorForLevel(batteryLevel)
+            textPaint.textSize = height * 0.52f
+            val textHeight = -textPaint.fontMetrics.ascent
+            val pctText =
+                if (batteryLevel > criticalLevel)
+                    batteryLevel.toString()
+                else
+                    warningString
+            val pctX = width * 0.5f
+            val pctY = (height + textHeight) * 0.47f
+            c.drawText(pctText, pctX, pctY, textPaint)
+        }
+    }
+
+    // Some stuff required by Drawable.
+    override fun setAlpha(alpha: Int) {}
+
+    override fun setColorFilter(colorFilter: ColorFilter?) {
+        framePaint.colorFilter = colorFilter
+        batteryPaint.colorFilter = colorFilter
+        warningTextPaint.colorFilter = colorFilter
+        boltPaint.colorFilter = colorFilter
+        plusPaint.colorFilter = colorFilter
+    }
+
+    override fun getOpacity() = PixelFormat.UNKNOWN
+
+    companion object {
+        private fun loadPoints(
+            res: Resources,
+            pointArrayRes: Int
+        ): FloatArray {
+            val pts = res.getIntArray(pointArrayRes)
+            var maxX = 0
+            var maxY = 0
+            run {
+                var i = 0
+                while (i < pts.size) {
+                    maxX = max(maxX, pts[i])
+                    maxY = max(maxY, pts[i + 1])
+                    i += 2
+                }
+            }
+            val ptsF = FloatArray(pts.size)
+            var i = 0
+            while (i < pts.size) {
+                ptsF[i] = pts[i].toFloat() / maxX
+                ptsF[i + 1] = pts[i + 1].toFloat() / maxY
+                i += 2
+            }
+            return ptsF
+        }
+    }
+
+    init {
+        val res = context.resources
+        val color_levels = res.obtainTypedArray(R.array.batterymeter_color_levels)
+        val color_values = res.obtainTypedArray(R.array.batterymeter_color_values)
+        colors = IntArray(2 * color_levels.length())
+        for (i in 0 until color_levels.length()) {
+            colors[2 * i] = color_levels.getInt(i, 0)
+            if (color_values.getType(i) == TypedValue.TYPE_ATTRIBUTE) {
+                colors[2 * i + 1] = Utils.getColorAttrDefaultColor(
+                    context,
+                    color_values.getThemeAttributeId(i, 0)
+                )
+            } else {
+                colors[2 * i + 1] = color_values.getColor(i, 0)
+            }
+        }
+        color_levels.recycle()
+        color_values.recycle()
+        warningString = res.getString(R.string.battery_meter_very_low_overlay_symbol)
+        criticalLevel = res.getInteger(
+            com.android.internal.R.integer.config_criticalBatteryWarningLevel
+        )
+        framePaint = Paint(Paint.ANTI_ALIAS_FLAG)
+        framePaint.color = frameColor
+        framePaint.isDither = true
+        batteryPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+        batteryPaint.isDither = true
+        textPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+        textPaint.typeface = Typeface.create("sans-serif-condensed", Typeface.BOLD)
+        textPaint.textAlign = Paint.Align.CENTER
+        warningTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+        warningTextPaint.typeface = Typeface.create("sans-serif", Typeface.BOLD)
+        warningTextPaint.textAlign = Paint.Align.CENTER
+        if (colors.size > 1) {
+            warningTextPaint.color = colors[1]
+        }
+        chargeColor = Utils.getColorStateListDefaultColor(context, R.color.meter_consumed_color)
+        boltPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+        boltPaint.color = Utils.getColorStateListDefaultColor(
+            context,
+            R.color.batterymeter_bolt_color
+        )
+        boltPoints =
+            loadPoints(res, R.array.batterymeter_bolt_points)
+        plusPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+        plusPaint.color = Utils.getColorStateListDefaultColor(
+            context,
+            R.color.batterymeter_plus_color
+        )
+        powerSavePaint = Paint(Paint.ANTI_ALIAS_FLAG)
+        powerSavePaint.color = plusPaint.color
+        powerSavePaint.style = Paint.Style.STROKE
+        intrinsicWidth = res.getDimensionPixelSize(R.dimen.battery_width)
+        intrinsicHeight = res.getDimensionPixelSize(R.dimen.battery_height)
+
+        dualTone = res.getBoolean(com.android.internal.R.bool.config_batterymeterDualTone)
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
index 5fa04f93e993ade9638e8588d32bf91fad483dfd..e360cde880f2d9603aff0fae1913ae37fc877da9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -25,6 +25,7 @@ import android.graphics.Path
 import android.graphics.PixelFormat
 import android.graphics.Rect
 import android.graphics.RectF
+import android.graphics.Typeface
 import android.graphics.drawable.Drawable
 import android.util.PathParser
 import android.util.TypedValue
@@ -106,6 +107,12 @@ open class ThemedBatteryDrawable(private val context: Context, frameColor: Int)
             postInvalidate()
         }
 
+    var showPercent = false
+        set(value) {
+            field = value
+            postInvalidate()
+        }
+
     private val fillColorStrokePaint = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
         p.color = frameColor
         p.alpha = 255
@@ -152,6 +159,11 @@ open class ThemedBatteryDrawable(private val context: Context, frameColor: Int)
         p.style = Paint.Style.FILL_AND_STROKE
     }
 
+    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
+        p.typeface = Typeface.create("sans-serif-condensed", Typeface.BOLD)
+        p.textAlign = Paint.Align.CENTER
+    }
+
     init {
         val density = context.resources.displayMetrics.density
         intrinsicHeight = (Companion.HEIGHT * density).toInt()
@@ -250,6 +262,25 @@ open class ThemedBatteryDrawable(private val context: Context, frameColor: Int)
             c.drawPath(scaledPlus, errorPaint)
         }
         c.restore()
+
+        if (!charging && batteryLevel < 100 && showPercent) {
+            textPaint.textSize = bounds.height() * 0.38f
+            val textHeight = -textPaint.fontMetrics.ascent
+            val pctX = bounds.width() * 0.5f
+            val pctY = (bounds.height() + textHeight) * 0.5f
+
+            textPaint.color = fillColor
+            c.drawText(batteryLevel.toString(), pctX, pctY, textPaint)
+
+            textPaint.color = fillColor.toInt().inv() or 0xFF000000.toInt()
+            c.save()
+            c.clipRect(fillRect.left,
+                    fillRect.top + (fillRect.height() * (1 - fillFraction)),
+                    fillRect.right,
+                    fillRect.bottom)
+            c.drawText(batteryLevel.toString(), pctX, pctY, textPaint)
+            c.restore()
+        }
     }
 
     private fun batteryColorForLevel(level: Int): Int {
diff --git a/packages/SystemUI/res/layout/battery_percentage_view.xml b/packages/SystemUI/res/layout/battery_percentage_view.xml
index b9b1bb1f4330b9c9b88758c55ac6fcaa9a2f0083..75024ad914a81a5ce04736772aa06f67a91892a4 100644
--- a/packages/SystemUI/res/layout/battery_percentage_view.xml
+++ b/packages/SystemUI/res/layout/battery_percentage_view.xml
@@ -25,6 +25,5 @@
         android:textAppearance="@style/TextAppearance.StatusBar.Clock"
         android:textColor="?android:attr/textColorPrimary"
         android:gravity="center_vertical|start"
-        android:paddingStart="@dimen/battery_level_padding_start"
         android:importantForAccessibility="no"
         />
diff --git a/packages/SystemUI/res/values/lmodroid_dimens.xml b/packages/SystemUI/res/values/lmodroid_dimens.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eacc78e3a96a07382a3268ac484ffcce6cd23c24
--- /dev/null
+++ b/packages/SystemUI/res/values/lmodroid_dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The CyanogenMod Project
+     Copyright (C) 2018-2022 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.
+     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.
+-->
+<resources>
+    <!-- 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>
diff --git a/packages/SystemUI/res/xml/status_bar_prefs.xml b/packages/SystemUI/res/xml/status_bar_prefs.xml
index ceb624e8f88c193a96161930b7227791e6b44426..4e7c1da3a48137bf86847d23f9eb8b541f33602f 100644
--- a/packages/SystemUI/res/xml/status_bar_prefs.xml
+++ b/packages/SystemUI/res/xml/status_bar_prefs.xml
@@ -81,10 +81,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/battery" />
 
     <com.android.systemui.tuner.StatusBarSwitch
         android:key="alarm_clock"
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 39088c367a276c90a31b68834572beace6094c01..13b507c54020ffe776b26934a7156f21269a9a19 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.battery;
 
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+import static android.provider.Settings.System.STATUS_BAR_SHOW_BATTERY_PERCENT;
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 
@@ -36,6 +36,7 @@ import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.LayoutInflater;
+import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -44,6 +45,7 @@ import android.widget.TextView;
 import androidx.annotation.StyleRes;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.settingslib.graph.CircleBatteryDrawable;
 import com.android.settingslib.graph.ThemedBatteryDrawable;
 import com.android.systemui.DualToneHandler;
 import com.android.systemui.R;
@@ -59,6 +61,13 @@ import java.text.NumberFormat;
 
 public class BatteryMeterView extends LinearLayout implements DarkReceiver {
 
+    protected static final String STATUS_BAR_BATTERY_STYLE =
+            "customsystem:" + Settings.System.STATUS_BAR_BATTERY_STYLE;
+
+    protected static final int BATTERY_STYLE_PORTRAIT = 0;
+    protected static final int BATTERY_STYLE_CIRCLE = 1;
+    protected static final int BATTERY_STYLE_TEXT = 2;
+
     @Retention(SOURCE)
     @IntDef({MODE_DEFAULT, MODE_ON, MODE_OFF, MODE_ESTIMATE})
     public @interface BatteryPercentMode {}
@@ -67,7 +76,8 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
     public static final int MODE_OFF = 2;
     public static final int MODE_ESTIMATE = 3;
 
-    private final ThemedBatteryDrawable mDrawable;
+    private final CircleBatteryDrawable mCircleDrawable;
+    private final ThemedBatteryDrawable mThemedDrawable;
     private final ImageView mBatteryIconView;
     private TextView mBatteryPercentView;
 
@@ -75,13 +85,14 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
     private int mTextColor;
     private int mLevel;
     private int mShowPercentMode = MODE_DEFAULT;
-    private boolean mShowPercentAvailable;
     private boolean mCharging;
     // Error state where we know nothing about the current battery state
     private boolean mBatteryStateUnknown;
     // Lazily-loaded since this is expected to be a rare-if-ever state
     private Drawable mUnknownStateDrawable;
 
+    private int mBatteryStyle = BATTERY_STYLE_PORTRAIT;
+
     private DualToneHandler mDualToneHandler;
 
     private int mNonAdaptedSingleToneColor;
@@ -105,16 +116,14 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
         final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
                 context.getColor(R.color.meter_background_color));
         mPercentageStyleId = atts.getResourceId(R.styleable.BatteryMeterView_textAppearance, 0);
-        mDrawable = new ThemedBatteryDrawable(context, frameColor);
+        mCircleDrawable = new CircleBatteryDrawable(context, frameColor);
+        mThemedDrawable = new ThemedBatteryDrawable(context, frameColor);
         atts.recycle();
 
-        mShowPercentAvailable = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_battery_percentage_setting_available);
-
         setupLayoutTransition();
 
         mBatteryIconView = new ImageView(context);
-        mBatteryIconView.setImageDrawable(mDrawable);
+        mBatteryIconView.setImageDrawable(mThemedDrawable);
         final MarginLayoutParams mlp = new MarginLayoutParams(
                 getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_width),
                 getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_height));
@@ -146,6 +155,13 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
         setLayoutTransition(transition);
     }
 
+    protected void setBatteryStyle(int batteryStyle) {
+        if (batteryStyle == mBatteryStyle) return;
+        mBatteryStyle = batteryStyle;
+        updateBatteryStyle();
+        updateShowPercent();
+    }
+
     public void setForceShowPercent(boolean show) {
         setPercentShowMode(show ? MODE_ON : MODE_DEFAULT);
     }
@@ -185,15 +201,21 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
     }
 
     void onBatteryLevelChanged(int level, boolean pluggedIn) {
-        mDrawable.setCharging(pluggedIn);
-        mDrawable.setBatteryLevel(level);
+        mCircleDrawable.setCharging(pluggedIn);
+        mThemedDrawable.setCharging(pluggedIn);
+        mCircleDrawable.setBatteryLevel(level);
+        mThemedDrawable.setBatteryLevel(level);
         mCharging = pluggedIn;
         mLevel = level;
         updatePercentText();
+        if (pluggedIn) {
+            updateShowPercent();
+        }
     }
 
     void onPowerSaveChanged(boolean isPowerSave) {
-        mDrawable.setPowerSaveEnabled(isPowerSave);
+        mCircleDrawable.setPowerSaveEnabled(isPowerSave);
+        mThemedDrawable.setPowerSaveEnabled(isPowerSave);
     }
 
     private TextView loadPercentView() {
@@ -270,16 +292,21 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
     void updateShowPercent() {
         final boolean showing = mBatteryPercentView != null;
         // TODO(b/140051051)
-        final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
-                .getIntForUser(getContext().getContentResolver(),
-                SHOW_BATTERY_PERCENT, 0, UserHandle.USER_CURRENT));
+        final int showBatteryPercent = Settings.System.getIntForUser(
+                getContext().getContentResolver(), STATUS_BAR_SHOW_BATTERY_PERCENT, 0,
+                UserHandle.USER_CURRENT);
+        final boolean drawPercentInside = mShowPercentMode == MODE_DEFAULT &&
+                showBatteryPercent == 1;
+        final boolean drawPercentOnly = mShowPercentMode == MODE_ESTIMATE ||
+                showBatteryPercent == 2;
         boolean shouldShow =
-                (mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
-                || mShowPercentMode == MODE_ON
-                || mShowPercentMode == MODE_ESTIMATE;
+                (drawPercentOnly && (!drawPercentInside || mCharging) ||
+                mBatteryStyle == BATTERY_STYLE_TEXT);
         shouldShow = shouldShow && !mBatteryStateUnknown;
 
         if (shouldShow) {
+            mCircleDrawable.setShowPercent(false);
+            mThemedDrawable.setShowPercent(false);
             if (!showing) {
                 mBatteryPercentView = loadPercentView();
                 if (mPercentageStyleId != 0) { // Only set if specified as attribute
@@ -292,7 +319,17 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
                                 LayoutParams.WRAP_CONTENT,
                                 LayoutParams.MATCH_PARENT));
             }
+            if (mBatteryStyle == BATTERY_STYLE_TEXT) {
+                mBatteryPercentView.setPaddingRelative(0, 0, 0, 0);
+            } else {
+                Resources res = getContext().getResources();
+                mBatteryPercentView.setPaddingRelative(
+                        res.getDimensionPixelSize(R.dimen.battery_level_padding_start), 0, 0, 0);
+            }
+
         } else {
+            mCircleDrawable.setShowPercent(drawPercentInside);
+            mThemedDrawable.setShowPercent(drawPercentInside);
             if (showing) {
                 removeView(mBatteryPercentView);
                 mBatteryPercentView = null;
@@ -319,7 +356,7 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
         if (mBatteryStateUnknown) {
             mBatteryIconView.setImageDrawable(getUnknownStateDrawable());
         } else {
-            mBatteryIconView.setImageDrawable(mDrawable);
+            updateBatteryStyle();
         }
 
         updateShowPercent();
@@ -336,7 +373,9 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
         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(
@@ -346,6 +385,25 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
         mBatteryIconView.setLayoutParams(scaledLayoutParams);
     }
 
+    private void updateBatteryStyle() {
+        switch (mBatteryStyle) {
+            case BATTERY_STYLE_PORTRAIT:
+                mBatteryIconView.setImageDrawable(mThemedDrawable);
+                mBatteryIconView.setVisibility(View.VISIBLE);
+                scaleBatteryMeterViews();
+                break;
+            case BATTERY_STYLE_CIRCLE:
+                mBatteryIconView.setImageDrawable(mCircleDrawable);
+                mBatteryIconView.setVisibility(View.VISIBLE);
+                scaleBatteryMeterViews();
+                break;
+            case BATTERY_STYLE_TEXT:
+                mBatteryIconView.setVisibility(View.GONE);
+                mBatteryIconView.setImageDrawable(null);
+                break;
+        }
+    }
+
     @Override
     public void onDarkChanged(Rect area, float darkIntensity, int tint) {
         float intensity = DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0;
@@ -366,7 +424,8 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
      * @param singleToneColor
      */
     public void updateColors(int foregroundColor, int backgroundColor, int singleToneColor) {
-        mDrawable.setColors(foregroundColor, backgroundColor, singleToneColor);
+        mCircleDrawable.setColors(foregroundColor, backgroundColor, singleToneColor);
+        mThemedDrawable.setColors(foregroundColor, backgroundColor, singleToneColor);
         mTextColor = singleToneColor;
         if (mBatteryPercentView != null) {
             mBatteryPercentView.setTextColor(singleToneColor);
@@ -378,10 +437,11 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        String powerSave = mDrawable == null ? null : mDrawable.getPowerSaveEnabled() + "";
+        String powerSave = mThemedDrawable == null ?
+                null : mThemedDrawable.getPowerSaveEnabled() + "";
         CharSequence percent = mBatteryPercentView == null ? null : mBatteryPercentView.getText();
         pw.println("  BatteryMeterView:");
-        pw.println("    mDrawable.getPowerSave: " + powerSave);
+        pw.println("    getPowerSave: " + powerSave);
         pw.println("    mBatteryPercentView.getText(): " + percent);
         pw.println("    mTextColor: #" + Integer.toHexString(mTextColor));
         pw.println("    mBatteryStateUnknown: " + mBatteryStateUnknown);
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
index ae9a32309d45cdc6d9f1539dc6496901121d0457..34480b594282dce3ea0962fae63d3638820bb902 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.battery;
 
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+import static android.provider.Settings.System.STATUS_BAR_SHOW_BATTERY_PERCENT;
 
 import android.app.ActivityManager;
 import android.content.ContentResolver;
@@ -63,7 +63,13 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
             if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
                 ArraySet<String> icons = StatusBarIconController.getIconHideList(
                         getContext(), newValue);
-                mView.setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
+                mBatteryHidden = icons.contains(mSlotBattery);
+                mView.setVisibility(mBatteryHidden ? View.GONE : View.VISIBLE);
+            } else if (BatteryMeterView.STATUS_BAR_BATTERY_STYLE.equals(key)) {
+                if (!mBatteryHidden) {
+                    mView.setBatteryStyle(TunerService.parseInteger(newValue,
+                            BatteryMeterView.BATTERY_STYLE_PORTRAIT));
+                }
             }
         }
     };
@@ -90,6 +96,8 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
     private boolean mIgnoreTunerUpdates;
     private boolean mIsSubscribedForTunerUpdates;
 
+    private boolean mBatteryHidden;
+
     @Inject
     public BatteryMeterViewController(
             BatteryMeterView view,
@@ -156,7 +164,8 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
             return;
         }
 
-        mTunerService.addTunable(mTunable, StatusBarIconController.ICON_HIDE_LIST);
+        mTunerService.addTunable(mTunable, StatusBarIconController.ICON_HIDE_LIST,
+                BatteryMeterView.STATUS_BAR_BATTERY_STYLE);
         mIsSubscribedForTunerUpdates = true;
     }
 
@@ -171,7 +180,7 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
 
     private void registerShowBatteryPercentObserver(int user) {
         mContentResolver.registerContentObserver(
-                Settings.System.getUriFor(SHOW_BATTERY_PERCENT),
+                Settings.System.getUriFor(STATUS_BAR_SHOW_BATTERY_PERCENT),
                 false,
                 mSettingObserver,
                 user);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index f068a8ec8294f494e96b449e904607d71d3e63ac..eb41536e21d01e7acc83a7f8f1ac8871cdc660e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -62,7 +62,6 @@ public class KeyguardStatusBarView extends RelativeLayout {
 
     private final Rect mEmptyRect = new Rect(0, 0, 0, 0);
 
-    private boolean mShowPercentAvailable;
     private boolean mBatteryCharging;
 
     private TextView mCarrierLabel;
@@ -178,8 +177,6 @@ public class KeyguardStatusBarView extends RelativeLayout {
                 R.dimen.ongoing_appops_dot_min_padding);
         mCutoutSideNudge = getResources().getDimensionPixelSize(
                 R.dimen.display_cutout_margin_consumption);
-        mShowPercentAvailable = getContext().getResources().getBoolean(
-                com.android.internal.R.bool.config_battery_percentage_setting_available);
         mRoundedCornerPadding = res.getDimensionPixelSize(
                 R.dimen.rounded_corner_content_padding);
     }
@@ -209,7 +206,7 @@ public class KeyguardStatusBarView extends RelativeLayout {
                 mMultiUserAvatar.setVisibility(View.GONE);
             }
         }
-        mBatteryView.setForceShowPercent(mBatteryCharging && mShowPercentAvailable);
+        mBatteryView.setForceShowPercent(mBatteryCharging);
     }
 
     private void updateSystemIconsLayoutParams() {