diff options
Diffstat (limited to 'packages')
13 files changed, 1079 insertions, 395 deletions
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml index b5f917a..8d33742 100644 --- a/packages/SystemUI/res/layout/keyguard_status_bar.xml +++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml @@ -52,7 +52,7 @@ > <include layout="@layout/system_icons" /> </FrameLayout> - <TextView android:id="@+id/battery_level" + <com.android.systemui.BatteryLevelTextView android:id="@+id/battery_level_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 2cbe61f..f0932d3 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -95,6 +95,14 @@ <include layout="@layout/system_icons" /> + <com.android.systemui.BatteryLevelTextView android:id="@+id/battery_level_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginStart="@dimen/header_battery_margin_keyguard" + android:textColor="#ffffff" + android:textSize="@dimen/battery_level_text_size" /> + <com.android.systemui.statusbar.policy.Clock android:id="@+id/clock" android:textAppearance="@style/TextAppearance.StatusBar.Clock" diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml index 12c00cc..783054c 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml @@ -85,7 +85,7 @@ > <include layout="@layout/system_icons" /> </FrameLayout> - <TextView android:id="@+id/battery_level" + <com.android.systemui.BatteryLevelTextView android:id="@+id/battery_level_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" diff --git a/packages/SystemUI/res/values/cm_arrays.xml b/packages/SystemUI/res/values/cm_arrays.xml new file mode 100644 index 0000000..a9e3654 --- /dev/null +++ b/packages/SystemUI/res/values/cm_arrays.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2012-2014 The CyanogenMod 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <array name="batterymeter_inverted_bolt_points" translatable="false"> + <item>743</item><item>73</item> + <item>743</item><item>292</item> + <item>442</item><item>201</item> + <item>442</item><item>400</item> + <item>0</item><item>20</item> + <item>369</item><item>157</item> + <item>369</item><item>0</item> + </array> +</resources> diff --git a/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java new file mode 100644 index 0000000..4717a0b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2014 The CyanogenMod 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; + +import com.android.systemui.statusbar.policy.BatteryController; + +import android.content.Context; +import android.content.res.Configuration; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.TextView; + +import java.text.NumberFormat; + +public class BatteryLevelTextView extends TextView implements + BatteryController.BatteryStateChangeCallback{ + private BatteryController mBatteryController; + private boolean mBatteryCharging; + private boolean mForceShow; + private boolean mAttached; + private int mRequestedVisibility; + private int mStyle; + private int mPercentMode; + + public BatteryLevelTextView(Context context, AttributeSet attrs) { + super(context, attrs); + mRequestedVisibility = getVisibility(); + } + + public void setForceShown(boolean forceShow) { + mForceShow = forceShow; + updateVisibility(); + } + + public void setBatteryController(BatteryController batteryController) { + mBatteryController = batteryController; + if (mAttached) { + mBatteryController.addStateChangedCallback(this); + } + } + + @Override + public void setVisibility(int visibility) { + mRequestedVisibility = visibility; + updateVisibility(); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + // Respect font size setting. + setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.battery_level_text_size)); + } + + @Override + public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); + setText(percentage); + if (mBatteryCharging != charging) { + mBatteryCharging = charging; + updateVisibility(); + } + } + + @Override + public void onPowerSaveChanged() { + // Not used + } + + @Override + public void onBatteryStyleChanged(int style, int percentMode) { + mStyle = style; + mPercentMode = percentMode; + updateVisibility(); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + + if (mBatteryController != null) { + mBatteryController.addStateChangedCallback(this); + } + + mAttached = true; + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mAttached = false; + + if (mBatteryController != null) { + mBatteryController.removeStateChangedCallback(this); + } + } + + private void updateVisibility() { + boolean showNextPercent = mPercentMode == BatteryController.PERCENTAGE_MODE_OUTSIDE + || (mBatteryCharging && mPercentMode == BatteryController.PERCENTAGE_MODE_INSIDE); + if (mStyle == BatteryController.STYLE_GONE) { + showNextPercent = false; + } else if (mStyle == BatteryController.STYLE_TEXT) { + showNextPercent = true; + } + + if (showNextPercent || mForceShow) { + super.setVisibility(mRequestedVisibility); + } else { + super.setVisibility(GONE); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index 8cbfa0d..41d4aae 100755 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2013-14 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. @@ -16,6 +16,8 @@ package com.android.systemui; +import com.android.systemui.statusbar.policy.BatteryController; + import android.animation.ArgbEvaluator; import android.content.BroadcastReceiver; import android.content.Context; @@ -23,32 +25,22 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.content.res.TypedArray; -import android.database.ContentObserver; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; -import android.net.Uri; import android.os.BatteryManager; import android.os.Bundle; -import android.os.Handler; -import android.os.UserHandle; -import android.provider.Settings; import android.util.AttributeSet; import android.view.View; -import com.android.systemui.cm.UserContentObserver; -import com.android.systemui.statusbar.policy.BatteryController; - public class BatteryMeterView extends View implements DemoMode, BatteryController.BatteryStateChangeCallback { public static final String TAG = BatteryMeterView.class.getSimpleName(); public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST"; - public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent"; - - private static final boolean SINGLE_DIGIT_PERCENT = false; private static final int FULL = 96; @@ -56,25 +48,26 @@ public class BatteryMeterView extends View implements DemoMode, private final int[] mColors; - private boolean mShowPercent; + protected boolean mShowPercent = true; private float mButtonHeightFraction; private float mSubpixelSmoothingLeft; private float mSubpixelSmoothingRight; - private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint; - private float mTextHeight, mWarningTextHeight; - private int mIconTint = Color.WHITE; + + public enum BatteryMeterMode { + BATTERY_METER_GONE, + BATTERY_METER_ICON_PORTRAIT, + BATTERY_METER_ICON_LANDSCAPE, + BATTERY_METER_CIRCLE, + BATTERY_METER_TEXT + } private int mHeight; private int mWidth; private String mWarningString; private final int mCriticalLevel; - private int mChargeColor; - private final float[] mBoltPoints; - private final Path mBoltPath = new Path(); + private final int mFrameColor; - private final RectF mFrame = new RectF(); - private final RectF mButtonFrame = new RectF(); - private final RectF mBoltFrame = new RectF(); + private boolean mAnimationsEnabled; private final Path mShapePath = new Path(); private final Path mClipPath = new Path(); @@ -89,8 +82,129 @@ public class BatteryMeterView extends View implements DemoMode, private int mLightModeBackgroundColor; private int mLightModeFillColor; - private BatteryTracker mTracker = new BatteryTracker(); - private final SettingObserver mSettingObserver = new SettingObserver(); + protected BatteryMeterMode mMeterMode = null; + + protected boolean mAttached; + + private boolean mDemoMode; + protected BatteryTracker mDemoTracker = new BatteryTracker(); + protected BatteryTracker mTracker = new BatteryTracker(); + private BatteryMeterDrawable mBatteryMeterDrawable; + private int mIconTint = Color.WHITE; + + private class BatteryTracker extends BroadcastReceiver { + public static final int UNKNOWN_LEVEL = -1; + + // current battery status + boolean present = true; + int level = UNKNOWN_LEVEL; + String percentStr; + int plugType; + boolean plugged; + int health; + int status; + String technology; + int voltage; + int temperature; + boolean testmode = false; + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { + if (testmode && ! intent.getBooleanExtra("testmode", false)) return; + + level = (int)(100f + * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) + / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); + + present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true); + plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); + plugged = plugType != 0; + health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, + BatteryManager.BATTERY_HEALTH_UNKNOWN); + status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, + BatteryManager.BATTERY_STATUS_UNKNOWN); + technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY); + voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0); + temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0); + + setContentDescription( + context.getString(R.string.accessibility_battery_level, level)); + if (mBatteryMeterDrawable != null) { + setVisibility(View.VISIBLE); + invalidate(); + } + } else if (action.equals(ACTION_LEVEL_TEST)) { + testmode = true; + post(new Runnable() { + int curLevel = 0; + int incr = 1; + int saveLevel = level; + int savePlugged = plugType; + Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED); + @Override + public void run() { + if (curLevel < 0) { + testmode = false; + dummy.putExtra("level", saveLevel); + dummy.putExtra("plugged", savePlugged); + dummy.putExtra("testmode", false); + } else { + dummy.putExtra("level", curLevel); + dummy.putExtra("plugged", incr > 0 + ? BatteryManager.BATTERY_PLUGGED_AC : 0); + dummy.putExtra("testmode", true); + } + getContext().sendBroadcast(dummy); + + if (!testmode) return; + + curLevel += incr; + if (curLevel == 100) { + incr *= -1; + } + postDelayed(this, 200); + } + }); + } + } + + protected boolean shouldIndicateCharging() { + if (status == BatteryManager.BATTERY_STATUS_CHARGING) { + return true; + } + if (plugged) { + return status == BatteryManager.BATTERY_STATUS_FULL; + } + return false; + } + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(ACTION_LEVEL_TEST); + final Intent sticky = getContext().registerReceiver(mTracker, filter); + if (sticky != null) { + // preload the battery level + mTracker.onReceive(getContext(), sticky); + } + mBatteryController.addStateChangedCallback(this); + mAttached = true; + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + mAttached = false; + getContext().unregisterReceiver(mTracker); + mBatteryController.removeStateChangedCallback(this); + } public BatteryMeterView(Context context) { this(context, null, 0); @@ -106,8 +220,8 @@ public class BatteryMeterView extends View implements DemoMode, final Resources res = context.getResources(); TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView, defStyle, 0); - final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor, - context.getColor(R.color.batterymeter_frame_color)); + mFrameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor, + res.getColor(R.color.batterymeter_frame_color)); TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels); TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values); @@ -120,9 +234,8 @@ public class BatteryMeterView extends View implements DemoMode, levels.recycle(); colors.recycle(); atts.recycle(); - updateShowPercent(); mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol); - mCriticalLevel = mContext.getResources().getInteger( + mCriticalLevel = getContext().getResources().getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); mButtonHeightFraction = context.getResources().getFraction( R.fraction.battery_button_height_fraction, 1, 1); @@ -131,66 +244,46 @@ public class BatteryMeterView extends View implements DemoMode, mSubpixelSmoothingRight = context.getResources().getFraction( R.fraction.battery_subpixel_smoothing_right, 1, 1); - 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); - mTextPaint.setTypeface(font); - mTextPaint.setTextAlign(Paint.Align.CENTER); - - mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mWarningTextPaint.setColor(mColors[1]); - font = Typeface.create("sans-serif", Typeface.BOLD); - mWarningTextPaint.setTypeface(font); - mWarningTextPaint.setTextAlign(Paint.Align.CENTER); - - mChargeColor = context.getColor(R.color.batterymeter_charge_color); - - mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color)); - mBoltPoints = loadBoltPoints(res); - mDarkModeBackgroundColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_background); mDarkModeFillColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_fill); mLightModeBackgroundColor = context.getColor(R.color.light_mode_icon_color_dual_tone_background); mLightModeFillColor = context.getColor(R.color.light_mode_icon_color_dual_tone_fill); - } - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); + setAnimationsEnabled(true); + } - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(ACTION_LEVEL_TEST); - final Intent sticky = getContext().registerReceiver(mTracker, filter); - if (sticky != null) { - // preload the battery level - mTracker.onReceive(getContext(), sticky); + protected BatteryMeterDrawable createBatteryMeterDrawable(BatteryMeterMode mode) { + Resources res = mContext.getResources(); + switch (mode) { + case BATTERY_METER_CIRCLE: + return new CircleBatteryMeterDrawable(res); + case BATTERY_METER_ICON_LANDSCAPE: + return new NormalBatteryMeterDrawable(res, true); + case BATTERY_METER_TEXT: + case BATTERY_METER_GONE: + return null; + default: + return new NormalBatteryMeterDrawable(res, false); } - mBatteryController.addStateChangedCallback(this); - getContext().getContentResolver().registerContentObserver( - Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); } @Override - public void onDetachedFromWindow() { - super.onDetachedFromWindow(); + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + + if (mMeterMode == BatteryMeterMode.BATTERY_METER_CIRCLE) { + height += (CircleBatteryMeterDrawable.STROKE_WITH / 3); + width = height; + } else if (mMeterMode == BatteryMeterMode.BATTERY_METER_TEXT) { + onSizeChanged(width, height, 0, 0); // Force a size changed event + } else if (mMeterMode.compareTo(BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) == 0) { + width = (int)(height * 1.2f); + } - getContext().unregisterReceiver(mTracker); - mBatteryController.removeStateChangedCallback(this); - getContext().getContentResolver().unregisterContentObserver(mSettingObserver); + setMeasuredDimension(width, height); } public void setBatteryController(BatteryController batteryController) { @@ -209,35 +302,85 @@ public class BatteryMeterView extends View implements DemoMode, invalidate(); } - private static float[] loadBoltPoints(Resources res) { - final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); - int maxX = 0, maxY = 0; - for (int i = 0; i < pts.length; i += 2) { - maxX = Math.max(maxX, pts[i]); - maxY = Math.max(maxY, pts[i + 1]); + public void setAnimationsEnabled(boolean enabled) { + if (mAnimationsEnabled != enabled) { + mAnimationsEnabled = enabled; + setLayerType(mAnimationsEnabled ? LAYER_TYPE_HARDWARE : LAYER_TYPE_NONE, null); + invalidate(); } - final float[] ptsF = new float[pts.length]; - for (int i = 0; i < pts.length; i += 2) { - ptsF[i] = (float)pts[i] / maxX; - ptsF[i + 1] = (float)pts[i + 1] / maxY; + } + + @Override + public void onBatteryStyleChanged(int style, int percentMode) { + boolean showInsidePercent = percentMode == BatteryController.PERCENTAGE_MODE_INSIDE; + BatteryMeterMode meterMode = BatteryMeterMode.BATTERY_METER_ICON_PORTRAIT; + + switch (style) { + case BatteryController.STYLE_CIRCLE: + meterMode = BatteryMeterMode.BATTERY_METER_CIRCLE; + break; + case BatteryController.STYLE_GONE: + meterMode = BatteryMeterMode.BATTERY_METER_GONE; + showInsidePercent = false; + break; + case BatteryController.STYLE_ICON_LANDSCAPE: + meterMode = BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE; + break; + case BatteryController.STYLE_TEXT: + meterMode = BatteryMeterMode.BATTERY_METER_TEXT; + showInsidePercent = false; + break; + default: + break; } - return ptsF; + + setMode(meterMode); + mShowPercent = showInsidePercent; + invalidate(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); mHeight = h; mWidth = w; - mWarningTextPaint.setTextSize(h * 0.75f); - mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; + if (mBatteryMeterDrawable != null) { + mBatteryMeterDrawable.onSizeChanged(w, h, oldw, oldh); + } } - private void updateShowPercent() { - mShowPercent = 0 != Settings.System.getInt(getContext().getContentResolver(), - SHOW_PERCENT_SETTING, 0); + public void setMode(BatteryMeterMode mode) { + if (mMeterMode == mode) { + return; + } + + mMeterMode = mode; + BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker; + if (mode == BatteryMeterMode.BATTERY_METER_GONE || + mode == BatteryMeterMode.BATTERY_METER_TEXT) { + setVisibility(View.GONE); + mBatteryMeterDrawable = null; + } else { + if (mBatteryMeterDrawable != null) { + mBatteryMeterDrawable.onDispose(); + } + mBatteryMeterDrawable = createBatteryMeterDrawable(mode); + if (mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_PORTRAIT || + mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) { + ((NormalBatteryMeterDrawable)mBatteryMeterDrawable).loadBoltPoints( + mContext.getResources()); + } + if (tracker.present) { + setVisibility(View.VISIBLE); + requestLayout(); + invalidate(); + } else { + setVisibility(View.GONE); + } + } } - private int getColorForLevel(int percent) { + public int getColorForLevel(int percent) { // If we are in power save mode, always use the normal color. if (mPowerSaveEnabled) { @@ -261,13 +404,11 @@ public class BatteryMeterView extends View implements DemoMode, } public void setDarkIntensity(float darkIntensity) { - int backgroundColor = getBackgroundColor(darkIntensity); - int fillColor = getFillColor(darkIntensity); - mIconTint = fillColor; - mFramePaint.setColor(backgroundColor); - mBoltPaint.setColor(fillColor); - mChargeColor = fillColor; - invalidate(); + if (mBatteryMeterDrawable != null) { + int backgroundColor = getBackgroundColor(darkIntensity); + int fillColor = getFillColor(darkIntensity); + mBatteryMeterDrawable.setDarkIntensity(backgroundColor, fillColor); + } } private int getBackgroundColor(float darkIntensity) { @@ -285,261 +426,574 @@ public class BatteryMeterView extends View implements DemoMode, } @Override - public void draw(Canvas c) { - BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker; - final int level = tracker.level; - - if (level == BatteryTracker.UNKNOWN_LEVEL) return; - - float drawFrac = (float) level / 100f; - final int pt = getPaddingTop(); - final int pl = getPaddingLeft(); - final int pr = getPaddingRight(); - final int pb = getPaddingBottom(); - final int height = mHeight - pt - pb; - final int width = mWidth - pl - pr; - - final int buttonHeight = (int) (height * mButtonHeightFraction); - - mFrame.set(0, 0, width, height); - mFrame.offset(pl, pt); - - // button-frame: area above the battery body - mButtonFrame.set( - mFrame.left + Math.round(width * 0.25f), - mFrame.top, - mFrame.right - Math.round(width * 0.25f), - mFrame.top + buttonHeight); - - mButtonFrame.top += mSubpixelSmoothingLeft; - mButtonFrame.left += mSubpixelSmoothingLeft; - mButtonFrame.right -= mSubpixelSmoothingRight; - - // frame: battery body area - mFrame.top += buttonHeight; - mFrame.left += mSubpixelSmoothingLeft; - mFrame.top += mSubpixelSmoothingLeft; - mFrame.right -= mSubpixelSmoothingRight; - mFrame.bottom -= mSubpixelSmoothingRight; - - // set the battery charging color - mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level)); - - if (level >= FULL) { - drawFrac = 1f; - } else if (level <= mCriticalLevel) { - drawFrac = 0f; + protected void onDraw(Canvas canvas) { + if (mBatteryMeterDrawable != null) { + BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker; + mBatteryMeterDrawable.onDraw(canvas, tracker); } + } - final float levelTop = drawFrac == 1f ? mButtonFrame.top - : (mFrame.top + (mFrame.height() * (1f - drawFrac))); - - // define the battery shape - mShapePath.reset(); - mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top); - mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); - mShapePath.lineTo(mButtonFrame.right, mFrame.top); - mShapePath.lineTo(mFrame.right, mFrame.top); - mShapePath.lineTo(mFrame.right, mFrame.bottom); - mShapePath.lineTo(mFrame.left, mFrame.bottom); - mShapePath.lineTo(mFrame.left, mFrame.top); - mShapePath.lineTo(mButtonFrame.left, mFrame.top); - mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); - - if (tracker.plugged) { - // define the bolt shape - final float bl = mFrame.left + mFrame.width() / 4.5f; - final float bt = mFrame.top + mFrame.height() / 6f; - final float br = mFrame.right - mFrame.width() / 7f; - final float bb = mFrame.bottom - mFrame.height() / 10f; - 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) { + @Override + public boolean hasOverlappingRendering() { + return false; + } + + @Override + public void dispatchDemoCommand(String command, Bundle args) { + if (getVisibility() == View.VISIBLE) { + if (!mDemoMode && command.equals(COMMAND_ENTER)) { + mDemoMode = true; + mDemoTracker.level = mTracker.level; + mDemoTracker.plugged = mTracker.plugged; + } else if (mDemoMode && command.equals(COMMAND_EXIT)) { + mDemoMode = false; + postInvalidate(); + } else if (mDemoMode && command.equals(COMMAND_BATTERY)) { + String level = args.getString("level"); + String plugged = args.getString("plugged"); + if (level != null) { + mDemoTracker.level = Math.min(Math.max(Integer.parseInt(level), 0), 100); + } + if (plugged != null) { + mDemoTracker.plugged = Boolean.parseBoolean(plugged); + } + postInvalidate(); + } + } + } + + protected interface BatteryMeterDrawable { + void onDraw(Canvas c, BatteryTracker tracker); + void onSizeChanged(int w, int h, int oldw, int oldh); + void onDispose(); + void setDarkIntensity(int backgroundColor, int fillColor); + } + + protected class NormalBatteryMeterDrawable implements BatteryMeterDrawable { + private static final boolean SINGLE_DIGIT_PERCENT = false; + private static final boolean SHOW_100_PERCENT = false; + + private boolean mDisposed; + + protected final boolean mHorizontal; + + private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint; + private float mTextHeight, mWarningTextHeight; + + private int mChargeColor; + private final float[] mBoltPoints; + private final Path mBoltPath = new Path(); + + private final RectF mFrame = new RectF(); + private final RectF mButtonFrame = new RectF(); + private final RectF mBoltFrame = new RectF(); + + public NormalBatteryMeterDrawable(Resources res, boolean horizontal) { + super(); + mHorizontal = horizontal; + mDisposed = false; + + mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mFramePaint.setColor(mFrameColor); + 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); + mTextPaint.setTypeface(font); + mTextPaint.setTextAlign(Paint.Align.CENTER); + + mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mWarningTextPaint.setColor(mColors[1]); + font = Typeface.create("sans-serif", Typeface.BOLD); + mWarningTextPaint.setTypeface(font); + mWarningTextPaint.setTextAlign(Paint.Align.CENTER); + + mChargeColor = getResources().getColor(R.color.batterymeter_charge_color); + + mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color)); + mBoltPoints = loadBoltPoints(res); + } + + @Override + public void onDraw(Canvas c, BatteryTracker tracker) { + if (mDisposed) return; + + final int level = tracker.level; + + if (level == BatteryTracker.UNKNOWN_LEVEL) return; + + float drawFrac = (float) level / 100f; + final int pt = getPaddingTop() + (mHorizontal ? (int)(mHeight * 0.12f) : 0); + final int pl = getPaddingLeft(); + final int pr = getPaddingRight(); + final int pb = getPaddingBottom() + (mHorizontal ? (int)(mHeight * 0.08f) : 0); + final int height = mHeight - pt - pb; + final int width = mWidth - pl - pr; + + final int buttonHeight = (int) ((mHorizontal ? width : height) * mButtonHeightFraction); + + mFrame.set(0, 0, width, height); + mFrame.offset(pl, pt); + + if (mHorizontal) { + mButtonFrame.set( + /*cover frame border of intersecting area*/ + width - buttonHeight - mFrame.left, + mFrame.top + Math.round(height * 0.25f), + mFrame.right, + mFrame.bottom - Math.round(height * 0.25f)); + + mButtonFrame.top += mSubpixelSmoothingLeft; + mButtonFrame.bottom -= mSubpixelSmoothingRight; + mButtonFrame.right -= mSubpixelSmoothingRight; + } else { + // button-frame: area above the battery body + mButtonFrame.set( + mFrame.left + Math.round(width * 0.25f), + mFrame.top, + mFrame.right - Math.round(width * 0.25f), + mFrame.top + buttonHeight); + + mButtonFrame.top += mSubpixelSmoothingLeft; + mButtonFrame.left += mSubpixelSmoothingLeft; + mButtonFrame.right -= mSubpixelSmoothingRight; + } + + // frame: battery body area + + if (mHorizontal) { + mFrame.right -= buttonHeight; + } else { + mFrame.top += buttonHeight; + } + mFrame.left += mSubpixelSmoothingLeft; + mFrame.top += mSubpixelSmoothingLeft; + mFrame.right -= mSubpixelSmoothingRight; + mFrame.bottom -= mSubpixelSmoothingRight; + + // set the battery charging color + mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level)); + + if (level >= FULL) { + drawFrac = 1f; + } else if (level <= mCriticalLevel) { + drawFrac = 0f; + } + + final float levelTop; + + if (drawFrac == 1f) { + if (mHorizontal) { + levelTop = mButtonFrame.right; + } else { + levelTop = mButtonFrame.top; + } + } else { + if (mHorizontal) { + levelTop = (mFrame.right - (mFrame.width() * (1f - drawFrac))); + } else { + levelTop = (mFrame.top + (mFrame.height() * (1f - drawFrac))); + } + } + + // define the battery shape + mShapePath.reset(); + mShapePath.moveTo(mButtonFrame.left, mButtonFrame.top); + if (mHorizontal) { + mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); + mShapePath.lineTo(mButtonFrame.right, mButtonFrame.bottom); + mShapePath.lineTo(mButtonFrame.left, mButtonFrame.bottom); + mShapePath.lineTo(mFrame.right, mFrame.bottom); + mShapePath.lineTo(mFrame.left, mFrame.bottom); + mShapePath.lineTo(mFrame.left, mFrame.top); + mShapePath.lineTo(mButtonFrame.left, mFrame.top); + mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); + } else { + mShapePath.lineTo(mButtonFrame.right, mButtonFrame.top); + mShapePath.lineTo(mButtonFrame.right, mFrame.top); + mShapePath.lineTo(mFrame.right, mFrame.top); + mShapePath.lineTo(mFrame.right, mFrame.bottom); + mShapePath.lineTo(mFrame.left, mFrame.bottom); + mShapePath.lineTo(mFrame.left, mFrame.top); + mShapePath.lineTo(mButtonFrame.left, mFrame.top); + mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top); + } + + if (tracker.plugged) { + // define the bolt shape + final float bl = mFrame.left + mFrame.width() / (mHorizontal ? 9f : 4.5f); + final float bt = mFrame.top + mFrame.height() / (mHorizontal ? 4.5f : 6f); + final float br = mFrame.right - mFrame.width() / (mHorizontal ? 6f : 7f); + final float bb = mFrame.bottom - mFrame.height() / (mHorizontal ? 7f : 10f); + 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[i] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); + mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), + mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); + } + + float boltPct = mHorizontal ? + (mBoltFrame.left - levelTop) / (mBoltFrame.left - mBoltFrame.right) : + (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top); + boltPct = Math.min(Math.max(boltPct, 0), 1); + if (boltPct <= BOLT_LEVEL_THRESHOLD) { + // draw the bolt if opaque + c.drawPath(mBoltPath, mBoltPaint); + } else { + // otherwise cut the bolt out of the overall shape + mShapePath.op(mBoltPath, Path.Op.DIFFERENCE); + } + } + + // compute percentage text + boolean pctOpaque = false; + float pctX = 0, pctY = 0; + String pctText = null; + if (!tracker.plugged && level > mCriticalLevel && mShowPercent) { + mTextPaint.setColor(getColorForLevel(level)); + final float full = mHorizontal ? 0.60f : 0.45f; + final float nofull = mHorizontal ? 0.75f : 0.6f; + final float single = mHorizontal ? 0.86f : 0.75f; + mTextPaint.setTextSize(height * + (SINGLE_DIGIT_PERCENT ? single + : (tracker.level == 100 ? full : nofull))); + mTextHeight = -mTextPaint.getFontMetrics().ascent; + pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); + pctX = mWidth * 0.5f; + pctY = (mHeight + mTextHeight) * 0.47f; + if (mHorizontal) { + pctOpaque = pctX > levelTop; + } else { + pctOpaque = levelTop > pctY; + } + if (!pctOpaque) { + mTextPath.reset(); + mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath); + // cut the percentage text out of the overall shape + mShapePath.op(mTextPath, Path.Op.DIFFERENCE); } - mBoltPath.lineTo( - mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), - mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); } - float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top); - boltPct = Math.min(Math.max(boltPct, 0), 1); - if (boltPct <= BOLT_LEVEL_THRESHOLD) { - // draw the bolt if opaque - c.drawPath(mBoltPath, mBoltPaint); + // draw the battery shape background + c.drawPath(mShapePath, mFramePaint); + + // draw the battery shape, clipped to charging level + if (mHorizontal) { + mFrame.right = levelTop; } else { - // otherwise cut the bolt out of the overall shape - mShapePath.op(mBoltPath, Path.Op.DIFFERENCE); + mFrame.top = levelTop; + } + mClipPath.reset(); + mClipPath.addRect(mFrame, Path.Direction.CCW); + mShapePath.op(mClipPath, Path.Op.INTERSECT); + c.drawPath(mShapePath, mBatteryPaint); + + if (!tracker.plugged) { + if (level <= mCriticalLevel) { + // draw the warning text + final float x = mWidth * 0.5f; + final float y = (mHeight + mWarningTextHeight) * 0.48f; + c.drawText(mWarningString, x, y, mWarningTextPaint); + } else if (pctOpaque) { + // draw the percentage text + c.drawText(pctText, pctX, pctY, mTextPaint); + } } } - // compute percentage text - boolean pctOpaque = false; - float pctX = 0, pctY = 0; - String pctText = null; - if (!tracker.plugged && level > mCriticalLevel && mShowPercent) { - mTextPaint.setColor(getColorForLevel(level)); - mTextPaint.setTextSize(height * - (SINGLE_DIGIT_PERCENT ? 0.75f - : (tracker.level == 100 ? 0.38f : 0.5f))); - mTextHeight = -mTextPaint.getFontMetrics().ascent; - pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); - pctX = mWidth * 0.5f; - pctY = (mHeight + mTextHeight) * 0.47f; - pctOpaque = levelTop > pctY; - if (!pctOpaque) { - mTextPath.reset(); - mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath); - // cut the percentage text out of the overall shape - mShapePath.op(mTextPath, Path.Op.DIFFERENCE); - } + @Override + public void onDispose() { + mDisposed = true; + } + + @Override + public void setDarkIntensity(int backgroundColor, int fillColor) { + mIconTint = fillColor; + mFramePaint.setColor(backgroundColor); + mBoltPaint.setColor(fillColor); + mChargeColor = fillColor; + invalidate(); + } + + @Override + public void onSizeChanged(int w, int h, int oldw, int oldh) { + mHeight = h; + mWidth = w; + mWarningTextPaint.setTextSize(h * 0.75f); + mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; } - // draw the battery shape background - c.drawPath(mShapePath, mFramePaint); - - // draw the battery shape, clipped to charging level - mFrame.top = levelTop; - mClipPath.reset(); - mClipPath.addRect(mFrame, Path.Direction.CCW); - mShapePath.op(mClipPath, Path.Op.INTERSECT); - c.drawPath(mShapePath, mBatteryPaint); - - if (!tracker.plugged) { - if (level <= mCriticalLevel) { - // draw the warning text - final float x = mWidth * 0.5f; - final float y = (mHeight + mWarningTextHeight) * 0.48f; - c.drawText(mWarningString, x, y, mWarningTextPaint); - } else if (pctOpaque) { - // draw the percentage text - c.drawText(pctText, pctX, pctY, mTextPaint); + private float[] loadBoltPoints(Resources res) { + final int[] pts = res.getIntArray((mHorizontal + ? R.array.batterymeter_inverted_bolt_points + : R.array.batterymeter_bolt_points)); + int maxX = 0, maxY = 0; + for (int i = 0; i < pts.length; i += 2) { + maxX = Math.max(maxX, pts[i]); + maxY = Math.max(maxY, pts[i + 1]); + } + final float[] ptsF = new float[pts.length]; + for (int i = 0; i < pts.length; i += 2) { + ptsF[i] = (float)pts[i] / maxX; + ptsF[i + 1] = (float)pts[i + 1] / maxY; } + return ptsF; } } - @Override - public boolean hasOverlappingRendering() { - return false; - } + protected class CircleBatteryMeterDrawable implements BatteryMeterDrawable { + private static final boolean SINGLE_DIGIT_PERCENT = false; + private static final boolean SHOW_100_PERCENT = false; - private boolean mDemoMode; - private BatteryTracker mDemoTracker = new BatteryTracker(); + private static final int FULL = 96; - @Override - public void dispatchDemoCommand(String command, Bundle args) { - if (!mDemoMode && command.equals(COMMAND_ENTER)) { - mDemoMode = true; - mDemoTracker.level = mTracker.level; - mDemoTracker.plugged = mTracker.plugged; - } else if (mDemoMode && command.equals(COMMAND_EXIT)) { - mDemoMode = false; - postInvalidate(); - } else if (mDemoMode && command.equals(COMMAND_BATTERY)) { - String level = args.getString("level"); - String plugged = args.getString("plugged"); - if (level != null) { - mDemoTracker.level = Math.min(Math.max(Integer.parseInt(level), 0), 100); - } - if (plugged != null) { - mDemoTracker.plugged = Boolean.parseBoolean(plugged); - } - postInvalidate(); + public static final float STROKE_WITH = 6.5f; + + private boolean mDisposed; + + private int mAnimOffset; + private boolean mIsAnimating; // stores charge-animation status to reliably + //remove callbacks + + private int mCircleSize; // draw size of circle + private RectF mRectLeft; // contains the precalculated rect used in drawArc(), + // derived from mCircleSize + private float mTextX, mTextY; // precalculated position for drawText() to appear centered + + private Paint mTextPaint; + private Paint mFrontPaint; + private Paint mBackPaint; + private Paint mBoltPaint; + private Paint mWarningTextPaint; + + private final RectF mBoltFrame = new RectF(); + + private int mChargeColor; + private final float[] mBoltPoints; + private final Path mBoltPath = new Path(); + + public CircleBatteryMeterDrawable(Resources res) { + super(); + mDisposed = false; + + mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD); + mTextPaint.setTypeface(font); + mTextPaint.setTextAlign(Paint.Align.CENTER); + + mFrontPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mFrontPaint.setStrokeCap(Paint.Cap.BUTT); + mFrontPaint.setDither(true); + mFrontPaint.setStrokeWidth(0); + mFrontPaint.setStyle(Paint.Style.STROKE); + + mBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mBackPaint.setColor(res.getColor(R.color.batterymeter_frame_color)); + mBackPaint.setStrokeCap(Paint.Cap.BUTT); + mBackPaint.setDither(true); + mBackPaint.setStrokeWidth(0); + mBackPaint.setStyle(Paint.Style.STROKE); + + mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mWarningTextPaint.setColor(mColors[1]); + font = Typeface.create("sans-serif", Typeface.BOLD); + mWarningTextPaint.setTypeface(font); + mWarningTextPaint.setTextAlign(Paint.Align.CENTER); + + mChargeColor = getResources().getColor(R.color.batterymeter_charge_color); + + mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mBoltPaint.setColor(res.getColor(R.color.batterymeter_bolt_color)); + mBoltPoints = loadBoltPoints(res); } - } - private final class BatteryTracker extends BroadcastReceiver { - public static final int UNKNOWN_LEVEL = -1; + @Override + public void onDraw(Canvas c, BatteryTracker tracker) { + if (mDisposed) return; - // current battery status - int level = UNKNOWN_LEVEL; - String percentStr; - int plugType; - boolean plugged; - int health; - int status; - String technology; - int voltage; - int temperature; - boolean testmode = false; + if (mRectLeft == null) { + initSizeBasedStuff(); + } + + drawCircle(c, tracker, mTextX, mRectLeft); + if (mAnimationsEnabled) { + updateChargeAnim(tracker); + } + } @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { - if (testmode && ! intent.getBooleanExtra("testmode", false)) return; + public void onDispose() { + mDisposed = true; + } - level = (int)(100f - * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) - / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); + @Override + public void setDarkIntensity(int backgroundColor, int fillColor) { + mIconTint = fillColor; + mBoltPaint.setColor(fillColor); + mChargeColor = fillColor; + invalidate(); + } - plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); - plugged = plugType != 0; - health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, - BatteryManager.BATTERY_HEALTH_UNKNOWN); - status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, - BatteryManager.BATTERY_STATUS_UNKNOWN); - technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY); - voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0); - temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0); + @Override + public void onSizeChanged(int w, int h, int oldw, int oldh) { + initSizeBasedStuff(); + } - setContentDescription( - context.getString(R.string.accessibility_battery_level, level)); - postInvalidate(); - } else if (action.equals(ACTION_LEVEL_TEST)) { - testmode = true; - post(new Runnable() { - int curLevel = 0; - int incr = 1; - int saveLevel = level; - int savePlugged = plugType; - Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED); - @Override - public void run() { - if (curLevel < 0) { - testmode = false; - dummy.putExtra("level", saveLevel); - dummy.putExtra("plugged", savePlugged); - dummy.putExtra("testmode", false); - } else { - dummy.putExtra("level", curLevel); - dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC - : 0); - dummy.putExtra("testmode", true); - } - getContext().sendBroadcast(dummy); + private float[] loadBoltPoints(Resources res) { + final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); + int maxX = 0, maxY = 0; + for (int i = 0; i < pts.length; i += 2) { + maxX = Math.max(maxX, pts[i]); + maxY = Math.max(maxY, pts[i + 1]); + } + final float[] ptsF = new float[pts.length]; + for (int i = 0; i < pts.length; i += 2) { + ptsF[i] = (float)pts[i] / maxX; + ptsF[i + 1] = (float)pts[i + 1] / maxY; + } + return ptsF; + } - if (!testmode) return; + private void drawCircle(Canvas canvas, BatteryTracker tracker, + float textX, RectF drawRect) { + boolean unknownStatus = tracker.status == BatteryManager.BATTERY_STATUS_UNKNOWN; + int level = tracker.level; + Paint paint; - curLevel += incr; - if (curLevel == 100) { - incr *= -1; - } - postDelayed(this, 200); - } - }); + if (unknownStatus) { + paint = mBackPaint; + level = 100; // Draw all the circle; + } else { + paint = mFrontPaint; + paint.setColor(getColorForLevel(level)); + if (tracker.status == BatteryManager.BATTERY_STATUS_FULL) { + level = 100; + } + } + + // draw thin gray ring first + canvas.drawArc(drawRect, 270, 360, false, mBackPaint); + if (level != 0) { + // draw colored arc representing charge level + canvas.drawArc(drawRect, 270 + mAnimOffset, 3.6f * level, false, paint); + } + // if chosen by options, draw percentage text in the middle + // always skip percentage when 100, so layout doesnt break + if (unknownStatus) { + mTextPaint.setColor(paint.getColor()); + canvas.drawText("?", textX, mTextY, mTextPaint); + + } else if (tracker.plugged) { + canvas.drawPath(mBoltPath, mBoltPaint); + } else { + if (level > mCriticalLevel + && (mShowPercent && !(tracker.level == 100 && !SHOW_100_PERCENT))) { + // draw the percentage text + String pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level/10) : level); + mTextPaint.setColor(paint.getColor()); + canvas.drawText(pctText, textX, mTextY, mTextPaint); + } else if (level <= mCriticalLevel) { + // draw the warning text + canvas.drawText(mWarningString, textX, mTextY, mWarningTextPaint); + } } } - } - private final class SettingObserver extends ContentObserver { - public SettingObserver() { - super(new Handler()); + /** + * updates the animation counter + * cares for timed callbacks to continue animation cycles + * uses mInvalidate for delayed invalidate() callbacks + */ + private void updateChargeAnim(BatteryTracker tracker) { + // Stop animation when battery is full or after the meter + // rotated back to 0 after unplugging. + if (!tracker.shouldIndicateCharging() + || tracker.status == BatteryManager.BATTERY_STATUS_FULL + || tracker.level == 0) { + if (mIsAnimating) { + mIsAnimating = false; + mAnimOffset = 0; + } + return; + } + + mIsAnimating = true; + + if (mAnimOffset > 360) { + mAnimOffset = 0; + } else { + mAnimOffset += 3; + } + + postInvalidateDelayed(50); } - @Override - public void onChange(boolean selfChange, Uri uri) { - super.onChange(selfChange, uri); - updateShowPercent(); - postInvalidate(); + /** + * initializes all size dependent variables + * sets stroke width and text size of all involved paints + * YES! i think the method name is appropriate + */ + private void initSizeBasedStuff() { + mCircleSize = Math.min(getMeasuredWidth(), getMeasuredHeight()); + mTextPaint.setTextSize(mCircleSize / 2f); + mWarningTextPaint.setTextSize(mCircleSize / 2f); + + float strokeWidth = mCircleSize / STROKE_WITH; + mFrontPaint.setStrokeWidth(strokeWidth); + mBackPaint.setStrokeWidth(strokeWidth); + + // calculate rectangle for drawArc calls + int pLeft = getPaddingLeft(); + mRectLeft = new RectF(pLeft + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize + - strokeWidth / 2.0f + pLeft, mCircleSize - strokeWidth / 2.0f); + + // calculate Y position for text + Rect bounds = new Rect(); + mTextPaint.getTextBounds("99", 0, "99".length(), bounds); + mTextX = mCircleSize / 2.0f + getPaddingLeft(); + // the +1dp at end of formula balances out rounding issues.works out on all resolutions + mTextY = mCircleSize / 2.0f + (bounds.bottom - bounds.top) / 2.0f + - strokeWidth / 2.0f + getResources().getDisplayMetrics().density; + + // draw the bolt + final float bl = (int) (mRectLeft.left + mRectLeft.width() / 3.2f); + final float bt = (int) (mRectLeft.top + mRectLeft.height() / 4f); + final float br = (int) (mRectLeft.right - mRectLeft.width() / 5.2f); + final float bb = (int) (mRectLeft.bottom - mRectLeft.height() / 8f); + 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()); + } } } - } 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 b93fc76..db378d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -29,6 +29,7 @@ import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; +import com.android.systemui.BatteryLevelTextView; import com.android.systemui.BatteryMeterView; import com.android.systemui.R; import com.android.systemui.statusbar.policy.BatteryController; @@ -36,23 +37,18 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; -import java.text.NumberFormat; - /** * The header group on Keyguard. */ -public class KeyguardStatusBarView extends RelativeLayout - implements BatteryController.BatteryStateChangeCallback { +public class KeyguardStatusBarView extends RelativeLayout { - private boolean mBatteryCharging; private boolean mKeyguardUserSwitcherShowing; - private boolean mBatteryListening; private TextView mCarrierLabel; private View mSystemIconsSuperContainer; private MultiUserSwitch mMultiUserSwitch; private ImageView mMultiUserAvatar; - private TextView mBatteryLevel; + private BatteryLevelTextView mBatteryLevel; private BatteryController mBatteryController; private KeyguardUserSwitcher mKeyguardUserSwitcher; @@ -70,12 +66,13 @@ public class KeyguardStatusBarView extends RelativeLayout mSystemIconsSuperContainer = findViewById(R.id.system_icons_super_container); mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch); mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar); - mBatteryLevel = (TextView) findViewById(R.id.battery_level); + mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text); mCarrierLabel = (TextView) findViewById(R.id.keyguard_carrier_text); loadDimens(); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(), android.R.interpolator.fast_out_slow_in); updateUserSwitcher(); + updateVisibilities(); } @Override @@ -86,8 +83,6 @@ public class KeyguardStatusBarView extends RelativeLayout mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize( com.android.internal.R.dimen.text_size_small_material)); - mBatteryLevel.setTextSize(TypedValue.COMPLEX_UNIT_PX, - getResources().getDimensionPixelSize(R.dimen.battery_level_text_size)); } private void loadDimens() { @@ -104,7 +99,7 @@ public class KeyguardStatusBarView extends RelativeLayout } else if (mMultiUserSwitch.getParent() == this && mKeyguardUserSwitcherShowing) { removeView(mMultiUserSwitch); } - mBatteryLevel.setVisibility(mBatteryCharging ? View.VISIBLE : View.GONE); + mBatteryLevel.setVisibility(View.VISIBLE); } private void updateSystemIconsLayoutParams() { @@ -117,18 +112,6 @@ public class KeyguardStatusBarView extends RelativeLayout } } - public void setListening(boolean listening) { - if (listening == mBatteryListening) { - return; - } - mBatteryListening = listening; - if (mBatteryListening) { - mBatteryController.addStateChangedCallback(this); - } else { - mBatteryController.removeStateChangedCallback(this); - } - } - private void updateUserSwitcher() { boolean keyguardSwitcherAvailable = mKeyguardUserSwitcher != null; mMultiUserSwitch.setClickable(keyguardSwitcherAvailable); @@ -139,6 +122,7 @@ public class KeyguardStatusBarView extends RelativeLayout public void setBatteryController(BatteryController batteryController) { mBatteryController = batteryController; ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController); + mBatteryLevel.setBatteryController(batteryController); } public void setUserSwitcherController(UserSwitcherController controller) { @@ -154,22 +138,6 @@ public class KeyguardStatusBarView extends RelativeLayout }); } - @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { - String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); - mBatteryLevel.setText(percentage); - boolean changed = mBatteryCharging != charging; - mBatteryCharging = charging; - if (changed) { - updateVisibilities(); - } - } - - @Override - public void onPowerSaveChanged() { - // could not care less - } - public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) { mKeyguardUserSwitcher = keyguardUserSwitcher; mMultiUserSwitch.setKeyguardUserSwitcher(keyguardUserSwitcher); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index ed27eb9..76a9b0c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1864,7 +1864,6 @@ public class NotificationPanelView extends PanelView implements private void setListening(boolean listening) { mHeader.setListening(listening); - mKeyguardStatusBar.setListening(listening); mQsPanel.setListening(listening); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index ab036bc..a9bcd75 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -121,6 +121,7 @@ import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.BatteryMeterView; +import com.android.systemui.BatteryLevelTextView; import com.android.systemui.DemoMode; import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; @@ -315,6 +316,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private DozeServiceHost mDozeServiceHost; private boolean mScreenOnComingFromTouch; private PointF mScreenOnTouchLocation; + private BatteryMeterView mBatteryView; + private BatteryLevelTextView mBatteryTextView; int mPixelFormat; Object mQueueLock = new Object(); @@ -991,7 +994,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Other icons mLocationController = new LocationControllerImpl(mContext, mHandlerThread.getLooper()); // will post a notification - mBatteryController = new BatteryController(mContext); + mBatteryController = new BatteryController(mContext, mHandler); mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() { @Override public void onPowerSaveChanged() { @@ -1004,6 +1007,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { // noop } + @Override + public void onBatteryStyleChanged(int style, int percentMode) { + // noop + } }); mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper()); mHotspotController = new HotspotControllerImpl(mContext); @@ -1086,8 +1093,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mUserInfoController.reloadUserInfo(); mHeader.setBatteryController(mBatteryController); - ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController( - mBatteryController); + BatteryMeterView batteryMeterView = + ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)); + batteryMeterView.setBatteryController(mBatteryController); + batteryMeterView.setAnimationsEnabled(false); + ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.battery_level_text)) + .setBatteryController(mBatteryController); mKeyguardStatusBar.setBatteryController(mBatteryController); mHeader.setNextAlarmController(mNextAlarmController); mHeader.setWeatherController(mWeatherController); @@ -3377,6 +3388,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mSecurityController != null) { mSecurityController.onUserSwitched(mCurrentUserId); } + if (mBatteryController != null) { + mBatteryController.setUserId(mCurrentUserId); + } } private void resetUserSetupObserver() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index 0cc928f..6538ba6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -55,6 +55,7 @@ import android.widget.TextView; import android.widget.Toast; import com.android.keyguard.KeyguardStatusView; +import com.android.systemui.BatteryLevelTextView; import com.android.systemui.BatteryMeterView; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; @@ -71,12 +72,13 @@ import com.android.systemui.tuner.TunerService; import java.text.NumberFormat; +import cyanogenmod.providers.CMSettings; + /** * The view to manage the header area in the expanded status bar. */ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener, - BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback, - EmergencyListener, WeatherController.Callback { + NextAlarmController.NextAlarmChangeCallback, WeatherController.Callback, EmergencyListener { private boolean mExpanded; private boolean mListening; @@ -101,7 +103,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private Switch mQsDetailHeaderSwitch; private ImageView mQsDetailHeaderProgress; private TextView mEmergencyCallsOnly; - private TextView mBatteryLevel; + private BatteryLevelTextView mBatteryLevel; private TextView mAlarmStatus; private TextView mWeatherLine1, mWeatherLine2; @@ -149,6 +151,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private boolean mDetailTransitioning; private SettingsObserver mSettingsObserver; private boolean mShowWeather; + private boolean mShowBatteryTextExpanded; public StatusBarHeaderView(Context context, AttributeSet attrs) { super(context, attrs); @@ -179,7 +182,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle); mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress); mEmergencyCallsOnly = (TextView) findViewById(R.id.header_emergency_calls_only); - mBatteryLevel = (TextView) findViewById(R.id.battery_level); + mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text); mAlarmStatus = (TextView) findViewById(R.id.alarm_status); mAlarmStatus.setOnClickListener(this); mSignalCluster = findViewById(R.id.signal_cluster); @@ -234,7 +237,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - FontSizeUtils.updateFontSize(mBatteryLevel, R.dimen.battery_level_text_size); FontSizeUtils.updateFontSize(mEmergencyCallsOnly, R.dimen.qs_emergency_calls_only_text_size); FontSizeUtils.updateFontSize(mDateCollapsed, R.dimen.qs_date_collapsed_size); @@ -305,6 +307,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL public void setBatteryController(BatteryController batteryController) { mBatteryController = batteryController; ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController); + mBatteryLevel.setBatteryController(batteryController); } public void setNextAlarmController(NextAlarmController nextAlarmController) { @@ -366,12 +369,13 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE); mSettingsContainer.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE); mWeatherContainer.setVisibility(mExpanded && mShowWeather ? View.VISIBLE : View.GONE); - mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE); + mQsDetailHeader.setVisibility(mExpanded && mShowingDetail ? View.VISIBLE : View.INVISIBLE); if (mSignalCluster != null) { updateSignalClusterDetachment(); } mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE); - mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE); + mBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded); + mBatteryLevel.setVisibility(View.VISIBLE); mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility( TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE); } @@ -407,11 +411,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private void updateListeners() { if (mListening) { mSettingsObserver.observe(); - mBatteryController.addStateChangedCallback(this); mNextAlarmController.addStateChangedCallback(this); mWeatherController.addCallback(this); } else { - mBatteryController.removeStateChangedCallback(this); mNextAlarmController.removeStateChangedCallback(this); mWeatherController.removeCallback(this); mSettingsObserver.unobserve(); @@ -443,17 +445,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL } @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { - String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); - mBatteryLevel.setText(percentage); - } - - @Override - public void onPowerSaveChanged() { - // could not care less - } - - @Override public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) { mNextAlarm = nextAlarm; if (nextAlarm != null) { @@ -768,6 +759,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL float batteryX; float batteryY; float batteryLevelAlpha; + float batteryLevelExpandedAlpha; float settingsAlpha; float settingsTranslation; float signalClusterAlpha; @@ -800,6 +792,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL dateExpandedAlpha = v1.dateExpandedAlpha * (1 - t3) + v2.dateExpandedAlpha * t3; dateCollapsedAlpha = v1.dateCollapsedAlpha * (1 - t3) + v2.dateCollapsedAlpha * t3; alarmStatusAlpha = v1.alarmStatusAlpha * (1 - t3) + v2.alarmStatusAlpha * t3; + batteryLevelExpandedAlpha = + v1.batteryLevelExpandedAlpha * (1 - t3) + v2.batteryLevelExpandedAlpha * t3; } } @@ -925,6 +919,10 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.STATUS_BAR_SHOW_WEATHER), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(CMSettings.System.getUriFor( + CMSettings.System.STATUS_BAR_BATTERY_STYLE), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(CMSettings.System.getUriFor( + CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT), false, this, UserHandle.USER_ALL); update(); } @@ -940,9 +938,26 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL public void update() { ContentResolver resolver = mContext.getContentResolver(); + int currentUserId = ActivityManager.getCurrentUser(); + int batteryStyle = CMSettings.System.getIntForUser(resolver, + CMSettings.System.STATUS_BAR_BATTERY_STYLE, 0, currentUserId); + boolean showExpandedBatteryPercentage = CMSettings.System.getIntForUser(resolver, + CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, 0, currentUserId) == 0; + + switch (batteryStyle) { + case 4: //BATTERY_METER_GONE + case 6: //BATTERY_METER_TEXT + showExpandedBatteryPercentage = false; + break; + default: + break; + } + + mShowBatteryTextExpanded = showExpandedBatteryPercentage; mShowWeather = Settings.System.getInt( resolver, Settings.System.STATUS_BAR_SHOW_WEATHER, 1) == 1; updateVisibilities(); + requestCaptureValues(); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index d1b69ab..a154544 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -17,10 +17,14 @@ package com.android.systemui.statusbar.policy; import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.database.ContentObserver; +import android.net.Uri; import android.os.BatteryManager; +import android.os.Handler; import android.os.PowerManager; import android.util.Log; @@ -28,10 +32,22 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import cyanogenmod.providers.CMSettings; + public class BatteryController extends BroadcastReceiver { private static final String TAG = "BatteryController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + public static final int STYLE_ICON_PORTRAIT = 0; + public static final int STYLE_CIRCLE = 2; + public static final int STYLE_GONE = 4; + public static final int STYLE_ICON_LANDSCAPE = 5; + public static final int STYLE_TEXT = 6; + + public static final int PERCENTAGE_MODE_OFF = 0; + public static final int PERCENTAGE_MODE_INSIDE = 1; + public static final int PERCENTAGE_MODE_OUTSIDE = 2; + private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>(); private final PowerManager mPowerManager; @@ -41,7 +57,12 @@ public class BatteryController extends BroadcastReceiver { private boolean mCharged; private boolean mPowerSave; - public BatteryController(Context context) { + private int mStyle; + private int mPercentMode; + private int mUserId; + private SettingsObserver mObserver; + + public BatteryController(Context context, Handler handler) { mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); IntentFilter filter = new IntentFilter(); @@ -51,6 +72,14 @@ public class BatteryController extends BroadcastReceiver { context.registerReceiver(this, filter); updatePowerSave(); + + mObserver = new SettingsObserver(context, handler); + mObserver.observe(); + } + + public void setUserId(int userId) { + mUserId = userId; + mObserver.observe(); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -65,6 +94,7 @@ public class BatteryController extends BroadcastReceiver { public void addStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.add(cb); cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); + cb.onBatteryStyleChanged(mStyle, mPercentMode); } public void removeStateChangedCallback(BatteryStateChangeCallback cb) { @@ -121,8 +151,56 @@ public class BatteryController extends BroadcastReceiver { } } + private void fireSettingsChanged() { + final int N = mChangeCallbacks.size(); + for (int i = 0; i < N; i++) { + mChangeCallbacks.get(i).onBatteryStyleChanged(mStyle, mPercentMode); + } + } + public interface BatteryStateChangeCallback { void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging); void onPowerSaveChanged(); + void onBatteryStyleChanged(int style, int percentMode); } + + private final class SettingsObserver extends ContentObserver { + private ContentResolver mResolver; + private boolean mRegistered; + + private final Uri STYLE_URI = + CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_BATTERY_STYLE); + private final Uri PERCENT_URI = + CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT); + + public SettingsObserver(Context context, Handler handler) { + super(handler); + mResolver = context.getContentResolver(); + } + + public void observe() { + if (mRegistered) { + mResolver.unregisterContentObserver(this); + } + mResolver.registerContentObserver(STYLE_URI, false, this, mUserId); + mResolver.registerContentObserver(PERCENT_URI, false, this, mUserId); + mRegistered = true; + + update(); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + update(); + } + + private void update() { + mStyle = CMSettings.System.getIntForUser(mResolver, + CMSettings.System.STATUS_BAR_BATTERY_STYLE, 0, mUserId); + mPercentMode = CMSettings.System.getIntForUser(mResolver, + CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, 0, mUserId); + + fireSettingsChanged(); + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java index 71b5de5..1ff5cef 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java @@ -15,8 +15,6 @@ */ package com.android.systemui.tuner; -import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING; - import android.app.AlertDialog; import android.app.FragmentTransaction; import android.content.DialogInterface; @@ -105,8 +103,6 @@ public class TunerFragment extends PreferenceFragment { public void onResume() { super.onResume(); updateBatteryPct(); - getContext().getContentResolver().registerContentObserver( - System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); registerPrefs(getPreferenceScreen()); MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true); @@ -172,8 +168,6 @@ public class TunerFragment extends PreferenceFragment { private void updateBatteryPct() { mBatteryPct.setOnPreferenceChangeListener(null); - mBatteryPct.setChecked(System.getInt(getContext().getContentResolver(), - SHOW_PERCENT_SETTING, 0) != 0); mBatteryPct.setOnPreferenceChangeListener(mBatteryPctChange); } @@ -194,7 +188,6 @@ public class TunerFragment extends PreferenceFragment { public boolean onPreferenceChange(Preference preference, Object newValue) { final boolean v = (Boolean) newValue; MetricsLogger.action(getContext(), MetricsLogger.TUNER_BATTERY_PERCENTAGE, v); - System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0); return true; } }; diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java index 50234b2..500a828 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java @@ -135,7 +135,6 @@ public class TunerService extends SystemUI { public void clearAll() { // A couple special cases. Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null); - Settings.System.putString(mContentResolver, BatteryMeterView.SHOW_PERCENT_SETTING, null); Intent intent = new Intent(DemoMode.ACTION_DEMO); intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT); mContext.sendBroadcast(intent); |