From dfaf3bdeeb21c8421074c70d82642612bcdd8e98 Mon Sep 17 00:00:00 2001 From: Daniel Sandler Date: Fri, 12 Apr 2013 01:39:02 -0400 Subject: [PATCH] Toward regularizing color & level across battery indicators. Each of our existing assets is slightly incorrect in some way: inconsistent pixel jumps from one percent to the next, inconsistent color change, etc. The only way to get it perfectly right is to draw it programmatically. Bug: 8504254 // inconsistent color change threshold -- previously -- Bug: 3136046 // in Gingerbread Bug: 3387973 // Honeycomb Bug: 5070948 // ICS Change-Id: I6a3e7409ecec55e10328541ecb1e9d54aebdbe96 --- .../SystemUI/res/drawable-nodpi/lightning.png | Bin 0 -> 2896 bytes .../layout/quick_settings_tile_battery.xml | 10 +- .../res/layout/signal_cluster_view.xml | 3 +- packages/SystemUI/res/layout/status_bar.xml | 10 +- packages/SystemUI/res/values/arrays.xml | 12 + packages/SystemUI/res/values/colors.xml | 2 + packages/SystemUI/res/values/strings.xml | 3 + .../android/systemui/BatteryMeterView.java | 302 ++++++++++++++++++ .../statusbar/phone/PhoneStatusBar.java | 1 - .../statusbar/phone/QuickSettings.java | 11 +- 10 files changed, 336 insertions(+), 18 deletions(-) create mode 100644 packages/SystemUI/res/drawable-nodpi/lightning.png create mode 100755 packages/SystemUI/src/com/android/systemui/BatteryMeterView.java diff --git a/packages/SystemUI/res/drawable-nodpi/lightning.png b/packages/SystemUI/res/drawable-nodpi/lightning.png new file mode 100644 index 0000000000000000000000000000000000000000..29de3085a53364df2aa0a56dcf777f979eab0243 GIT binary patch literal 2896 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 MV>^v}aa%a=->lj3TmS$7 literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/layout/quick_settings_tile_battery.xml b/packages/SystemUI/res/layout/quick_settings_tile_battery.xml index c41e9b93545bc..f3b894cea53a6 100644 --- a/packages/SystemUI/res/layout/quick_settings_tile_battery.xml +++ b/packages/SystemUI/res/layout/quick_settings_tile_battery.xml @@ -19,14 +19,14 @@ android:layout_height="match_parent" android:layout_gravity="top" android:orientation="vertical"> - - \ No newline at end of file + diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml index aab5083da3cb1..66b06ef789dfc 100644 --- a/packages/SystemUI/res/layout/signal_cluster_view.xml +++ b/packages/SystemUI/res/layout/signal_cluster_view.xml @@ -20,8 +20,9 @@ - + diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml index cd6aaf604a248..506722d2ef0b0 100644 --- a/packages/SystemUI/res/values/arrays.xml +++ b/packages/SystemUI/res/values/arrays.xml @@ -40,4 +40,16 @@ @null + + + 4 + 15 + 100 + + + #FFFF0000 + #FFFE6600 + #FF3792B4 + + diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 803be6ec7e90c..04de60fb52b77 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -34,4 +34,6 @@ #ff33B5E5 #FF000000 #B0000000 + + #FF404040 diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index eec81778ed51f..c849aa6d8e96d 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -503,4 +503,7 @@ Notifications appear here Access them anytime by swiping down.\nSwipe down again for system controls. + + + ! diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java new file mode 100755 index 0000000000000..aa4362e2df823 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2013 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.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.BatteryManager; +import android.provider.Settings; +import android.util.AttributeSet; +import android.view.View; + +public class BatteryMeterView extends View { + public static final String TAG = BatteryMeterView.class.getSimpleName(); + public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST"; + + public static final boolean ENABLE_PERCENT = true; + public static final boolean SINGLE_DIGIT_PERCENT = false; + public static final boolean SHOW_100_PERCENT = false; + + public static final int FULL = 96; + public static final int EMPTY = 4; + + int[] mColors; + + boolean mShowPercent = true; + Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint; + int mButtonHeight; + private float mTextHeight, mWarningTextHeight; + Drawable mLightning; + + private int mHeight; + private int mWidth; + private String mWarningString; + + private class BatteryTracker extends BroadcastReceiver { + // current battery status + int 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)); + + 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)); + 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); + + if (!testmode) return; + + curLevel += incr; + if (curLevel == 100) { + incr *= -1; + } + postDelayed(this, 200); + } + }); + } + } + } + + BatteryTracker mTracker = new BatteryTracker(); + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(ACTION_LEVEL_TEST); + getContext().registerReceiver(mTracker, filter); + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + getContext().unregisterReceiver(mTracker); + } + + public BatteryMeterView(Context context) { + this(context, null, 0); + } + + public BatteryMeterView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + 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= FULL) { + drawFrac = 1f; + } else if (level <= EMPTY) { + drawFrac = 0f; + } + + c.drawRect(buttonframe, + drawFrac == 1f ? mBatteryPaint : mFramePaint); + + RectF clip = new RectF(frame); + clip.top += (frame.height() * (1f - drawFrac)); + + c.save(Canvas.CLIP_SAVE_FLAG); + c.clipRect(clip); + c.drawRect(frame, mBatteryPaint); + c.restore(); + + if (level <= EMPTY) { + final float x = mWidth * 0.5f; + final float y = (mHeight + mWarningTextHeight) * 0.48f; + c.drawText(mWarningString, x, y, mWarningTextPaint); + } else if (mTracker.plugged) { + final Rect r = new Rect( + (int)frame.left + width / 4, (int)frame.top + height / 5, + (int)frame.right - width / 4, (int)frame.bottom - height / 6); + mLightning.setBounds(r); + mLightning.draw(c); + } else if (mShowPercent && !(mTracker.level == 100 && !SHOW_100_PERCENT)) { + mTextPaint.setTextSize(height * + (SINGLE_DIGIT_PERCENT ? 0.75f + : (mTracker.level == 100 ? 0.38f : 0.5f))); + mTextHeight = -mTextPaint.getFontMetrics().ascent; + + final String str = String.valueOf(SINGLE_DIGIT_PERCENT ? (pct/10) : pct); + final float x = mWidth * 0.5f; + final float y = (mHeight + mTextHeight) * 0.47f; + c.drawText(str, + x, + y, + mTextPaint); + +// Paint pt = new Paint(); +// pt.setStrokeWidth(1f); +// pt.setStyle(Paint.Style.STROKE); +// pt.setColor(0xFFFF0000); +// c.drawRect(x, y-mTextHeight, x+tw, y, pt); +// +// Slog.v(TAG, "tw=" + tw + " th=" + mTextHeight); +// +// pt.setColor(0xFFFF00FF); +// c.drawRect(1, 1, mWidth, mHeight, pt); + } + } +} 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 74970873f982b..62be5d64d54d2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -507,7 +507,6 @@ public class PhoneStatusBar extends BaseStatusBar { // Other icons mLocationController = new LocationController(mContext); // will post a notification mBatteryController = new BatteryController(mContext); - mBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.battery)); mNetworkController = new NetworkController(mContext); mBluetoothController = new BluetoothController(mContext); mRotationLockController = new RotationLockController(mContext); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java index 5233f42892049..5f034a8c752c1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java @@ -494,7 +494,9 @@ class QuickSettings { } // Battery - final QuickSettingsBasicTile batteryTile = new QuickSettingsBasicTile(mContext); + final QuickSettingsTileView batteryTile = (QuickSettingsTileView) + inflater.inflate(R.layout.quick_settings_tile, parent, false); + batteryTile.setContent(R.layout.quick_settings_tile_battery, inflater); batteryTile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -506,9 +508,6 @@ class QuickSettings { public void refreshView(QuickSettingsTileView unused, State state) { QuickSettingsModel.BatteryState batteryState = (QuickSettingsModel.BatteryState) state; - Drawable d = batteryState.pluggedIn - ? mChargingBatteryLevels - : mBatteryLevels; String t; if (batteryState.batteryLevel == 100) { t = mContext.getString(R.string.quick_settings_battery_charged_label); @@ -519,9 +518,7 @@ class QuickSettings { : mContext.getString(R.string.status_bar_settings_battery_meter_format, batteryState.batteryLevel); } - batteryTile.setImageDrawable(d); - batteryTile.getImageView().setImageLevel(batteryState.batteryLevel); - batteryTile.setText(t); + ((TextView)batteryTile.findViewById(R.id.text)).setText(t); batteryTile.setContentDescription( mContext.getString(R.string.accessibility_quick_settings_battery, t)); }