In split-screen the light status bar flag for one side of the status bar can be different from the other side. SYSTEM_UI_FLAG_LIGHT_STATUS_BAR is now reported for both the fullscreen stack and docked stack, but not anymore in the "default" SysUI visibility field when reporting a visibility change to SystemUI. The change also reports the docked stack and the fullscreen stack bounds, so SystemUI can guard tinting the icons on whether the icon is one of the areas. When calculating the light status bar flag in PWM, we keep track of the top fullscreen opaque window state for the docked and fullscreen stack separately. Bug: 24365214 Change-Id: Id2240a86d75bf96e0138ec7652a4793859f56e3c
553 lines
20 KiB
Java
Executable File
553 lines
20 KiB
Java
Executable File
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.systemui;
|
|
|
|
import android.animation.ArgbEvaluator;
|
|
import android.annotation.Nullable;
|
|
import android.content.Context;
|
|
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.ColorFilter;
|
|
import android.graphics.Paint;
|
|
import android.graphics.Path;
|
|
import android.graphics.RectF;
|
|
import android.graphics.Typeface;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.net.Uri;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.provider.Settings;
|
|
|
|
import com.android.systemui.statusbar.policy.BatteryController;
|
|
|
|
public class BatteryMeterDrawable extends Drawable implements DemoMode,
|
|
BatteryController.BatteryStateChangeCallback {
|
|
|
|
private static final float ASPECT_RATIO = 9.5f / 14.5f;
|
|
public static final String TAG = BatteryMeterDrawable.class.getSimpleName();
|
|
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;
|
|
|
|
private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction
|
|
|
|
private final int[] mColors;
|
|
private final int mIntrinsicWidth;
|
|
private final int mIntrinsicHeight;
|
|
|
|
private boolean mShowPercent;
|
|
private float mButtonHeightFraction;
|
|
private float mSubpixelSmoothingLeft;
|
|
private float mSubpixelSmoothingRight;
|
|
private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint,
|
|
mPlusPaint;
|
|
private float mTextHeight, mWarningTextHeight;
|
|
private int mIconTint = Color.WHITE;
|
|
private float mOldDarkIntensity = 0f;
|
|
|
|
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 float[] mPlusPoints;
|
|
private final Path mPlusPath = new Path();
|
|
|
|
private final RectF mFrame = new RectF();
|
|
private final RectF mButtonFrame = new RectF();
|
|
private final RectF mBoltFrame = new RectF();
|
|
private final RectF mPlusFrame = new RectF();
|
|
|
|
private final Path mShapePath = new Path();
|
|
private final Path mClipPath = new Path();
|
|
private final Path mTextPath = new Path();
|
|
|
|
private BatteryController mBatteryController;
|
|
private boolean mPowerSaveEnabled;
|
|
|
|
private int mDarkModeBackgroundColor;
|
|
private int mDarkModeFillColor;
|
|
|
|
private int mLightModeBackgroundColor;
|
|
private int mLightModeFillColor;
|
|
|
|
private final SettingObserver mSettingObserver = new SettingObserver();
|
|
|
|
private final Context mContext;
|
|
private final Handler mHandler;
|
|
|
|
private int mLevel = -1;
|
|
private boolean mPluggedIn;
|
|
private boolean mListening;
|
|
|
|
public BatteryMeterDrawable(Context context, Handler handler, int frameColor) {
|
|
mContext = context;
|
|
mHandler = handler;
|
|
final Resources res = context.getResources();
|
|
TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
|
|
TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
|
|
|
|
final int N = levels.length();
|
|
mColors = new int[2*N];
|
|
for (int i=0; i<N; i++) {
|
|
mColors[2*i] = levels.getInt(i, 0);
|
|
mColors[2*i+1] = colors.getColor(i, 0);
|
|
}
|
|
levels.recycle();
|
|
colors.recycle();
|
|
updateShowPercent();
|
|
mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
|
|
mCriticalLevel = mContext.getResources().getInteger(
|
|
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
|
|
mButtonHeightFraction = context.getResources().getFraction(
|
|
R.fraction.battery_button_height_fraction, 1, 1);
|
|
mSubpixelSmoothingLeft = context.getResources().getFraction(
|
|
R.fraction.battery_subpixel_smoothing_left, 1, 1);
|
|
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);
|
|
|
|
mPlusPaint = new Paint(mBoltPaint);
|
|
mPlusPoints = loadPlusPoints(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);
|
|
|
|
mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width);
|
|
mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height);
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicHeight() {
|
|
return mIntrinsicHeight;
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicWidth() {
|
|
return mIntrinsicWidth;
|
|
}
|
|
|
|
public void startListening() {
|
|
mListening = true;
|
|
mContext.getContentResolver().registerContentObserver(
|
|
Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
|
|
updateShowPercent();
|
|
if (mDemoMode) return;
|
|
mBatteryController.addStateChangedCallback(this);
|
|
}
|
|
|
|
public void stopListening() {
|
|
mListening = false;
|
|
mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
|
|
if (mDemoMode) return;
|
|
mBatteryController.removeStateChangedCallback(this);
|
|
}
|
|
|
|
public void disableShowPercent() {
|
|
mShowPercent = false;
|
|
postInvalidate();
|
|
}
|
|
|
|
private void postInvalidate() {
|
|
mHandler.post(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
invalidateSelf();
|
|
}
|
|
});
|
|
}
|
|
|
|
public void setBatteryController(BatteryController batteryController) {
|
|
mBatteryController = batteryController;
|
|
mPowerSaveEnabled = mBatteryController.isPowerSave();
|
|
}
|
|
|
|
@Override
|
|
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
|
|
mLevel = level;
|
|
mPluggedIn = pluggedIn;
|
|
|
|
postInvalidate();
|
|
}
|
|
|
|
@Override
|
|
public void onPowerSaveChanged(boolean isPowerSave) {
|
|
mPowerSaveEnabled = isPowerSave;
|
|
invalidateSelf();
|
|
}
|
|
|
|
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]);
|
|
}
|
|
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;
|
|
}
|
|
|
|
private static float[] loadPlusPoints(Resources res) {
|
|
final int[] pts = res.getIntArray(R.array.batterymeter_plus_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 void setBounds(int left, int top, int right, int bottom) {
|
|
super.setBounds(left, top, right, bottom);
|
|
mHeight = bottom - top;
|
|
mWidth = right - left;
|
|
mWarningTextPaint.setTextSize(mHeight * 0.75f);
|
|
mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
|
|
}
|
|
|
|
private void updateShowPercent() {
|
|
mShowPercent = 0 != Settings.System.getInt(mContext.getContentResolver(),
|
|
SHOW_PERCENT_SETTING, 0);
|
|
}
|
|
|
|
private int getColorForLevel(int percent) {
|
|
|
|
// If we are in power save mode, always use the normal color.
|
|
if (mPowerSaveEnabled) {
|
|
return mColors[mColors.length-1];
|
|
}
|
|
int thresh, color = 0;
|
|
for (int i=0; i<mColors.length; i+=2) {
|
|
thresh = mColors[i];
|
|
color = mColors[i+1];
|
|
if (percent <= thresh) {
|
|
|
|
// Respect tinting for "normal" level
|
|
if (i == mColors.length-2) {
|
|
return mIconTint;
|
|
} else {
|
|
return color;
|
|
}
|
|
}
|
|
}
|
|
return color;
|
|
}
|
|
|
|
public void setDarkIntensity(float darkIntensity) {
|
|
if (darkIntensity == mOldDarkIntensity) {
|
|
return;
|
|
}
|
|
int backgroundColor = getBackgroundColor(darkIntensity);
|
|
int fillColor = getFillColor(darkIntensity);
|
|
mIconTint = fillColor;
|
|
mFramePaint.setColor(backgroundColor);
|
|
mBoltPaint.setColor(fillColor);
|
|
mChargeColor = fillColor;
|
|
invalidateSelf();
|
|
mOldDarkIntensity = darkIntensity;
|
|
}
|
|
|
|
private int getBackgroundColor(float darkIntensity) {
|
|
return getColorForDarkIntensity(
|
|
darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor);
|
|
}
|
|
|
|
private int getFillColor(float darkIntensity) {
|
|
return getColorForDarkIntensity(
|
|
darkIntensity, mLightModeFillColor, mDarkModeFillColor);
|
|
}
|
|
|
|
private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
|
|
return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
|
|
}
|
|
|
|
@Override
|
|
public void draw(Canvas c) {
|
|
final int level = mLevel;
|
|
|
|
if (level == -1) return;
|
|
|
|
float drawFrac = (float) level / 100f;
|
|
final int height = mHeight;
|
|
final int width = (int) (ASPECT_RATIO * mHeight);
|
|
int px = (mWidth - width) / 2;
|
|
|
|
final int buttonHeight = (int) (height * mButtonHeightFraction);
|
|
|
|
mFrame.set(0, 0, width, height);
|
|
mFrame.offset(px, 0);
|
|
|
|
// 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(mPluggedIn ? mChargeColor : getColorForLevel(level));
|
|
|
|
if (level >= FULL) {
|
|
drawFrac = 1f;
|
|
} else if (level <= mCriticalLevel) {
|
|
drawFrac = 0f;
|
|
}
|
|
|
|
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 (mPluggedIn) {
|
|
// define the bolt shape
|
|
final float bl = mFrame.left + mFrame.width() / 4f;
|
|
final float bt = mFrame.top + mFrame.height() / 6f;
|
|
final float br = mFrame.right - mFrame.width() / 4f;
|
|
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) {
|
|
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());
|
|
}
|
|
|
|
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);
|
|
} else {
|
|
// otherwise cut the bolt out of the overall shape
|
|
mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
|
|
}
|
|
} else if (mPowerSaveEnabled) {
|
|
// define the plus shape
|
|
final float pw = mFrame.width() * 2 / 3;
|
|
final float pl = mFrame.left + (mFrame.width() - pw) / 2;
|
|
final float pt = mFrame.top + (mFrame.height() - pw) / 2;
|
|
final float pr = mFrame.right - (mFrame.width() - pw) / 2;
|
|
final float pb = mFrame.bottom - (mFrame.height() - pw) / 2;
|
|
if (mPlusFrame.left != pl || mPlusFrame.top != pt
|
|
|| mPlusFrame.right != pr || mPlusFrame.bottom != pb) {
|
|
mPlusFrame.set(pl, pt, pr, pb);
|
|
mPlusPath.reset();
|
|
mPlusPath.moveTo(
|
|
mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
|
|
mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
|
|
for (int i = 2; i < mPlusPoints.length; i += 2) {
|
|
mPlusPath.lineTo(
|
|
mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(),
|
|
mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height());
|
|
}
|
|
mPlusPath.lineTo(
|
|
mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
|
|
mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
|
|
}
|
|
|
|
float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top);
|
|
boltPct = Math.min(Math.max(boltPct, 0), 1);
|
|
if (boltPct <= BOLT_LEVEL_THRESHOLD) {
|
|
// draw the bolt if opaque
|
|
c.drawPath(mPlusPath, mPlusPaint);
|
|
} else {
|
|
// otherwise cut the bolt out of the overall shape
|
|
mShapePath.op(mPlusPath, Path.Op.DIFFERENCE);
|
|
}
|
|
}
|
|
|
|
// compute percentage text
|
|
boolean pctOpaque = false;
|
|
float pctX = 0, pctY = 0;
|
|
String pctText = null;
|
|
if (!mPluggedIn && level > mCriticalLevel && mShowPercent) {
|
|
mTextPaint.setColor(getColorForLevel(level));
|
|
mTextPaint.setTextSize(height *
|
|
(SINGLE_DIGIT_PERCENT ? 0.75f
|
|
: (mLevel == 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);
|
|
}
|
|
}
|
|
|
|
// 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 (!mPluggedIn) {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Some stuff required by Drawable.
|
|
@Override
|
|
public void setAlpha(int alpha) {
|
|
}
|
|
|
|
@Override
|
|
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity() {
|
|
return 0;
|
|
}
|
|
|
|
private boolean mDemoMode;
|
|
|
|
@Override
|
|
public void dispatchDemoCommand(String command, Bundle args) {
|
|
if (!mDemoMode && command.equals(COMMAND_ENTER)) {
|
|
mBatteryController.removeStateChangedCallback(this);
|
|
mDemoMode = true;
|
|
if (mListening) {
|
|
mBatteryController.removeStateChangedCallback(this);
|
|
}
|
|
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
|
|
mDemoMode = false;
|
|
postInvalidate();
|
|
if (mListening) {
|
|
mBatteryController.addStateChangedCallback(this);
|
|
}
|
|
} else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
|
|
String level = args.getString("level");
|
|
String plugged = args.getString("plugged");
|
|
if (level != null) {
|
|
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
|
|
}
|
|
if (plugged != null) {
|
|
mPluggedIn = Boolean.parseBoolean(plugged);
|
|
}
|
|
postInvalidate();
|
|
}
|
|
}
|
|
|
|
private final class SettingObserver extends ContentObserver {
|
|
public SettingObserver() {
|
|
super(new Handler());
|
|
}
|
|
|
|
@Override
|
|
public void onChange(boolean selfChange, Uri uri) {
|
|
super.onChange(selfChange, uri);
|
|
updateShowPercent();
|
|
postInvalidate();
|
|
}
|
|
}
|
|
|
|
}
|