Add more QS tiles
(only for paging prototype)
Change-Id: Ifb09e3262540a486c9ee7e83a904f96cc4e33fec
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
new file mode 100755
index 0000000..3eb1271
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
@@ -0,0 +1,464 @@
+/*
+ * 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.*;
+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 boolean mShowPercent;
+ 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;
+
+ 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 RectF mFrame = new RectF();
+ private final RectF mButtonFrame = new RectF();
+ private final RectF mBoltFrame = 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);
+
+ 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);
+ }
+
+ public void startListening() {
+ mListening = true;
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
+ if (mDemoMode) return;
+ mBatteryController.addStateChangedCallback(this);
+ }
+
+ public void stopListening() {
+ mListening = false;
+ mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
+ if (mDemoMode) return;
+ mBatteryController.removeStateChangedCallback(this);
+ }
+
+ 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() {
+ mPowerSaveEnabled = mBatteryController.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;
+ }
+
+ @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) {
+ int backgroundColor = getBackgroundColor(darkIntensity);
+ int fillColor = getFillColor(darkIntensity);
+ mIconTint = fillColor;
+ mFramePaint.setColor(backgroundColor);
+ mBoltPaint.setColor(fillColor);
+ mChargeColor = fillColor;
+ invalidateSelf();
+ }
+
+ 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() / 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) {
+ 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);
+ }
+ }
+
+ // 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();
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
old mode 100755
new mode 100644
index 95b58e5..6cb8da4
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -13,82 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.systemui;
-import android.animation.ArgbEvaluator;
-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.database.ContentObserver;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-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.provider.Settings;
import android.util.AttributeSet;
-import android.view.View;
-
+import android.widget.ImageView;
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";
+public class BatteryMeterView extends ImageView implements BatteryController.BatteryStateChangeCallback {
- 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 boolean mShowPercent;
- 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;
-
- 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 RectF mFrame = new RectF();
- private final RectF mButtonFrame = new RectF();
- private final RectF mBoltFrame = new RectF();
-
- private final Path mShapePath = new Path();
- private final Path mClipPath = new Path();
- private final Path mTextPath = new Path();
-
+ private final BatteryMeterDrawable mDrawable;
private BatteryController mBatteryController;
- private boolean mPowerSaveEnabled;
-
- private int mDarkModeBackgroundColor;
- private int mDarkModeFillColor;
-
- private int mLightModeBackgroundColor;
- private int mLightModeFillColor;
-
- private BatteryTracker mTracker = new BatteryTracker();
- private final SettingObserver mSettingObserver = new SettingObserver();
public BatteryMeterView(Context context) {
this(context, null, 0);
@@ -101,326 +38,14 @@
public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- 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));
- 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();
+ mDrawable = new BatteryMeterDrawable(context, new Handler(), frameColor);
atts.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);
-
- 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();
-
- 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);
- getContext().getContentResolver().registerContentObserver(
- Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- getContext().unregisterReceiver(mTracker);
- mBatteryController.removeStateChangedCallback(this);
- getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
- }
-
- public void setBatteryController(BatteryController batteryController) {
- mBatteryController = batteryController;
- mPowerSaveEnabled = mBatteryController.isPowerSave();
- }
-
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- // TODO: Use this callback instead of own broadcast receiver.
- }
-
- @Override
- public void onPowerSaveChanged() {
- mPowerSaveEnabled = mBatteryController.isPowerSave();
- 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]);
- }
- 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
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- mHeight = h;
- mWidth = w;
- mWarningTextPaint.setTextSize(h * 0.75f);
- mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
- }
-
- private void updateShowPercent() {
- mShowPercent = 0 != Settings.System.getInt(getContext().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) {
- int backgroundColor = getBackgroundColor(darkIntensity);
- int fillColor = getFillColor(darkIntensity);
- mIconTint = fillColor;
- mFramePaint.setColor(backgroundColor);
- mBoltPaint.setColor(fillColor);
- mChargeColor = fillColor;
- invalidate();
- }
-
- 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) {
- 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;
- }
-
- 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) {
- 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);
- }
- }
-
- // 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);
- }
- }
-
- // 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);
- }
- }
+ setImageDrawable(mDrawable);
}
@Override
@@ -428,116 +53,37 @@
return false;
}
- private boolean mDemoMode;
- private BatteryTracker mDemoTracker = new BatteryTracker();
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mBatteryController.addStateChangedCallback(this);
+ mDrawable.startListening();
+ }
@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 void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mBatteryController.removeStateChangedCallback(this);
+ mDrawable.stopListening();
}
- private final class BatteryTracker extends BroadcastReceiver {
- public static final int UNKNOWN_LEVEL = -1;
-
- // 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;
-
- @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);
- }
- });
- }
- }
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ setContentDescription(
+ getContext().getString(R.string.accessibility_battery_level, level));
}
- private final class SettingObserver extends ContentObserver {
- public SettingObserver() {
- super(new Handler());
- }
+ @Override
+ public void onPowerSaveChanged() {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- super.onChange(selfChange, uri);
- updateShowPercent();
- postInvalidate();
- }
}
+ public void setBatteryController(BatteryController mBatteryController) {
+ this.mBatteryController = mBatteryController;
+ mDrawable.setBatteryController(mBatteryController);
+ }
+
+ public void setDarkIntensity(float f) {
+ mDrawable.setDarkIntensity(f);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 3b3593b..e562682 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -30,16 +30,7 @@
import android.view.ViewGroup;
import com.android.systemui.qs.QSTile.State;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.FlashlightController;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.Listenable;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.*;
import java.util.Collection;
import java.util.Objects;
@@ -349,6 +340,9 @@
CastController getCastController();
FlashlightController getFlashlightController();
KeyguardMonitor getKeyguardMonitor();
+ UserSwitcherController getUserSwitcherController();
+ UserInfoController getUserInfoController();
+ BatteryController getBatteryController();
public interface Callback {
void onTilesChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 08cdc1e..e575923 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -267,7 +267,7 @@
final int w = MeasureSpec.getSize(widthMeasureSpec);
final int h = MeasureSpec.getSize(heightMeasureSpec);
final int iconSpec = exactly(mIconSizePx);
- mIcon.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST), iconSpec);
+ mIcon.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), iconSpec);
switch (mType) {
case QS_TYPE_QUICK:
mCircle.measure(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSTileHost.java
index 84b05d0..f676ea3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSTileHost.java
@@ -44,7 +44,8 @@
host.getRotationLockController(), host.getNetworkController(),
host.getZenModeController(), host.getHotspotController(), host.getCastController(),
host.getFlashlightController(), host.getUserSwitcherController(),
- host.getKeyguardMonitor(), new BlankSecurityController());
+ host.getUserInfoController(), host.getKeyguardMonitor(),
+ new BlankSecurityController(), host.getBatteryController());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
new file mode 100644
index 0000000..8f9655d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -0,0 +1,96 @@
+/*
+ * 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.qs.tiles;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.BatteryMeterDrawable;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.BatteryController;
+
+import java.text.NumberFormat;
+
+public class BatteryTile extends QSTile<QSTile.State> implements BatteryController.BatteryStateChangeCallback {
+
+ private final BatteryMeterDrawable mDrawable;
+ private final BatteryController mBatteryController;
+
+ private int mLevel;
+
+ public BatteryTile(Host host) {
+ super(host);
+ mBatteryController = host.getBatteryController();
+ mDrawable = new BatteryMeterDrawable(host.getContext(), new Handler(),
+ host.getContext().getColor(R.color.batterymeter_frame_color));
+ mDrawable.setBatteryController(mBatteryController);
+ }
+
+ @Override
+ protected State newTileState() {
+ return new QSTile.State();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsLogger.QS_BATTERY_TILE;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (listening) {
+ mDrawable.startListening();
+ mBatteryController.addStateChangedCallback(this);
+ } else {
+ mDrawable.stopListening();
+ mBatteryController.removeStateChangedCallback(this);
+ }
+ }
+
+ @Override
+ protected void handleClick() {
+ mHost.startActivityDismissingKeyguard(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY));
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ int level = (arg != null) ? (Integer) arg : mLevel;
+ String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
+
+ state.visible = true;
+ state.icon = new Icon() {
+ @Override
+ public Drawable getDrawable(Context context) {
+ return mDrawable;
+ }
+ };
+ state.label = percentage;
+ }
+
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ mLevel = level;
+ refreshState((Integer) level);
+ }
+
+ @Override
+ public void onPowerSaveChanged() {
+
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QLockTile.java
new file mode 100644
index 0000000..3675f02
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QLockTile.java
@@ -0,0 +1,81 @@
+/*
+ * 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.qs.tiles;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSTileView;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.R;
+
+public class QLockTile extends QSTile<QSTile.State> implements KeyguardMonitor.Callback {
+
+ private final KeyguardMonitor mKeyguard;
+
+ public QLockTile(Host host) {
+ super(host);
+ mKeyguard = host.getKeyguardMonitor();
+ }
+
+ @Override
+ public int getTileType() {
+ return QSTileView.QS_TYPE_QUICK;
+ }
+
+ @Override
+ protected State newTileState() {
+ return new State();
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (listening) {
+ mKeyguard.addCallback(this);
+ } else {
+ mKeyguard.removeCallback(this);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsLogger.QS_LOCK_TILE;
+ }
+
+ @Override
+ public void onKeyguardChanged() {
+ refreshState();
+ }
+
+ @Override
+ protected void handleClick() {
+ if (mKeyguard.isShowing()) {
+ mKeyguard.unlock();
+ } else {
+ mKeyguard.lock();
+ }
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ // TOD: Content description.
+ state.visible = true;
+ if (mKeyguard.isShowing()) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_lock);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_open);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
new file mode 100644
index 0000000..3c5ab8d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -0,0 +1,88 @@
+/*
+ * 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.qs.tiles;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.Pair;
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+
+public class UserTile extends QSTile<QSTile.State> implements UserInfoController.OnUserInfoChangedListener {
+
+ private final UserSwitcherController mUserSwitcherController;
+ private final UserInfoController mUserInfoController;
+ private Pair<String, Drawable> mLastUpdate;
+
+ public UserTile(Host host) {
+ super(host);
+ mUserSwitcherController = host.getUserSwitcherController();
+ mUserInfoController = host.getUserInfoController();
+ }
+
+ @Override
+ protected State newTileState() {
+ return new QSTile.State();
+ }
+
+ @Override
+ protected void handleClick() {
+ showDetail(true);
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return mUserSwitcherController.userDetailAdapter;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsLogger.QS_USER_TILE;
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (listening) {
+ mUserInfoController.addListener(this);
+ } else {
+ mUserInfoController.remListener(this);
+ }
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ final Pair<String, Drawable> p = arg != null ? (Pair<String, Drawable>) arg : mLastUpdate;
+ state.visible = p != null;
+ if (!state.visible) return;
+ state.label = p.first;
+ // TODO: Better content description.
+ state.contentDescription = p.first;
+ state.icon = new Icon() {
+ @Override
+ public Drawable getDrawable(Context context) {
+ return p.second;
+ }
+ };
+ }
+
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture) {
+ mLastUpdate = new Pair<>(name, picture);
+ refreshState(mLastUpdate);
+ }
+}
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 98f5444..876a934 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -904,8 +904,8 @@
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, mHotspotController,
mCastController, mFlashlightController,
- mUserSwitcherController, mKeyguardMonitor,
- mSecurityController);
+ mUserSwitcherController, mUserInfoController, mKeyguardMonitor,
+ mSecurityController, mBatteryController);
mQSPanel.setHost(qsh);
mQSPanel.setTiles(qsh.getTiles());
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
@@ -3001,6 +3001,10 @@
dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
}
+ public void dismissKeyguard() {
+ mStatusBarKeyguardViewManager.dismiss();
+ }
+
private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone) {
if (mStatusBarKeyguardViewManager.isShowing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 385c5d5..6ec9494 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -26,34 +26,8 @@
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.tiles.AirplaneModeTile;
-import com.android.systemui.qs.tiles.BluetoothTile;
-import com.android.systemui.qs.tiles.CastTile;
-import com.android.systemui.qs.tiles.CellularTile;
-import com.android.systemui.qs.tiles.ColorInversionTile;
-import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.qs.tiles.FlashlightTile;
-import com.android.systemui.qs.tiles.HotspotTile;
-import com.android.systemui.qs.tiles.IntentTile;
-import com.android.systemui.qs.tiles.LocationTile;
-import com.android.systemui.qs.tiles.QAirplaneTile;
-import com.android.systemui.qs.tiles.QBluetoothTile;
-import com.android.systemui.qs.tiles.QFlashlightTile;
-import com.android.systemui.qs.tiles.QRotationLockTile;
-import com.android.systemui.qs.tiles.QWifiTile;
-import com.android.systemui.qs.tiles.RotationLockTile;
-import com.android.systemui.qs.tiles.WifiTile;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.FlashlightController;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.qs.tiles.*;
+import com.android.systemui.statusbar.policy.*;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -85,8 +59,10 @@
private final Looper mLooper;
private final FlashlightController mFlashlight;
private final UserSwitcherController mUserSwitcherController;
+ private final UserInfoController mUserInfoController;
private final KeyguardMonitor mKeyguard;
private final SecurityController mSecurity;
+ private final BatteryController mBattery;
private Callback mCallback;
@@ -95,8 +71,8 @@
RotationLockController rotation, NetworkController network,
ZenModeController zen, HotspotController hotspot,
CastController cast, FlashlightController flashlight,
- UserSwitcherController userSwitcher, KeyguardMonitor keyguard,
- SecurityController security) {
+ UserSwitcherController userSwitcher, UserInfoController userInfo, KeyguardMonitor keyguard,
+ SecurityController security, BatteryController battery) {
mContext = context;
mStatusBar = statusBar;
mBluetooth = bluetooth;
@@ -108,8 +84,10 @@
mCast = cast;
mFlashlight = flashlight;
mUserSwitcherController = userSwitcher;
+ mUserInfoController = userInfo;
mKeyguard = keyguard;
mSecurity = security;
+ mBattery = battery;
final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
Process.THREAD_PRIORITY_BACKGROUND);
@@ -203,10 +181,21 @@
return mKeyguard;
}
+ @Override
public UserSwitcherController getUserSwitcherController() {
return mUserSwitcherController;
}
+ @Override
+ public UserInfoController getUserInfoController() {
+ return mUserInfoController;
+ }
+
+ @Override
+ public BatteryController getBatteryController() {
+ return mBattery;
+ }
+
public SecurityController getSecurityController() {
return mSecurity;
}
@@ -259,6 +248,8 @@
else if (tileSpec.equals("location")) return new LocationTile(this);
else if (tileSpec.equals("cast")) return new CastTile(this);
else if (tileSpec.equals("hotspot")) return new HotspotTile(this);
+ else if (tileSpec.equals("user")) return new UserTile(this);
+ else if (tileSpec.equals("battery")) return new BatteryTile(this);
// Detail only versions of wifi and bluetooth.
else if (tileSpec.equals("dwifi")) return new WifiTile(this, true);
else if (tileSpec.equals("dbt")) return new BluetoothTile(this, true);
@@ -268,6 +259,7 @@
else if (tileSpec.equals("qairplane")) return new QAirplaneTile(this);
else if (tileSpec.equals("qrotation")) return new QRotationLockTile(this);
else if (tileSpec.equals("qflashlight")) return new QFlashlightTile(this);
+ else if (tileSpec.equals("qlock")) return new QLockTile(this);
// Intent tiles.
else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
else throw new IllegalArgumentException("Bad tile spec: " + tileSpec);
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..5071df0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
+import android.os.Handler;
import android.os.PowerManager;
import android.util.Log;
@@ -30,24 +31,31 @@
public class BatteryController extends BroadcastReceiver {
private static final String TAG = "BatteryController";
+
+ public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
+
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
private final PowerManager mPowerManager;
+ private final Handler mHandler;
private int mLevel;
private boolean mPluggedIn;
private boolean mCharging;
private boolean mCharged;
private boolean mPowerSave;
+ private boolean mTestmode = false;
public BatteryController(Context context) {
+ mHandler = new Handler();
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
+ filter.addAction(ACTION_LEVEL_TEST);
context.registerReceiver(this, filter);
updatePowerSave();
@@ -71,9 +79,10 @@
mChangeCallbacks.remove(cb);
}
- public void onReceive(Context context, Intent intent) {
+ public void onReceive(final Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
mLevel = (int)(100f
* intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
/ intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
@@ -89,6 +98,38 @@
updatePowerSave();
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
+ } else if (action.equals(ACTION_LEVEL_TEST)) {
+ mTestmode = true;
+ mHandler.post(new Runnable() {
+ int curLevel = 0;
+ int incr = 1;
+ int saveLevel = mLevel;
+ boolean savePlugged = mPluggedIn;
+ Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ @Override
+ public void run() {
+ if (curLevel < 0) {
+ mTestmode = 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);
+ }
+ context.sendBroadcast(dummy);
+
+ if (!mTestmode) return;
+
+ curLevel += incr;
+ if (curLevel == 100) {
+ incr *= -1;
+ }
+ mHandler.postDelayed(this, 200);
+ }
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index d907b00..cec0c0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -18,7 +18,8 @@
import android.app.ActivityManager;
import android.content.Context;
-
+import android.os.RemoteException;
+import android.view.WindowManagerGlobal;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.settings.CurrentUserTracker;
@@ -83,6 +84,20 @@
return mCanSkipBouncer;
}
+ public void unlock() {
+ try {
+ WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void lock() {
+ try {
+ WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */);
+ } catch (RemoteException e) {
+ }
+ }
+
public void notifyKeyguardState(boolean showing, boolean secure) {
if (mShowing == showing && mSecure == secure) return;
mShowing = showing;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
index a8d4f13..6931d1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
@@ -71,6 +71,11 @@
public void addListener(OnUserInfoChangedListener callback) {
mCallbacks.add(callback);
+ callback.onUserInfoChanged(mUserName, mUserDrawable);
+ }
+
+ public void remListener(OnUserInfoChangedListener callback) {
+ mCallbacks.remove(callback);
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QSPagingSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/QSPagingSwitch.java
index 4387b33..04a51f0 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/QSPagingSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QSPagingSwitch.java
@@ -9,8 +9,8 @@
public class QSPagingSwitch extends TunerSwitch {
public static final String QS_PAGE_TILES =
- "dwifi,dbt,inversion,dnd,cell,airplane,rotation,flashlight,location,"
- + "hotspot,qwifi,qbt,qrotation,qflashlight,qairplane,cast";
+ "dwifi,dbt,dnd,cell,battery,user,rotation,flashlight,location,"
+ + "hotspot,qwifi,qbt,qlock,qflashlight,qairplane,inversion,cast";
public QSPagingSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
index 772f866..703ee661 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
@@ -206,8 +206,8 @@
private static class CustomHost extends QSTileHost {
public CustomHost(Context context) {
- super(context, null, null, null, null, null, null, null, null, null,
- null, null, new BlankSecurityController());
+ super(context, null, null, null, null, null, null, null, null, null, null,
+ null, null, new BlankSecurityController(), null);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 920f875..9a78b6c 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -39,7 +39,7 @@
import com.android.systemui.qs.QSPanel;
import com.android.systemui.tuner.TunerService.Tunable;
-import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
+import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
public class TunerFragment extends PreferenceFragment {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 50234b2..71559389 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -33,7 +33,7 @@
import android.provider.Settings;
import android.util.ArrayMap;
-import com.android.systemui.BatteryMeterView;
+import com.android.systemui.BatteryMeterDrawable;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
@@ -135,7 +135,7 @@
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);
+ Settings.System.putString(mContentResolver, BatteryMeterDrawable.SHOW_PERCENT_SETTING, null);
Intent intent = new Intent(DemoMode.ACTION_DEMO);
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
mContext.sendBroadcast(intent);