summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src')
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/FilterCanvas.java79
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSImageView.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTile.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileView.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/Recents.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsAlgorithm.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsLayout.java136
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java139
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java265
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java122
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Listenable.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java)6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java108
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java2
56 files changed, 1356 insertions, 432 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FilterCanvas.java b/packages/SystemUI/src/com/android/systemui/qs/FilterCanvas.java
deleted file mode 100644
index 05c8ee3..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/FilterCanvas.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-
-/** Canvas that forwards calls to another canvas. Can be subclassed to transform drawing calls.
- * Temporary solution to runtime modification of a single drawable shape into two
- * enabled & disabled versions. See QSImageView. **/
-public class FilterCanvas extends Canvas {
- private final Canvas mCanvas;
-
- public FilterCanvas(Canvas c) {
- mCanvas = c;
- }
-
- @Override
- public void drawPath(Path path, Paint paint) {
- mCanvas.drawPath(path, paint);
- }
-
- @Override
- public int getSaveCount() {
- return mCanvas.getSaveCount();
- }
-
- @Override
- public int save() {
- return mCanvas.save();
- }
-
- @Override
- public void translate(float dx, float dy) {
- mCanvas.translate(dx, dy);
- }
-
- @Override
- public boolean clipRect(int left, int top, int right, int bottom) {
- return mCanvas.clipRect(left, top, right, bottom);
- }
-
- @Override
- public boolean clipRect(Rect rect) {
- return mCanvas.clipRect(rect);
- }
-
- @Override
- public void concat(Matrix matrix) {
- mCanvas.concat(matrix);
- }
-
- @Override
- public void restoreToCount(int saveCount) {
- mCanvas.restoreToCount(saveCount);
- }
-
- @Override
- public void drawRect(Rect r, Paint paint) {
- mCanvas.drawRect(r, paint);
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java b/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java
index 1e15b9f..c169df0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java
@@ -21,10 +21,10 @@ import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings.Global;
-import com.android.systemui.statusbar.policy.Disposable;
+import com.android.systemui.statusbar.policy.Listenable;
/** Helper for managing a global setting. **/
-public abstract class GlobalSetting extends ContentObserver implements Disposable {
+public abstract class GlobalSetting extends ContentObserver implements Listenable {
private final Context mContext;
private final String mSettingName;
@@ -34,8 +34,6 @@ public abstract class GlobalSetting extends ContentObserver implements Disposabl
super(handler);
mContext = context;
mSettingName = settingName;
- mContext.getContentResolver().registerContentObserver(
- Global.getUriFor(mSettingName), false, this);
}
public int getValue() {
@@ -47,8 +45,13 @@ public abstract class GlobalSetting extends ContentObserver implements Disposabl
}
@Override
- public void dispose() {
- mContext.getContentResolver().unregisterContentObserver(this);
+ public void setListening(boolean listening) {
+ if (listening) {
+ mContext.getContentResolver().registerContentObserver(
+ Global.getUriFor(mSettingName), false, this);
+ } else {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImageView.java b/packages/SystemUI/src/com/android/systemui/qs/QSImageView.java
deleted file mode 100644
index ed67560..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QSImageView.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Path;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.VectorDrawable;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import com.android.systemui.R;
-
-/** ImageView that performs runtime modification of vector drawables (using FilterCanvas). **/
-public class QSImageView extends ImageView {
-
- private final int mOutlineWidth;
- private final int mColorEnabled;
- private final int mColorDisabled;
- private FilterCanvas mFilterCanvas;
- private Canvas mCanvas;
- private boolean mEnabledVersion = true;
- private boolean mFilter;
-
- public QSImageView(Context context) {
- this(context, null);
- }
-
- public QSImageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- final Resources res = context.getResources();
- mOutlineWidth = res.getDimensionPixelSize(R.dimen.quick_settings_tile_icon_outline);
- mColorEnabled = res.getColor(R.color.quick_settings_tile_icon_enabled);
- mColorDisabled = res.getColor(R.color.quick_settings_tile_icon_disabled);
- }
-
- public void setEnabledVersion(boolean enabledVersion) {
- mEnabledVersion = enabledVersion;
- invalidate();
- }
-
- @Override
- public void setImageDrawable(Drawable drawable) {
- mFilter = drawable instanceof VectorDrawable;
- super.setImageDrawable(drawable);
- }
-
- @Override
- public void setImageResource(int resId) {
- setImageDrawable(mContext.getDrawable(resId));
- }
-
- @Override
- public void draw(Canvas canvas) {
- if (mFilter) {
- if (canvas != mCanvas) {
- mCanvas = canvas;
- mFilterCanvas = new QSFilterCanvas(canvas);
- }
- super.draw(mFilterCanvas);
- } else {
- super.draw(canvas);
- }
- }
-
- private class QSFilterCanvas extends FilterCanvas {
- public QSFilterCanvas(Canvas c) {
- super(c);
- }
-
- @Override
- public void drawPath(Path path, Paint paint) {
- if (mEnabledVersion) {
- paint.setColor(mColorEnabled);
- } else {
- paint.setStyle(Style.STROKE);
- paint.setStrokeJoin(Paint.Join.ROUND);
- paint.setColor(mColorDisabled);
- paint.setStrokeWidth(mOutlineWidth);
- }
- super.drawPath(path, paint);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index afb5483..6176eb6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -80,7 +80,10 @@ public class QSPanel extends ViewGroup {
showDetail(false /*show*/, mDetailRecord);
}
for (TileRecord r : mRecords) {
- r.tile.setShown(expanded);
+ r.tile.setListening(expanded);
+ if (expanded) {
+ r.tile.refreshState();
+ }
}
}
@@ -125,6 +128,7 @@ public class QSPanel extends ViewGroup {
}
};
r.tileView.init(click, clickSecondary);
+ r.tile.refreshState();
mRecords.add(r);
addView(r.tileView);
@@ -156,24 +160,29 @@ public class QSPanel extends ViewGroup {
mCellHeight = (int)(mCellWidth / TILE_ASPECT);
mLargeCellWidth = (int)(mCellWidth * LARGE_TILE_FACTOR);
mLargeCellHeight = (int)(mCellHeight * LARGE_TILE_FACTOR);
- int r = 0;
- int c = 0;
+ int r = -1;
+ int c = -1;
int rows = 0;
+ boolean rowIsDual = false;
for (TileRecord record : mRecords) {
if (record.tileView.getVisibility() == GONE) continue;
+ // wrap to next column if we've reached the max # of columns
+ // also don't allow dual + single tiles on the same row
+ if (r == -1 || c == (mColumns - 1) || rowIsDual != record.tile.supportsDualTargets()) {
+ r++;
+ c = 0;
+ rowIsDual = record.tile.supportsDualTargets();
+ } else {
+ c++;
+ }
record.row = r;
record.col = c;
rows = r + 1;
- c++;
- if (c == mColumns /*end of normal column*/ || r == 0 && c == 2 /*end of 1st column*/) {
- c = 0;
- r++;
- }
}
for (TileRecord record : mRecords) {
if (record.tileView.getVisibility() == GONE) continue;
- record.tileView.setDual(record.row == 0);
+ record.tileView.setDual(record.tile.supportsDualTargets());
final int cw = record.row == 0 ? mLargeCellWidth : mCellWidth;
final int ch = record.row == 0 ? mLargeCellHeight : mCellHeight;
record.tileView.measure(exactly(cw), exactly(ch));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 05f308d..835a5c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -19,7 +19,6 @@ package com.android.systemui.qs;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.VectorDrawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -30,7 +29,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.Disposable;
+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;
@@ -47,8 +46,10 @@ import java.util.Objects;
* handleUpdateState. Callbacks affecting state should use refreshState to trigger another
* state update pass on tile looper.
*/
-public abstract class QSTile<TState extends State> implements Disposable {
- private final String TAG = "QSTile." + getClass().getSimpleName();
+public abstract class QSTile<TState extends State> implements Listenable {
+ protected final String TAG = "QSTile." + getClass().getSimpleName();
+ protected static final boolean DEBUG = false;
+ public static final int FEEDBACK_START_DELAY = 400;
protected final Host mHost;
protected final Context mContext;
@@ -69,6 +70,10 @@ public abstract class QSTile<TState extends State> implements Disposable {
mHandler = new H(host.getLooper());
}
+ public boolean supportsDualTargets() {
+ return false;
+ }
+
public Host getHost() {
return mHost;
}
@@ -111,10 +116,6 @@ public abstract class QSTile<TState extends State> implements Disposable {
mHandler.obtainMessage(H.USER_SWITCH, newUserId).sendToTarget();
}
- public void setShown(boolean shown) {
- mHandler.obtainMessage(H.SHOWN, shown ? 1 : 0, 0).sendToTarget();
- }
-
// call only on tile worker looper
private void handleSetCallback(Callback callback) {
@@ -126,10 +127,6 @@ public abstract class QSTile<TState extends State> implements Disposable {
// optional
}
- protected void handleShown(boolean shown) {
- // optional, discouraged
- }
-
protected void handleRefreshState(Object arg) {
handleUpdateState(mTmpState, arg);
final boolean changed = mTmpState.copyTo(mState);
@@ -161,7 +158,6 @@ public abstract class QSTile<TState extends State> implements Disposable {
private static final int REFRESH_STATE = 4;
private static final int SHOW_DETAIL = 5;
private static final int USER_SWITCH = 6;
- private static final int SHOWN = 7;
private H(Looper looper) {
super(looper);
@@ -189,9 +185,6 @@ public abstract class QSTile<TState extends State> implements Disposable {
} else if (msg.what == USER_SWITCH) {
name = "handleUserSwitch";
handleUserSwitch(msg.arg1);
- } else if (msg.what == SHOWN) {
- name = "handleShown";
- handleShown(msg.arg1 != 0);
}
} catch (Throwable t) {
final String error = "Error in " + name;
@@ -212,7 +205,6 @@ public abstract class QSTile<TState extends State> implements Disposable {
void collapsePanels();
Looper getLooper();
Context getContext();
- VectorDrawable getVectorDrawable(int resId);
BluetoothController getBluetoothController();
LocationController getLocationController();
RotationLockController getRotationLockController();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 17a95fb..4cfb636 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -25,9 +25,11 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
@@ -43,9 +45,9 @@ public class QSTileView extends ViewGroup {
protected final Context mContext;
private final View mIcon;
private final View mDivider;
- private final TextView mLabel;
private final H mHandler = new H();
+ private TextView mLabel;
private boolean mDual;
private OnClickListener mClickPrimary;
private OnClickListener mClickSecondary;
@@ -55,14 +57,7 @@ public class QSTileView extends ViewGroup {
mContext = context;
final Resources res = context.getResources();
- mLabel = new TextView(mContext);
- mLabel.setId(android.R.id.title);
- mLabel.setTextColor(res.getColor(R.color.quick_settings_tile_text));
- mLabel.setGravity(Gravity.CENTER);
- mLabel.setTypeface(CONDENSED);
- mLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- res.getDimensionPixelSize(R.dimen.quick_settings_tile_text_size));
- addView(mLabel);
+ recreateLabel();
setClipChildren(false);
mIcon = createIcon();
@@ -78,8 +73,33 @@ public class QSTileView extends ViewGroup {
setBackground(getSelectableBackground());
}
+ private void recreateLabel() {
+ CharSequence labelText = null;
+ if (mLabel != null) {
+ labelText = mLabel.getText();
+ removeView(mLabel);
+ }
+ final Resources res = mContext.getResources();
+ mLabel = new TextView(mDual ? new ContextThemeWrapper(mContext, R.style.QSBorderless_Tiny)
+ : mContext);
+ mLabel.setId(android.R.id.title);
+ mLabel.setTextColor(res.getColor(R.color.quick_settings_tile_text));
+ mLabel.setGravity(Gravity.CENTER);
+ mLabel.setTypeface(CONDENSED);
+ mLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ res.getDimensionPixelSize(R.dimen.quick_settings_tile_text_size));
+ if (labelText != null) {
+ mLabel.setText(labelText);
+ }
+ addView(mLabel);
+ }
+
public void setDual(boolean dual) {
+ final boolean changed = dual != mDual;
mDual = dual;
+ if (changed) {
+ recreateLabel();
+ }
if (mDual) {
setOnClickListener(mClickPrimary);
mLabel.setClickable(true);
@@ -98,7 +118,7 @@ public class QSTileView extends ViewGroup {
}
protected View createIcon() {
- QSImageView icon = new QSImageView(mContext);
+ final ImageView icon = new ImageView(mContext);
icon.setId(android.R.id.icon);
icon.setScaleType(ScaleType.CENTER_INSIDE);
return icon;
@@ -120,9 +140,10 @@ public class QSTileView extends ViewGroup {
final int iconSpec = exactly((int)mLabel.getTextSize() * 2);
mIcon.measure(iconSpec, iconSpec);
mLabel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
- mLabel.measure(widthMeasureSpec, exactly(mLabel.getMeasuredHeight() + p * 2));
if (mDual) {
mDivider.measure(widthMeasureSpec, exactly(mDivider.getLayoutParams().height));
+ } else {
+ mLabel.measure(widthMeasureSpec, exactly(mLabel.getMeasuredHeight() + p * 2));
}
setMeasuredDimension(w, h);
}
@@ -156,15 +177,12 @@ public class QSTileView extends ViewGroup {
}
protected void handleStateChanged(QSTile.State state) {
- if (mIcon instanceof QSImageView) {
- QSImageView qsiv = (QSImageView) mIcon;
+ if (mIcon instanceof ImageView) {
+ ImageView iv = (ImageView) mIcon;
if (state.icon != null) {
- qsiv.setImageDrawable(state.icon);
+ iv.setImageDrawable(state.icon);
} else if (state.iconId > 0) {
- qsiv.setImageResource(state.iconId);
- }
- if (state.icon != null && state instanceof QSTile.BooleanState) {
- qsiv.setEnabledVersion(((QSTile.BooleanState)state).value);
+ iv.setImageResource(state.iconId);
}
}
mLabel.setText(state.label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
index 4debaa9..3ed3d30 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
@@ -21,10 +21,10 @@ import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings.Secure;
-import com.android.systemui.statusbar.policy.Disposable;
+import com.android.systemui.statusbar.policy.Listenable;
/** Helper for managing a secure setting. **/
-public abstract class SecureSetting extends ContentObserver implements Disposable {
+public abstract class SecureSetting extends ContentObserver implements Listenable {
private final Context mContext;
private final String mSettingName;
@@ -38,8 +38,7 @@ public abstract class SecureSetting extends ContentObserver implements Disposabl
}
public void rebindForCurrentUser() {
- mContext.getContentResolver().registerContentObserver(
- Secure.getUriFor(mSettingName), false, this);
+ setListening(true);
}
public int getValue() {
@@ -51,8 +50,13 @@ public abstract class SecureSetting extends ContentObserver implements Disposabl
}
@Override
- public void dispose() {
- mContext.getContentResolver().unregisterContentObserver(this);
+ public void setListening(boolean listening) {
+ if (listening) {
+ mContext.getContentResolver().registerContentObserver(
+ Secure.getUriFor(mSettingName), false, this);
+ } else {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 5fe8422..c0f9bf2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -39,11 +39,6 @@ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
handleRefreshState(value);
}
};
-
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- mContext.registerReceiver(mReceiver, filter);
- refreshState();
}
@Override
@@ -70,7 +65,6 @@ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
state.value = airplaneMode;
state.visible = true;
state.label = mContext.getString(R.string.quick_settings_airplane_mode_label);
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_airplane);
if (airplaneMode) {
state.iconId = R.drawable.ic_qs_airplane_on;
state.contentDescription = mContext.getString(
@@ -84,9 +78,15 @@ public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
}
}
- public void dispose() {
- mSetting.dispose();
- mContext.unregisterReceiver(mReceiver);
+ public void setListening(boolean listening) {
+ if (listening) {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ mContext.registerReceiver(mReceiver, filter);
+ } else {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ mSetting.setListening(listening);
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 60a6047..7335ab4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -33,7 +33,11 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
public BluetoothTile(Host host) {
super(host);
mController = host.getBluetoothController();
- mController.addStateChangedCallback(mCallback);
+ }
+
+ @Override
+ public boolean supportsDualTargets() {
+ return true;
}
@Override
@@ -42,8 +46,12 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
}
@Override
- public void dispose() {
- mController.removeStateChangedCallback(mCallback);
+ public void setListening(boolean listening) {
+ if (listening) {
+ mController.addStateChangedCallback(mCallback);
+ } else {
+ mController.removeStateChangedCallback(mCallback);
+ }
}
@Override
@@ -64,14 +72,13 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
final boolean connected = mController.isBluetoothConnected();
state.visible = supported;
state.value = enabled;
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_bluetooth);
final String stateContentDescription;
if (enabled) {
if (connected) {
- state.iconId = R.drawable.ic_qs_bluetooth_on;
+ state.iconId = R.drawable.ic_qs_bluetooth_connected;
stateContentDescription = mContext.getString(R.string.accessibility_desc_connected);
} else {
- state.iconId = R.drawable.ic_qs_bluetooth_not_connected;
+ state.iconId = R.drawable.ic_qs_bluetooth_on;
stateContentDescription = mContext.getString(R.string.accessibility_desc_on);
}
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
index 0e9b9a7..bfd416d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
@@ -51,21 +51,25 @@ public class BugreportTile extends QSTile<QSTile.State> {
}
@Override
- public void dispose() {
- mSetting.dispose();
+ public void setListening(boolean listening) {
+ mSetting.setListening(listening);
}
@Override
protected void handleClick() {
- mHost.collapsePanels();
- mUiHandler.post(mShowDialog);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mHost.collapsePanels();
+ mUiHandler.post(mShowDialog);
+ }
+ }, FEEDBACK_START_DELAY);
}
@Override
protected void handleUpdateState(State state, Object pushArg) {
state.visible = mSetting.getValue() != 0;
- state.iconId = com.android.internal.R.drawable.stat_sys_adb;
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_bugreport);
+ state.iconId = R.drawable.ic_qs_bugreport;
state.label = mContext.getString(com.android.internal.R.string.bugreport_title);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index a3eaa2c..907c77e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -35,14 +35,9 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
private final CastController mController;
- private boolean mShown;
-
public CastTile(Host host) {
super(host);
mController = host.getCastController();
- if (mController != null) {
- mController.addCallback(mCallback);
- }
}
@Override
@@ -51,9 +46,14 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
}
@Override
- public void dispose() {
+ public void setListening(boolean listening) {
if (mController == null) return;
- mController.removeCallback(mCallback);
+ if (listening) {
+ mController.addCallback(mCallback);
+ } else {
+ mController.removeCallback(mCallback);
+ }
+ mController.setDiscovering(listening);
}
@Override
@@ -64,17 +64,13 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
}
@Override
- protected void handleShown(boolean shown) {
- if (mShown == shown) return;
- if (mController == null) return;
- mShown = shown;
- mController.setDiscovering(mShown);
- }
-
- @Override
protected void handleClick() {
- mHost.collapsePanels();
- mUiHandler.post(mShowDialog);
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ mHost.collapsePanels();
+ mUiHandler.post(mShowDialog);
+ }
+ }, FEEDBACK_START_DELAY);
}
@Override
@@ -82,13 +78,13 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
state.visible = true;
state.label = mContext
.getString(R.string.quick_settings_remote_display_no_connection_label);
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_cast);
if (arg instanceof CallbackInfo) {
final CallbackInfo cb = (CallbackInfo) arg;
if (cb.connectedRouteName != null) {
state.value = !cb.connecting;
}
}
+ state.iconId = state.value ? R.drawable.ic_qs_cast_on : R.drawable.ic_qs_cast_off;
}
private static class CallbackInfo {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 86a4e79..182a0ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -38,7 +38,6 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
public CellularTile(Host host) {
super(host);
mController = host.getNetworkController();
- mController.addNetworkSignalChangedCallback(mCallback);
}
@Override
@@ -47,8 +46,12 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
}
@Override
- public void dispose() {
- mController.removeNetworkSignalChangedCallback(mCallback);
+ public void setListening(boolean listening) {
+ if (listening) {
+ mController.addNetworkSignalChangedCallback(mCallback);
+ } else {
+ mController.removeNetworkSignalChangedCallback(mCallback);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 66740af..5301362 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -39,8 +39,6 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
handleRefreshState(value);
}
};
-
- refreshState();
}
@Override
@@ -49,8 +47,8 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
}
@Override
- public void dispose() {
- mSetting.dispose();
+ public void setListening(boolean listening) {
+ mSetting.setListening(listening);
}
@Override
@@ -73,6 +71,6 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
state.visible = mVisible;
state.value = enabled;
state.label = mContext.getString(R.string.quick_settings_inversion_label);
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_invert_colors);
+ state.iconId = R.drawable.ic_qs_color_inversion;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 1a67afc..f2ba558 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -42,7 +42,7 @@ public class HotspotTile extends QSTile<QSTile.State> {
}
@Override
- public void dispose() {
+ public void setListening(boolean listening) {
}
@@ -55,6 +55,6 @@ public class HotspotTile extends QSTile<QSTile.State> {
protected void handleUpdateState(State state, Object arg) {
state.visible = mController != null;
state.label = mContext.getString(R.string.quick_settings_hotspot_label);
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_hotspot);
+ state.iconId = R.drawable.ic_qs_hotspot_off;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index d32f98f..c5ad9e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs.tiles;
+import android.graphics.drawable.AnimationDrawable;
+
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.LocationController;
@@ -29,7 +31,6 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
public LocationTile(Host host) {
super(host);
mController = host.getLocationController();
- mController.addSettingsChangedCallback(mCallback);
}
@Override
@@ -37,8 +38,13 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
return new BooleanState();
}
- public void dispose() {
- mController.removeSettingsChangedCallback(mCallback);
+ @Override
+ public void setListening(boolean listening) {
+ if (listening) {
+ mController.addSettingsChangedCallback(mCallback);
+ } else {
+ mController.removeSettingsChangedCallback(mCallback);
+ }
}
@Override
@@ -56,16 +62,27 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
protected void handleUpdateState(BooleanState state, Object arg) {
final boolean locationEnabled = mController.isLocationEnabled();
state.visible = true;
- state.value = locationEnabled;
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_location);
+ if (state.value != locationEnabled) {
+ state.value = locationEnabled;
+ final AnimationDrawable d = (AnimationDrawable) mContext.getDrawable(locationEnabled
+ ? R.drawable.ic_qs_location_on
+ : R.drawable.ic_qs_location_off);
+ state.icon = d;
+ mUiHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ d.start();
+ }
+ });
+ }
if (locationEnabled) {
- state.iconId = R.drawable.ic_qs_location_on;
+ if (state.icon == null) state.iconId = R.drawable.ic_qs_location_01;
state.label = mContext.getString(R.string.quick_settings_location_label);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_location,
mContext.getString(R.string.accessibility_desc_on));
} else {
- state.iconId = R.drawable.ic_qs_location_off;
+ if (state.icon == null) state.iconId = R.drawable.ic_qs_location_11;
state.label = mContext.getString(R.string.quick_settings_location_off_label);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_location,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java
index 36a579c..c5e9b52 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java
@@ -33,8 +33,6 @@ public class RingerModeTile extends QSTile<RingerModeTile.IntState> {
public RingerModeTile(Host host) {
super(host);
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- final IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
- mContext.registerReceiver(mReceiver, filter);
}
@Override
@@ -43,8 +41,13 @@ public class RingerModeTile extends QSTile<RingerModeTile.IntState> {
}
@Override
- public void dispose() {
- mContext.unregisterReceiver(mReceiver);
+ public void setListening(boolean listening) {
+ if (listening) {
+ final IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
+ mContext.registerReceiver(mReceiver, filter);
+ } else {
+ mContext.unregisterReceiver(mReceiver);
+ }
}
@Override
@@ -64,13 +67,13 @@ public class RingerModeTile extends QSTile<RingerModeTile.IntState> {
state.visible = true;
state.value = ringerMode;
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_ringer_vibrate);
+ state.iconId = R.drawable.ic_qs_ringer_vibrate;
state.label = "Vibrate";
} else if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_ringer_silent);
+ state.iconId = R.drawable.ic_qs_ringer_silent;
state.label = "Silent";
} else {
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_ringer_audible);
+ state.iconId = R.drawable.ic_qs_ringer_audible;
state.label = "Audible";
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index d075299..1b0967b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -33,8 +33,6 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
public RotationLockTile(Host host) {
super(host);
mController = host.getRotationLockController();
- if (mController == null) return;
- mController.addRotationLockControllerCallback(mCallback);
}
@Override
@@ -42,9 +40,13 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
return new BooleanState();
}
- public void dispose() {
+ public void setListening(boolean listening) {
if (mController == null) return;
- mController.removeRotationLockControllerCallback(mCallback);
+ if (listening) {
+ mController.addRotationLockControllerCallback(mCallback);
+ } else {
+ mController.removeRotationLockControllerCallback(mCallback);
+ }
}
@Override
@@ -61,8 +63,8 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
if (state.value != rotationLocked) {
state.value = rotationLocked;
final AnimationDrawable d = (AnimationDrawable) mContext.getDrawable(rotationLocked
- ? R.drawable.ic_rotate_locked_anim
- : R.drawable.ic_rotate_unlocked_anim);
+ ? R.drawable.ic_qs_rotation_locked
+ : R.drawable.ic_qs_rotation_unlocked);
state.icon = d;
mUiHandler.post(new Runnable() {
@Override
@@ -80,12 +82,12 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
: R.string.quick_settings_rotation_locked_label;
state.label = mContext.getString(label);
if (state.icon == null) {
- state.icon = mContext.getDrawable(R.drawable.ic_rotate_24_15);
+ state.icon = mContext.getDrawable(R.drawable.ic_qs_rotation_15);
}
} else {
state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
if (state.icon == null) {
- state.icon = mContext.getDrawable(R.drawable.ic_rotate_24_01);
+ state.icon = mContext.getDrawable(R.drawable.ic_qs_rotation_01);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index e08a6fa..ef7fb89 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.provider.Settings;
+import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -37,7 +38,11 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
public WifiTile(Host host) {
super(host);
mController = host.getNetworkController();
- mController.addNetworkSignalChangedCallback(mCallback);
+ }
+
+ @Override
+ public boolean supportsDualTargets() {
+ return true;
}
@Override
@@ -46,8 +51,12 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
}
@Override
- public void dispose() {
- mController.removeNetworkSignalChangedCallback(mCallback);
+ public void setListening(boolean listening) {
+ if (listening) {
+ mController.addNetworkSignalChangedCallback(mCallback);
+ } else {
+ mController.removeNetworkSignalChangedCallback(mCallback);
+ }
}
@Override
@@ -67,8 +76,9 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
@Override
protected void handleUpdateState(SignalState state, Object arg) {
- if (arg == null) return;
state.visible = true;
+ if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
+ if (arg == null) return;
CallbackInfo cb = (CallbackInfo) arg;
boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
@@ -114,6 +124,18 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
boolean activityIn;
boolean activityOut;
String wifiSignalContentDescription;
+
+ @Override
+ public String toString() {
+ return new StringBuilder("CallbackInfo[")
+ .append("enabled=").append(enabled)
+ .append(",wifiSignalIconId=").append(wifiSignalIconId)
+ .append(",enabledDesc=").append(enabledDesc)
+ .append(",activityIn=").append(activityIn)
+ .append(",activityOut=").append(activityOut)
+ .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
+ .append(']').toString();
+ }
}
private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() {
@@ -121,6 +143,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
boolean activityIn, boolean activityOut,
String wifiSignalContentDescriptionId, String description) {
+ if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
final CallbackInfo info = new CallbackInfo();
info.enabled = enabled;
info.wifiSignalIconId = wifiSignalIconId;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java
index dceb856..2edefe7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java
@@ -32,6 +32,7 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RelativeLayout;
@@ -39,7 +40,6 @@ import android.widget.Switch;
import android.widget.TextView;
import com.android.systemui.R;
-import com.android.systemui.qs.QSImageView;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -72,9 +72,7 @@ public class ZenModeDetail extends RelativeLayout {
mContext = getContext();
mController = mHost.getZenModeController();
- final QSImageView close = (QSImageView) findViewById(android.R.id.button1);
- close.setImageDrawable(mHost.getVectorDrawable(R.drawable.ic_qs_close));
- close.setEnabledVersion(true);
+ final ImageView close = (ImageView) findViewById(android.R.id.button1);
close.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -239,9 +237,7 @@ public class ZenModeDetail extends RelativeLayout {
title.setText(condition.summary);
title.setEnabled(enabled);
title.setAlpha(enabled ? 1 : .5f);
- final QSImageView button1 = (QSImageView) row.findViewById(android.R.id.button1);
- button1.setImageDrawable(mHost.getVectorDrawable(R.drawable.ic_qs_minus));
- button1.setEnabledVersion(true);
+ final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -250,9 +246,7 @@ public class ZenModeDetail extends RelativeLayout {
}
});
- final QSImageView button2 = (QSImageView) row.findViewById(android.R.id.button2);
- button2.setImageDrawable(mHost.getVectorDrawable(R.drawable.ic_qs_plus));
- button2.setEnabledVersion(true);
+ final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java
index 83918e8..bfa9c19 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles;
import android.content.Context;
+import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
@@ -33,7 +34,6 @@ public class ZenModeTile extends QSTile<QSTile.BooleanState> {
public ZenModeTile(Host host) {
super(host);
mController = host.getZenModeController();
- mController.addCallback(mCallback);
}
@Override
@@ -51,8 +51,12 @@ public class ZenModeTile extends QSTile<QSTile.BooleanState> {
}
@Override
- public void dispose() {
- mController.removeCallback(mCallback);
+ public void setListening(boolean listening) {
+ if (listening) {
+ mController.addCallback(mCallback);
+ } else {
+ mController.removeCallback(mCallback);
+ }
}
@Override
@@ -69,14 +73,14 @@ public class ZenModeTile extends QSTile<QSTile.BooleanState> {
final boolean zen = arg instanceof Boolean ? (Boolean)arg : mController.isZen();
state.value = zen;
state.visible = true;
- state.iconId = R.drawable.stat_sys_zen_limited;
- state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_zen);
+ state.iconId = zen ? R.drawable.ic_qs_zen_on : R.drawable.ic_qs_zen_off;
state.label = mContext.getString(R.string.zen_mode_title);
}
private final ZenModeController.Callback mCallback = new ZenModeController.Callback() {
@Override
public void onZenChanged(boolean zen) {
+ if (DEBUG) Log.d(TAG, "onZenChanged " + zen);
refreshState(zen);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
index d3e949f..00c43e8 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -43,14 +43,12 @@ public class Recents extends SystemUI implements RecentsComponent {
private static final boolean DEBUG = true;
// Which recents to use
- boolean mUseAlternateRecents;
+ boolean mUseAlternateRecents = true;
AlternateRecentsComponent mAlternateRecents;
boolean mBootCompleted = false;
@Override
public void start() {
- Configuration config = mContext.getResources().getConfiguration();
- mUseAlternateRecents = (config.smallestScreenWidthDp < 600);
if (mUseAlternateRecents) {
if (mAlternateRecents == null) {
mAlternateRecents = new AlternateRecentsComponent(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 1ca0476..1c12ac2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -400,15 +400,14 @@ public class RecentsTaskLoader {
ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
if (info == null) continue;
- ActivityManager.RecentsActivityValues av = t.activityValues;
+ ActivityManager.TaskDescription av = t.taskDescription;
String activityLabel = null;
BitmapDrawable activityIcon = null;
int activityColor = 0;
if (av != null) {
- activityLabel = (av.label != null ? av.label.toString() :
- ssp.getActivityLabel(info));
- activityIcon = (av.icon != null) ? new BitmapDrawable(res, av.icon) : null;
- activityColor = av.colorPrimary;
+ activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info));
+ activityIcon = (av.getIcon() != null) ? new BitmapDrawable(res, av.getIcon()) : null;
+ activityColor = av.getPrimaryColor();
} else {
activityLabel = ssp.getActivityLabel(info);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 8d82883..59d0ea6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -96,18 +96,19 @@ public class SystemServicesProxy {
int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
ComponentName cn = new ComponentName("com.android.test" + packageIndex,
"com.android.test" + i + ".Activity");
+ String description = "" + i + " - " +
+ Long.toString(Math.abs(new Random().nextLong()), 36);
// Create the recent task info
ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
rti.id = rti.persistentId = i;
rti.baseIntent = new Intent();
rti.baseIntent.setComponent(cn);
- rti.activityValues = new ActivityManager.RecentsActivityValues();
- rti.description = "" + i + " - " +
- Long.toString(Math.abs(new Random().nextLong()), 36);
+ rti.description = description;
if (i % 2 == 0) {
- rti.activityValues.label = rti.description;
- rti.activityValues.icon = Bitmap.createBitmap(mDummyIcon);
- rti.activityValues.colorPrimary = new Random().nextInt();
+ rti.taskDescription = new ActivityManager.TaskDescription(description,
+ Bitmap.createBitmap(mDummyIcon), new Random().nextInt());
+ } else {
+ rti.taskDescription = new ActivityManager.TaskDescription();
}
tasks.add(rti);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 91df9ef..5e8c769 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -45,6 +46,9 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private int mBgResId = R.drawable.notification_quantum_bg;
private int mDimmedBgResId = R.drawable.notification_quantum_bg_dim;
+ private int mBgTint = 0;
+ private int mDimmedBgTint = 0;
+
/**
* Flag to indicate that the notification has been touched once and the second touch will
* click it.
@@ -209,17 +213,23 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
* @param bgResId The background resource to use in normal state.
* @param dimmedBgResId The background resource to use in dimmed state.
*/
- public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
+ public void setBackgroundResourceIds(int bgResId, int bgTint, int dimmedBgResId, int dimmedTint) {
mBgResId = bgResId;
+ mBgTint = bgTint;
mDimmedBgResId = dimmedBgResId;
+ mDimmedBgTint = dimmedTint;
updateBackgroundResource();
}
+ public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
+ setBackgroundResourceIds(bgResId, 0, dimmedBgResId, 0);
+ }
+
private void fadeBackgroundResource() {
if (mDimmed) {
- setBackgroundDimmed(mDimmedBgResId);
+ setBackgroundDimmed(mDimmedBgResId, mDimmedBgTint);
} else {
- setBackgroundNormal(mBgResId);
+ setBackgroundNormal(mBgResId, mBgTint);
}
int startAlpha = mDimmed ? 255 : 0;
int endAlpha = mDimmed ? 0 : 255;
@@ -256,12 +266,12 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private void updateBackgroundResource() {
if (mDimmed) {
- setBackgroundDimmed(mDimmedBgResId);
+ setBackgroundDimmed(mDimmedBgResId, mDimmedBgTint);
mBackgroundDimmed.setAlpha(255);
setBackgroundNormal(null);
} else {
setBackgroundDimmed(null);
- setBackgroundNormal(mBgResId);
+ setBackgroundNormal(mBgResId, mBgTint);
mBackgroundNormal.setAlpha(255);
}
}
@@ -295,12 +305,20 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
invalidate();
}
- private void setBackgroundNormal(int drawableResId) {
- setBackgroundNormal(getResources().getDrawable(drawableResId));
+ private void setBackgroundNormal(int drawableResId, int tintColor) {
+ final Drawable d = getResources().getDrawable(drawableResId);
+ if (tintColor != 0) {
+ d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
+ }
+ setBackgroundNormal(d);
}
- private void setBackgroundDimmed(int drawableResId) {
- setBackgroundDimmed(getResources().getDrawable(drawableResId));
+ private void setBackgroundDimmed(int drawableResId, int tintColor) {
+ final Drawable d = getResources().getDrawable(drawableResId);
+ if (tintColor != 0) {
+ d.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
+ }
+ setBackgroundDimmed(d);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index b079265..7918dec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -429,14 +429,16 @@ public abstract class BaseStatusBar extends SystemUI implements
protected void applyLegacyRowBackground(StatusBarNotification sbn,
NotificationData.Entry entry) {
+ int version = 0;
+ try {
+ ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.getPackageName(), 0);
+ version = info.targetSdkVersion;
+ } catch (NameNotFoundException ex) {
+ Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
+ }
+
if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
- int version = 0;
- try {
- ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.getPackageName(), 0);
- version = info.targetSdkVersion;
- } catch (NameNotFoundException ex) {
- Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
- }
+ // Using custom RemoteViews
if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
entry.row.setBackgroundResource(R.drawable.notification_row_legacy_bg);
} else if (version < Build.VERSION_CODES.L) {
@@ -903,6 +905,7 @@ public abstract class BaseStatusBar extends SystemUI implements
entry.row = row;
entry.row.setHeightRange(mRowMinHeight, mRowMaxHeight);
entry.row.setOnActivatedListener(this);
+ entry.row.setIsBelowSpeedBump(isBelowSpeedBump(entry.notification));
entry.expanded = contentViewLocal;
entry.expandedPublic = publicViewLocal;
entry.setBigContentView(bigContentViewLocal);
@@ -1065,8 +1068,8 @@ public abstract class BaseStatusBar extends SystemUI implements
if (DEBUG) {
Log.d(TAG, "addNotificationViews: added at " + pos);
}
- updateRowStates();
updateNotificationIcons();
+ updateRowStates();
}
private void addNotificationViews(IBinder key, StatusBarNotification notification) {
@@ -1086,6 +1089,7 @@ public abstract class BaseStatusBar extends SystemUI implements
mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
int n = mNotificationData.size();
int visibleNotifications = 0;
+ int speedBumpIndex = -1;
boolean onKeyguard = mState == StatusBarState.KEYGUARD;
for (int i = n-1; i >= 0; i--) {
NotificationData.Entry entry = mNotificationData.get(i);
@@ -1113,6 +1117,10 @@ public abstract class BaseStatusBar extends SystemUI implements
entry.row.setVisibility(View.VISIBLE);
visibleNotifications++;
}
+ if (entry.row.getVisibility() != View.GONE && speedBumpIndex == -1
+ && entry.row.isBelowSpeedBump() ) {
+ speedBumpIndex = n - 1 - i;
+ }
}
if (onKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
@@ -1120,6 +1128,8 @@ public abstract class BaseStatusBar extends SystemUI implements
} else {
mKeyguardIconOverflowContainer.setVisibility(View.GONE);
}
+
+ mStackScroller.updateSpeedBumpIndex(speedBumpIndex);
}
private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
@@ -1335,9 +1345,19 @@ public abstract class BaseStatusBar extends SystemUI implements
} else {
entry.row.setOnClickListener(null);
}
+ boolean wasBelow = entry.row.isBelowSpeedBump();
+ boolean nowBelow = isBelowSpeedBump(notification);
+ if (wasBelow != nowBelow) {
+ entry.row.setIsBelowSpeedBump(nowBelow);
+ }
entry.row.notifyContentUpdated();
}
+ private boolean isBelowSpeedBump(StatusBarNotification notification) {
+ return notification.getNotification().priority ==
+ Notification.PRIORITY_MIN;
+ }
+
protected void notifyHeadsUpScreenOn(boolean screenOn) {
if (!screenOn && mInterruptingNotificationEntry != null) {
mHandler.sendEmptyMessage(MSG_ESCALATE_HEADS_UP);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 39f2bb9..f6c80fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -52,6 +52,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
private NotificationContentView mPublicLayout;
private NotificationContentView mPrivateLayout;
private int mMaxExpandHeight;
+ private boolean mIsBelowSpeedBump;
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -244,6 +245,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
mPrivateLayout.setClipTopAmount(clipTopAmount);
}
+ public boolean isBelowSpeedBump() {
+ return mIsBelowSpeedBump;
+ }
+
+ public void setIsBelowSpeedBump(boolean isBelow) {
+ this.mIsBelowSpeedBump = isBelow;
+ }
+
public void notifyContentUpdated() {
mPrivateLayout.notifyContentUpdated();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 4bd0e1c..061396d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -40,11 +40,15 @@ public abstract class ExpandableView extends FrameLayout {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!mActualHeightInitialized && mActualHeight == 0) {
- mActualHeight = getHeight();
+ mActualHeight = getInitialHeight();
}
mActualHeightInitialized = true;
}
+ protected int getInitialHeight() {
+ return getHeight();
+ }
+
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (filterMotionEvent(ev)) {
@@ -146,6 +150,10 @@ public abstract class ExpandableView extends FrameLayout {
}
}
+ public boolean isTransparent() {
+ return false;
+ }
+
/**
* A listener notifying when {@link #getActualHeight} changes.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
index 6401695..9c39002 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
@@ -89,7 +89,7 @@ public class InterceptedNotifications {
return;
}
final Notification n = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.stat_sys_zen_limited)
+ .setSmallIcon(R.drawable.ic_qs_zen_on)
.setContentTitle(mContext.getResources().getQuantityString(
R.plurals.zen_mode_notification_title,
mIntercepted.size(), mIntercepted.size()))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java
new file mode 100644
index 0000000..3ca021a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.statusbar;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Outline;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * An single dot of the {@link com.android.systemui.statusbar.SpeedBumpDotsLayout}
+ */
+public class SpeedBumpDotView extends View {
+
+ private final Paint mPaint = new Paint();
+
+ public SpeedBumpDotView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mPaint.setAntiAlias(true);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ float radius = getWidth() / 2.0f;
+ canvas.drawCircle(radius, radius, radius, mPaint);
+ }
+
+ public void setColor(int color) {
+ mPaint.setColor(color);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsAlgorithm.java
new file mode 100644
index 0000000..cac6327
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsAlgorithm.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 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.statusbar;
+
+import android.content.Context;
+import android.view.View;
+import com.android.systemui.R;
+
+/**
+ * The Algorithm of the {@link com.android.systemui.statusbar.SpeedBumpDotsLayout} which can be
+ * queried for {@link * com.android.systemui.statusbar.SpeedBumpDotsState}
+ */
+public class SpeedBumpDotsAlgorithm {
+
+ private final float mDotRadius;
+
+ public SpeedBumpDotsAlgorithm(Context context) {
+ mDotRadius = context.getResources().getDimensionPixelSize(R.dimen.speed_bump_dots_height)
+ / 2.0f;
+ }
+
+ public void getState(SpeedBumpDotsState resultState) {
+
+ // First reset the current state and ensure that every View has a ViewState
+ resultState.resetViewStates();
+
+ SpeedBumpDotsLayout hostView = resultState.getHostView();
+ boolean currentlyVisible = hostView.isCurrentlyVisible();
+ resultState.setActiveState(currentlyVisible
+ ? SpeedBumpDotsState.SHOWN
+ : SpeedBumpDotsState.HIDDEN);
+ int hostWidth = hostView.getWidth();
+ float layoutWidth = hostWidth - 2 * mDotRadius;
+ int childCount = hostView.getChildCount();
+ float paddingBetween = layoutWidth / (childCount - 1);
+ float centerY = hostView.getHeight() / 2.0f;
+ for (int i = 0; i < childCount; i++) {
+ View child = hostView.getChildAt(i);
+ SpeedBumpDotsState.ViewState viewState = resultState.getViewStateForView(child);
+ if (currentlyVisible) {
+ float xTranslation = i * paddingBetween;
+ viewState.xTranslation = xTranslation;
+ viewState.yTranslation = calculateYTranslation(hostView, centerY, xTranslation,
+ layoutWidth);
+ } else {
+ viewState.xTranslation = layoutWidth / 2;
+ viewState.yTranslation = centerY - mDotRadius;
+ }
+ viewState.alpha = currentlyVisible ? 1.0f : 0.0f;
+ viewState.scale = currentlyVisible ? 1.0f : 0.5f;
+ }
+ }
+
+ private float calculateYTranslation(SpeedBumpDotsLayout hostView, float centerY,
+ float xTranslation, float layoutWidth) {
+ float t = hostView.getAnimationProgress();
+ if (t == 0.0f || t == 1.0f) {
+ return centerY - mDotRadius;
+ }
+ float damping = (0.5f -Math.abs(0.5f - t)) * 1.3f;
+ float partialOffset = xTranslation / layoutWidth;
+ float indentFactor = (float) (Math.sin((t + partialOffset * 1.5f) * - Math.PI) * damping);
+ return (1.0f - indentFactor) * centerY - mDotRadius;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsLayout.java
new file mode 100644
index 0000000..ddf5215
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsLayout.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2014 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.statusbar;
+
+import android.animation.TimeAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import com.android.systemui.R;
+
+/**
+ * A layout with a certain number of dots which are integrated in the
+ * {@link com.android.systemui.statusbar.SpeedBumpView}
+ */
+public class SpeedBumpDotsLayout extends ViewGroup {
+
+ private static final float DOT_CLICK_ANIMATION_LENGTH = 300;
+ private final int mDotSize;
+ private final SpeedBumpDotsAlgorithm mAlgorithm = new SpeedBumpDotsAlgorithm(getContext());
+ private final SpeedBumpDotsState mCurrentState = new SpeedBumpDotsState(this);
+ private boolean mIsCurrentlyVisible = true;
+ private final ValueAnimator mClickAnimator;
+ private float mAnimationProgress;
+ private ValueAnimator.AnimatorUpdateListener mClickUpdateListener
+ = new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mAnimationProgress = animation.getAnimatedFraction();
+ updateChildren();
+ }
+ };
+
+ public SpeedBumpDotsLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mDotSize = getResources().getDimensionPixelSize(R.dimen.speed_bump_dots_height);
+ createDots(context, attrs);
+ mClickAnimator = TimeAnimator.ofFloat(0, DOT_CLICK_ANIMATION_LENGTH);
+ mClickAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
+ mClickAnimator.addUpdateListener(mClickUpdateListener);
+ }
+
+ private void createDots(Context context, AttributeSet attrs) {
+ SpeedBumpDotView blueDot = new SpeedBumpDotView(context, attrs);
+ blueDot.setColor(getResources().getColor(R.color.speed_bump_dot_blue));
+ addView(blueDot);
+
+ SpeedBumpDotView redDot = new SpeedBumpDotView(context, attrs);
+ redDot.setColor(getResources().getColor(R.color.speed_bump_dot_red));
+ addView(redDot);
+
+ SpeedBumpDotView yellowDot = new SpeedBumpDotView(context, attrs);
+ yellowDot.setColor(getResources().getColor(R.color.speed_bump_dot_yellow));
+ addView(yellowDot);
+
+ SpeedBumpDotView greenDot = new SpeedBumpDotView(context, attrs);
+ greenDot.setColor(getResources().getColor(R.color.speed_bump_dot_green));
+ addView(greenDot);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int childWidthSpec = MeasureSpec.makeMeasureSpec(mDotSize,
+ MeasureSpec.getMode(widthMeasureSpec));
+ int childHeightSpec = MeasureSpec.makeMeasureSpec(mDotSize,
+ MeasureSpec.getMode(heightMeasureSpec));
+ measureChildren(childWidthSpec, childHeightSpec);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ child.layout(0, 0, mDotSize, mDotSize);
+ }
+ if (changed) {
+ updateChildren();
+ }
+ }
+
+ private void updateChildren() {
+ mAlgorithm.getState(mCurrentState);
+ mCurrentState.apply();
+ }
+
+ public void performVisibilityAnimation(boolean visible) {
+ if (mClickAnimator.isRunning()) {
+ mClickAnimator.cancel();
+ }
+ mIsCurrentlyVisible = visible;
+ mAlgorithm.getState(mCurrentState);
+ mCurrentState.animateToState();
+ }
+
+ public void setInvisible() {
+ mIsCurrentlyVisible = false;
+ mAlgorithm.getState(mCurrentState);
+ mCurrentState.apply();
+ }
+
+ public boolean isCurrentlyVisible() {
+ return mIsCurrentlyVisible;
+ }
+
+ public void performDotClickAnimation() {
+ if (mClickAnimator.isRunning()) {
+ // don't perform an animation if it's running already
+ return;
+ }
+ mClickAnimator.start();
+ }
+
+
+ public float getAnimationProgress() {
+ return mAnimationProgress;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java
new file mode 100644
index 0000000..06a7f95
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014 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.statusbar;
+
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A state of a {@link com.android.systemui.statusbar.SpeedBumpDotsLayout}
+ */
+public class SpeedBumpDotsState {
+
+ public static final int HIDDEN = 1;
+ public static final int SHOWN = 2;
+ private static final int VISIBILITY_ANIMATION_DELAY_PER_ELEMENT = 80;
+
+ private final SpeedBumpDotsLayout mHostView;
+ private final HashMap<View, ViewState> mStateMap = new HashMap<View, ViewState>();
+ private final Interpolator mFastOutSlowInInterpolator;
+ private int mActiveState = 0;
+
+ public SpeedBumpDotsState(SpeedBumpDotsLayout hostLayout) {
+ mHostView = hostLayout;
+ mFastOutSlowInInterpolator = AnimationUtils
+ .loadInterpolator(hostLayout.getContext(),
+ android.R.interpolator.fast_out_slow_in);
+ }
+
+ public SpeedBumpDotsLayout getHostView() {
+ return mHostView;
+ }
+
+ public void resetViewStates() {
+ int numChildren = mHostView.getChildCount();
+ for (int i = 0; i < numChildren; i++) {
+ View child = mHostView.getChildAt(i);
+ ViewState viewState = mStateMap.get(child);
+ if (viewState == null) {
+ viewState = new ViewState();
+ mStateMap.put(child, viewState);
+ }
+ }
+ }
+
+ public ViewState getViewStateForView(View requestedView) {
+ return mStateMap.get(requestedView);
+ }
+
+ public void apply() {
+ int childCount = mHostView.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = mHostView.getChildAt(i);
+ ViewState viewState = mStateMap.get(child);
+ float translationX = child.getTranslationX();
+ float translationY = child.getTranslationY();
+ float scale = child.getScaleX();
+ float alpha = child.getAlpha();
+ if (translationX != viewState.xTranslation) {
+ child.setTranslationX(viewState.xTranslation);
+ }
+ if (translationY != viewState.yTranslation) {
+ child.setTranslationY(viewState.yTranslation);
+ }
+ if (scale != viewState.scale) {
+ child.setScaleX(viewState.scale);
+ child.setScaleY(viewState.scale);
+ }
+ if (alpha != viewState.alpha) {
+ child.setAlpha(viewState.alpha);
+ }
+ }
+ }
+
+ public void animateToState() {
+ int childCount = mHostView.getChildCount();
+ int middleIndex = (childCount - 1) / 2;
+ long delayPerElement = VISIBILITY_ANIMATION_DELAY_PER_ELEMENT;
+ boolean isAppearing = getActiveState() == SHOWN;
+ boolean isDisappearing = getActiveState() == HIDDEN;
+ for (int i = 0; i < childCount; i++) {
+ int delayIndex;
+ if (i <= middleIndex) {
+ delayIndex = i * 2;
+ } else {
+ int distToMiddle = i - middleIndex;
+ delayIndex = (childCount - 1) - (distToMiddle - 1) * 2;
+ }
+ long startDelay = 0;
+ if (isAppearing || isDisappearing) {
+ if (isDisappearing) {
+ delayIndex = childCount - 1 - delayIndex;
+ }
+ startDelay = delayIndex * delayPerElement;
+ }
+ View child = mHostView.getChildAt(i);
+ ViewState viewState = mStateMap.get(child);
+ child.animate().setInterpolator(mFastOutSlowInInterpolator)
+ .setStartDelay(startDelay)
+ .alpha(viewState.alpha).withLayer()
+ .translationX(viewState.xTranslation)
+ .translationY(viewState.yTranslation)
+ .scaleX(viewState.scale).scaleY(viewState.scale);
+ }
+ }
+
+ public int getActiveState() {
+ return mActiveState;
+ }
+
+ public void setActiveState(int mActiveState) {
+ this.mActiveState = mActiveState;
+ }
+
+ public static class ViewState {
+ float xTranslation;
+ float yTranslation;
+ float alpha;
+ float scale;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
new file mode 100644
index 0000000..8ae503a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2014 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.statusbar;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Outline;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.TextView;
+import com.android.systemui.R;
+
+/**
+ * The view representing the separation between important and less important notifications
+ */
+public class SpeedBumpView extends ExpandableView implements View.OnClickListener {
+
+ private final int mCollapsedHeight;
+ private final int mDotsHeight;
+ private final int mTextPaddingInset;
+ private SpeedBumpDotsLayout mDots;
+ private View mLineLeft;
+ private View mLineRight;
+ private boolean mIsExpanded;
+ private boolean mDividerVisible = true;
+ private ValueAnimator mCurrentAnimator;
+ private final Interpolator mFastOutSlowInInterpolator;
+ private float mCenterX;
+ private TextView mExplanationText;
+ private boolean mExplanationTextVisible = false;
+ private AnimatorListenerAdapter mHideExplanationListener = new AnimatorListenerAdapter() {
+ private boolean mCancelled;
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mCancelled) {
+ mExplanationText.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mCancelled = false;
+ }
+ };
+ private Animator.AnimatorListener mAnimationFinishedListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mCurrentAnimator = null;
+ }
+ };
+
+ public SpeedBumpView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mCollapsedHeight = getResources()
+ .getDimensionPixelSize(R.dimen.speed_bump_height_collapsed);
+ mTextPaddingInset = getResources().getDimensionPixelSize(
+ R.dimen.speed_bump_text_padding_inset);
+ mDotsHeight = getResources().getDimensionPixelSize(R.dimen.speed_bump_dots_height);
+ setOnClickListener(this);
+ mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
+ android.R.interpolator.fast_out_slow_in);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mDots = (SpeedBumpDotsLayout) findViewById(R.id.speed_bump_dots_layout);
+ mLineLeft = findViewById(R.id.speedbump_line_left);
+ mLineRight = findViewById(R.id.speedbump_line_right);
+ mExplanationText = (TextView) findViewById(R.id.speed_bump_text);
+ resetExplanationText();
+
+ }
+
+ @Override
+ protected int getInitialHeight() {
+ return mCollapsedHeight;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return getActualHeight();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ Outline outline = new Outline();
+ mCenterX = getWidth() / 2;
+ float centerY = getHeight() / 2;
+ // TODO: hide outline better
+ // Temporary workaround to hide outline on a transparent view
+ int outlineLeft = (int) (mCenterX - getResources().getDisplayMetrics().densityDpi * 8);
+ int outlineTop = (int) (centerY - mDotsHeight / 2);
+ outline.setOval(outlineLeft, outlineTop, outlineLeft + mDotsHeight,
+ outlineTop + mDotsHeight);
+ setOutline(outline);
+ mLineLeft.setPivotX(mLineLeft.getWidth());
+ mLineLeft.setPivotY(mLineLeft.getHeight() / 2);
+ mLineRight.setPivotX(0);
+ mLineRight.setPivotY(mLineRight.getHeight() / 2);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ measureChildren(widthMeasureSpec, heightMeasureSpec);
+ int height = mCollapsedHeight + mExplanationText.getMeasuredHeight() - mTextPaddingInset;
+ setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mCurrentAnimator != null) {
+ return;
+ }
+ int startValue = mIsExpanded ? getMaxHeight() : mCollapsedHeight;
+ int endValue = mIsExpanded ? mCollapsedHeight : getMaxHeight();
+ mCurrentAnimator = ValueAnimator.ofInt(startValue, endValue);
+ mCurrentAnimator.setInterpolator(mFastOutSlowInInterpolator);
+ mCurrentAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ setActualHeight((int) animation.getAnimatedValue());
+ }
+ });
+ mCurrentAnimator.addListener(mAnimationFinishedListener);
+ mCurrentAnimator.start();
+ mIsExpanded = !mIsExpanded;
+ mDots.performDotClickAnimation();
+ animateExplanationTextInternal(mIsExpanded);
+ }
+
+ private void animateExplanationTextInternal(boolean visible) {
+ if (mExplanationTextVisible != visible) {
+ float translationY = 0.0f;
+ float scale = 0.5f;
+ float alpha = 0.0f;
+ boolean needsHideListener = true;
+ if (visible) {
+ mExplanationText.setVisibility(VISIBLE);
+ translationY = mDots.getBottom() - mTextPaddingInset;
+ scale = 1.0f;
+ alpha = 1.0f;
+ needsHideListener = false;
+ }
+ mExplanationText.animate().setInterpolator(mFastOutSlowInInterpolator)
+ .alpha(alpha)
+ .scaleX(scale)
+ .scaleY(scale)
+ .translationY(translationY)
+ .setListener(needsHideListener ? mHideExplanationListener : null)
+ .withLayer();
+ mExplanationTextVisible = visible;
+ }
+ }
+
+ @Override
+ public boolean isTransparent() {
+ return true;
+ }
+
+ public void performVisibilityAnimation(boolean nowVisible) {
+ animateDivider(nowVisible);
+
+ // Animate explanation Text
+ if (mIsExpanded) {
+ animateExplanationTextInternal(nowVisible);
+ }
+ }
+
+ public void animateDivider(boolean nowVisible) {
+ if (nowVisible != mDividerVisible) {
+ // Animate dividers
+ float endValue = nowVisible ? 1.0f : 0.0f;
+ float endTranslationXLeft = nowVisible ? 0.0f : mCenterX - mLineLeft.getRight();
+ float endTranslationXRight = nowVisible ? 0.0f : mCenterX - mLineRight.getLeft();
+ mLineLeft.animate()
+ .alpha(endValue)
+ .withLayer()
+ .scaleX(endValue)
+ .scaleY(endValue)
+ .translationX(endTranslationXLeft)
+ .setInterpolator(mFastOutSlowInInterpolator);
+ mLineRight.animate()
+ .alpha(endValue)
+ .withLayer()
+ .scaleX(endValue)
+ .scaleY(endValue)
+ .translationX(endTranslationXRight)
+ .setInterpolator(mFastOutSlowInInterpolator);
+
+ // Animate dots
+ mDots.performVisibilityAnimation(nowVisible);
+ mDividerVisible = nowVisible;
+ }
+ }
+
+ public void setInvisible() {
+ float endTranslationXLeft = mCenterX - mLineLeft.getRight();
+ float endTranslationXRight = mCenterX - mLineRight.getLeft();
+ mLineLeft.setAlpha(0.0f);
+ mLineLeft.setScaleX(0.0f);
+ mLineLeft.setScaleY(0.0f);
+ mLineLeft.setTranslationX(endTranslationXLeft);
+ mLineRight.setAlpha(0.0f);
+ mLineRight.setScaleX(0.0f);
+ mLineRight.setScaleY(0.0f);
+ mLineRight.setTranslationX(endTranslationXRight);
+ mDots.setInvisible();
+ resetExplanationText();
+
+ mDividerVisible = false;
+ }
+
+ public void collapse() {
+ if (mIsExpanded) {
+ setActualHeight(mCollapsedHeight);
+ mIsExpanded = false;
+ }
+ resetExplanationText();
+ }
+
+ public void animateExplanationText(boolean nowVisible) {
+ if (mIsExpanded) {
+ animateExplanationTextInternal(nowVisible);
+ }
+ }
+
+ private void resetExplanationText() {
+ mExplanationText.setTranslationY(0);
+ mExplanationText.setVisibility(INVISIBLE);
+ mExplanationText.setAlpha(0.0f);
+ mExplanationText.setScaleX(0.5f);
+ mExplanationText.setScaleY(0.5f);
+ mExplanationTextVisible = false;
+ }
+
+ public boolean isExpanded() {
+ return mIsExpanded;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index eb63a54..a41ec22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -43,6 +43,7 @@ public class BarTransitions {
public static final int MODE_SEMI_TRANSPARENT = 1;
public static final int MODE_TRANSLUCENT = 2;
public static final int MODE_LIGHTS_OUT = 3;
+ public static final int MODE_TRANSPARENT = 4;
public static final int LIGHTS_IN_DURATION = 250;
public static final int LIGHTS_OUT_DURATION = 750;
@@ -69,7 +70,8 @@ public class BarTransitions {
public void transitionTo(int mode, boolean animate) {
// low-end devices do not support translucent modes, fallback to opaque
- if (!HIGH_END && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT)) {
+ if (!HIGH_END && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
+ || mode == MODE_TRANSPARENT)) {
mode = MODE_OPAQUE;
}
if (mMode == mode) return;
@@ -97,6 +99,7 @@ public class BarTransitions {
if (mode == MODE_SEMI_TRANSPARENT) return "MODE_SEMI_TRANSPARENT";
if (mode == MODE_TRANSLUCENT) return "MODE_TRANSLUCENT";
if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT";
+ if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT";
throw new IllegalArgumentException("Unknown mode " + mode);
}
@@ -111,6 +114,7 @@ public class BarTransitions {
private static class BarBackgroundDrawable extends Drawable {
private final int mOpaque;
private final int mSemiTransparent;
+ private final int mTransparent;
private final Drawable mGradient;
private final TimeInterpolator mInterpolator;
@@ -130,9 +134,11 @@ public class BarTransitions {
if (DEBUG_COLORS) {
mOpaque = 0xff0000ff;
mSemiTransparent = 0x7f0000ff;
+ mTransparent = 0x2f0000ff;
} else {
mOpaque = res.getColor(R.color.system_bar_background_opaque);
mSemiTransparent = res.getColor(R.color.system_bar_background_semi_transparent);
+ mTransparent = res.getColor(R.color.system_bar_background_transparent);
}
mGradient = res.getDrawable(gradientResourceId);
mInterpolator = new LinearInterpolator();
@@ -184,9 +190,11 @@ public class BarTransitions {
public void draw(Canvas canvas) {
int targetGradientAlpha = 0, targetColor = 0;
if (mMode == MODE_TRANSLUCENT) {
- targetGradientAlpha = 0xff;
+ targetColor = mSemiTransparent;
} else if (mMode == MODE_SEMI_TRANSPARENT) {
targetColor = mSemiTransparent;
+ } else if (mMode == MODE_TRANSPARENT) {
+ targetColor = mTransparent;
} else {
targetColor = mOpaque;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 869edff..0a3fdef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -60,7 +60,8 @@ public class DemoStatusIcons extends LinearLayout implements DemoMode {
} else if (mDemoMode && command.equals(COMMAND_STATUS)) {
String volume = args.getString("volume");
if (volume != null) {
- int iconId = volume.equals("silent") ? R.drawable.stat_sys_ringer_silent
+ int iconId = volume.equals("zen") ? R.drawable.stat_sys_ringer_zen
+ : volume.equals("silent") ? R.drawable.stat_sys_ringer_silent
: volume.equals("vibrate") ? R.drawable.stat_sys_ringer_vibrate
: 0;
updateSlot("volume", null, iconId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index a0582ee..c83b479 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -61,7 +61,7 @@ public final class NavigationBarTransitions extends BarTransitions {
@Override
public void transitionTo(int mode, boolean animate) {
mRequestedMode = mode;
- if (mVertical && mode == MODE_TRANSLUCENT) {
+ if (mVertical && (mode == MODE_TRANSLUCENT || mode == MODE_TRANSPARENT)) {
// translucent mode not allowed when vertical
mode = MODE_OPAQUE;
}
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 b9f5ab2..19252c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
@@ -25,6 +27,7 @@ import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -36,12 +39,11 @@ import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
public class NotificationPanelView extends PanelView implements
ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
View.OnClickListener {
- public static final boolean DEBUG_GESTURES = true;
- private static final int EXPANSION_ANIMATION_LENGTH = 375;
PhoneStatusBar mStatusBar;
private StatusBarHeaderView mHeader;
@@ -80,6 +82,20 @@ public class NotificationPanelView extends PanelView implements
private FlingAnimationUtils mFlingAnimationUtils;
private int mStatusBarMinHeight;
+ private int mClockNotificationsMarginMin;
+ private int mClockNotificationsMarginMax;
+ private float mClockYFractionMin;
+ private float mClockYFractionMax;
+ private Interpolator mFastOutSlowInInterpolator;
+ private ObjectAnimator mClockAnimator;
+ private int mClockAnimationTarget = -1;
+
+ /**
+ * The number (fractional) of notifications the "more" card counts when calculating how many
+ * notifications are currently visible for the y positioning of the clock.
+ */
+ private float mMoreCardNotificationAmount;
+
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -113,9 +129,27 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller = (NotificationStackScrollLayout)
findViewById(R.id.notification_stack_scroller);
mNotificationStackScroller.setOnHeightChangedListener(this);
+ mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
+ android.R.interpolator.fast_out_slow_in);
+ }
+
+ @Override
+ protected void loadDimens() {
+ super.loadDimens();
mNotificationTopPadding = getResources().getDimensionPixelSize(
R.dimen.notifications_top_padding);
mMinStackHeight = getResources().getDimensionPixelSize(R.dimen.collapsed_stack_height);
+ mClockNotificationsMarginMin = getResources().getDimensionPixelSize(
+ R.dimen.keyguard_clock_notifications_margin_min);
+ mClockNotificationsMarginMax = getResources().getDimensionPixelSize(
+ R.dimen.keyguard_clock_notifications_margin_max);
+ mClockYFractionMin =
+ getResources().getFraction(R.fraction.keyguard_clock_y_fraction_min, 1, 1);
+ mClockYFractionMax =
+ getResources().getFraction(R.fraction.keyguard_clock_y_fraction_max, 1, 1);
+ mMoreCardNotificationAmount =
+ (float) getResources().getDimensionPixelSize(R.dimen.notification_summary_height) /
+ getResources().getDimensionPixelSize(R.dimen.notification_min_height);
mFlingAnimationUtils = new FlingAnimationUtils(getContext());
mStatusBarMinHeight = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
@@ -124,15 +158,8 @@ public class NotificationPanelView extends PanelView implements
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- int keyguardBottomMargin =
- ((MarginLayoutParams) mKeyguardStatusView.getLayoutParams()).bottomMargin;
if (!mQsExpanded) {
- mStackScrollerIntrinsicPadding = mStatusBar.getBarState() == StatusBarState.KEYGUARD
- ? mKeyguardStatusView.getBottom() + keyguardBottomMargin
- : mHeader.getBottom() + mNotificationTopPadding;
- mNotificationStackScroller.setTopPadding(mStackScrollerIntrinsicPadding,
- mAnimateNextTopPaddingChange);
- mAnimateNextTopPaddingChange = false;
+ positionClockAndNotifications();
}
// Calculate quick setting heights.
@@ -143,8 +170,81 @@ public class NotificationPanelView extends PanelView implements
}
}
- public void animateNextTopPaddingChange() {
+ /**
+ * Positions the clock and notifications dynamically depending on how many notifications are
+ * showing.
+ */
+ private void positionClockAndNotifications() {
+ boolean animateClock = mNotificationStackScroller.isAddOrRemoveAnimationPending();
+ if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+ mStackScrollerIntrinsicPadding = mHeader.getBottom() + mNotificationTopPadding;
+ } else {
+ int notificationCount = mNotificationStackScroller.getNotGoneChildCount();
+ int y = getClockY(notificationCount) - mKeyguardStatusView.getHeight()/2;
+ int padding = getClockNotificationsPadding(notificationCount);
+ if (animateClock || mClockAnimator != null) {
+ startClockAnimation(y);
+ } else {
+ mKeyguardStatusView.setY(y);
+ }
+ mStackScrollerIntrinsicPadding = y + mKeyguardStatusView.getHeight() + padding;
+ }
+ mNotificationStackScroller.setTopPadding(mStackScrollerIntrinsicPadding,
+ mAnimateNextTopPaddingChange || animateClock);
+ mAnimateNextTopPaddingChange = false;
+ }
+
+ private void startClockAnimation(int y) {
+ if (mClockAnimationTarget == y) {
+ return;
+ }
+ mClockAnimationTarget = y;
+ getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ getViewTreeObserver().removeOnPreDrawListener(this);
+ if (mClockAnimator != null) {
+ mClockAnimator.removeAllListeners();
+ mClockAnimator.cancel();
+ }
+ mClockAnimator =
+ ObjectAnimator.ofFloat(mKeyguardStatusView, View.Y, mClockAnimationTarget);
+ mClockAnimator.setInterpolator(mFastOutSlowInInterpolator);
+ mClockAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ mClockAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mClockAnimator = null;
+ mClockAnimationTarget = -1;
+ }
+ });
+ StackStateAnimator.startInstantly(mClockAnimator);
+ return true;
+ }
+ });
+ }
+
+ private int getClockNotificationsPadding(int notificationCount) {
+ float t = notificationCount
+ / (mStatusBar.getMaxKeyguardNotifications() + mMoreCardNotificationAmount);
+ t = Math.min(t, 1.0f);
+ return (int) (t * mClockNotificationsMarginMin + (1 - t) * mClockNotificationsMarginMax);
+ }
+
+ private float getClockYFraction(int notificationCount) {
+ float t = notificationCount
+ / (mStatusBar.getMaxKeyguardNotifications() + mMoreCardNotificationAmount);
+ t = Math.min(t, 1.0f);
+ return (1 - t) * mClockYFractionMax + t * mClockYFractionMin;
+ }
+
+ private int getClockY(int notificationCount) {
+ return (int) (getClockYFraction(notificationCount) * getHeight());
+ }
+
+ public void animateToFullShade() {
mAnimateNextTopPaddingChange = true;
+ mNotificationStackScroller.goToFullShade();
requestLayout();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 8c70517..517f763 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -20,6 +20,7 @@ import android.animation.ObjectAnimator;
import android.animation.TimeAnimator;
import android.animation.TimeAnimator.TimeListener;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.Log;
@@ -218,7 +219,7 @@ public class PanelView extends FrameLayout {
};
private float mVel, mAccel;
- protected int mMaxPanelHeight = 0;
+ protected int mMaxPanelHeight = -1;
private String mViewName;
private float mInitialTouchY;
private float mInitialTouchX;
@@ -321,7 +322,7 @@ public class PanelView extends FrameLayout {
setOnHierarchyChangeListener(mHierarchyListener);
}
- private void loadDimens() {
+ protected void loadDimens() {
final Resources res = getContext().getResources();
mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
@@ -582,8 +583,14 @@ public class PanelView extends FrameLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ loadDimens();
+ }
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
loadDimens();
+ mMaxPanelHeight = -1;
}
public void fling(float vel, boolean always) {
@@ -617,7 +624,8 @@ public class PanelView extends FrameLayout {
// Did one of our children change size?
int newHeight = getMeasuredHeight();
- if (newHeight != mMaxPanelHeight) {
+ if (newHeight > mMaxPanelHeight) {
+ // we only adapt the max height if it's bigger
mMaxPanelHeight = newHeight;
// If the user isn't actively poking us, let's rubberband to the content
if (!mTracking && !mTimeAnimator.isStarted()
@@ -706,6 +714,7 @@ public class PanelView extends FrameLayout {
* @return the default implementation simply returns the maximum height.
*/
protected int getMaxPanelHeight() {
+ mMaxPanelHeight = Math.max(mMaxPanelHeight, getHeight());
return mMaxPanelHeight;
}
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 842627c..1072e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -26,6 +26,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OU
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -105,6 +106,7 @@ import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.NotificationOverflowContainer;
import com.android.systemui.statusbar.SignalClusterView;
+import com.android.systemui.statusbar.SpeedBumpView;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -221,8 +223,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
IconMerger mNotificationIcons;
// [+>
View mMoreIcon;
- // mode indicator icon
- ImageView mModeIcon;
// expanded notifications
NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -486,13 +486,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void setZenMode(int mode) {
super.setZenMode(mode);
- if (mModeIcon == null) return;
if (!isDeviceProvisioned()) return;
final boolean zen = mode != Settings.Global.ZEN_MODE_OFF;
- mModeIcon.setVisibility(zen ? View.VISIBLE : View.GONE);
if (!zen) {
mIntercepted.releaseIntercepted();
}
+ if (mIconPolicy != null) {
+ mIconPolicy.setZenMode(zen);
+ }
}
@Override
@@ -616,8 +617,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
- mModeIcon = (ImageView)mStatusBarView.findViewById(R.id.modeIcon);
- mModeIcon.setImageResource(R.drawable.stat_sys_zen_limited);
mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
mTickerView = mStatusBarView.findViewById(R.id.ticker);
@@ -633,6 +632,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
mStackScroller.addView(mKeyguardIconOverflowContainer);
+ SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate(
+ R.layout.status_bar_notification_speed_bump, mStackScroller, false);
+ mStackScroller.setSpeedBumpView(speedBump);
+
mExpandedContents = mStackScroller;
mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
@@ -1149,7 +1152,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
ArrayList<View> toRemove = new ArrayList<View>();
for (int i=0; i< mStackScroller.getChildCount(); i++) {
View child = mStackScroller.getChildAt(i);
- if (!toShow.contains(child) && child != mKeyguardIconOverflowContainer) {
+ if (!toShow.contains(child) && child instanceof ExpandableNotificationRow) {
toRemove.add(child);
}
}
@@ -1870,6 +1873,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private int barMode(int vis, int transientFlag, int translucentFlag) {
return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT
: (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT
+ : (vis & View.SYSTEM_UI_TRANSPARENT) != 0 ? MODE_TRANSPARENT
: (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT
: MODE_OPAQUE;
}
@@ -2558,13 +2562,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|| (mDisabled & StatusBarManager.DISABLE_SEARCH) != 0;
}
- public void postStartSettingsActivity(final Intent intent) {
- mHandler.post(new Runnable() {
+ public void postStartSettingsActivity(final Intent intent, int delay) {
+ mHandler.postDelayed(new Runnable() {
@Override
public void run() {
handleStartSettingsActivity(intent, true /*onlyProvisioned*/);
}
- });
+ }, delay);
}
private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
@@ -2580,7 +2584,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
public void startSettingsActivity(String action) {
- postStartSettingsActivity(new Intent(action));
+ postStartSettingsActivity(new Intent(action), 0);
}
private static class FastColorDrawable extends Drawable {
@@ -2720,7 +2724,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
setBarState(StatusBarState.SHADE);
if (mLeaveOpenOnKeyguardHide) {
mLeaveOpenOnKeyguardHide = false;
- mNotificationPanel.animateNextTopPaddingChange();
+ mNotificationPanel.animateToFullShade();
} else {
instantCollapseNotificationPanel();
}
@@ -2892,7 +2896,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mLeaveOpenOnKeyguardHide = true;
showBouncer();
} else {
- mNotificationPanel.animateNextTopPaddingChange();
+ mNotificationPanel.animateToFullShade();
setBarState(StatusBarState.SHADE_LOCKED);
updateKeyguardState();
}
@@ -2915,4 +2919,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void reattachSystemIcons() {
mSystemIconArea.addView(mSystemIcons, 0);
}
+
+ public void onScreenTurnedOff() {
+ mStackScroller.setAnimationsEnabled(false);
+ }
+
+ public void onScreenTurnedOn() {
+ mStackScroller.setAnimationsEnabled(true);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 194774d..b6f5ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -63,6 +63,9 @@ public class PhoneStatusBarPolicy {
// ringer volume
private boolean mVolumeVisible;
+ // zen mode
+ private boolean mZen;
+
// bluetooth device status
private boolean mBluetoothEnabled = false;
@@ -152,6 +155,11 @@ public class PhoneStatusBarPolicy {
updateVolume();
}
+ public void setZenMode(boolean zen) {
+ mZen = zen;
+ updateVolume();
+ }
+
private final void updateAlarm(Intent intent) {
boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
mService.setIconVisibility("alarm_clock", alarmSet);
@@ -195,11 +203,15 @@ public class PhoneStatusBarPolicy {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
final int ringerMode = audioManager.getRingerMode();
final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
- ringerMode == AudioManager.RINGER_MODE_VIBRATE;
+ ringerMode == AudioManager.RINGER_MODE_VIBRATE ||
+ mZen;
final int iconId;
String contentDescription = null;
- if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ if (mZen) {
+ iconId = R.drawable.stat_sys_ringer_zen;
+ contentDescription = mContext.getString(R.string.zen_mode_title);
+ } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
iconId = R.drawable.stat_sys_ringer_vibrate;
contentDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
index 8406565..8520f40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
@@ -68,7 +68,8 @@ public final class PhoneStatusBarTransitions extends BarTransitions {
}
private boolean isOpaque(int mode) {
- return !(mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT);
+ return !(mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
+ || mode == MODE_TRANSPARENT);
}
@Override
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 1fe3be5..7029898 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.content.Intent;
-import android.graphics.drawable.VectorDrawable;
import android.os.HandlerThread;
import android.os.Looper;
@@ -113,7 +112,7 @@ public class QSTileHost implements QSTile.Host {
@Override
public void startSettingsActivity(final Intent intent) {
- mStatusBar.postStartSettingsActivity(intent);
+ mStatusBar.postStartSettingsActivity(intent, QSTile.FEEDBACK_START_DELAY);
}
@Override
@@ -137,11 +136,6 @@ public class QSTileHost implements QSTile.Host {
}
@Override
- public VectorDrawable getVectorDrawable(int resId) {
- return (VectorDrawable) mContext.getDrawable(resId);
- }
-
- @Override
public BluetoothController getBluetoothController() {
return mBluetooth;
}
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 2305445..36b063b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -86,6 +86,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
(ImageView) findViewById(R.id.brightness_icon),
(ToggleSlider) findViewById(R.id.brightness_slider));
loadDimens();
+ updateVisibilities();
}
private void loadDimens() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 77b760e..1040c15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -125,11 +125,13 @@ public class StatusBarKeyguardViewManager {
public void onScreenTurnedOff() {
mScreenOn = false;
+ mPhoneStatusBar.onScreenTurnedOff();
mBouncer.onScreenTurnedOff();
}
public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
mScreenOn = true;
+ mPhoneStatusBar.onScreenTurnedOn();
if (callback != null) {
callbackAfterDraw(callback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 46a637b..b7bf6cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -75,8 +75,7 @@ public class StatusBarWindowManager {
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+ | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
PixelFormat.TRANSLUCENT);
mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
mLp.gravity = Gravity.TOP;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 1c7119f..5a19881 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -59,6 +59,7 @@ public class BluetoothControllerImpl extends BroadcastReceiver implements Blueto
public void addStateChangedCallback(BluetoothStateChangeCallback cb) {
mChangeCallbacks.add(cb);
+ fireCallback(cb);
}
@Override
@@ -131,7 +132,11 @@ public class BluetoothControllerImpl extends BroadcastReceiver implements Blueto
private void fireCallbacks() {
for (BluetoothStateChangeCallback cb : mChangeCallbacks) {
- cb.onBluetoothStateChange(mEnabled);
+ fireCallback(cb);
}
}
+
+ private void fireCallback(BluetoothStateChangeCallback cb) {
+ cb.onBluetoothStateChange(mEnabled);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 33a85b1..bcd865c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -28,6 +28,10 @@ public class CastControllerImpl implements CastController {
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final MediaRouter mMediaRouter;
+ private boolean mEnabled;
+ private boolean mConnecting;
+ private String mConnectedRouteName;
+
public CastControllerImpl(Context context) {
mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
}
@@ -35,6 +39,7 @@ public class CastControllerImpl implements CastController {
@Override
public void addCallback(Callback callback) {
mCallbacks.add(callback);
+ fireStateChanged(callback);
}
@Override
@@ -76,12 +81,23 @@ public class CastControllerImpl implements CastController {
if (connectedRoute != null) {
connectedRouteName = connectedRoute.getName().toString();
}
- fireStateChanged(enabled, connecting, connectedRouteName);
+ synchronized(mCallbacks) {
+ mEnabled = enabled;
+ mConnecting = connecting;
+ mConnectedRouteName = connectedRouteName;
+ }
+ fireStateChanged();
}
- private void fireStateChanged(boolean enabled, boolean connecting, String connectedRouteName) {
+ private void fireStateChanged() {
for (Callback callback : mCallbacks) {
- callback.onStateChanged(enabled, connecting, connectedRouteName);
+ fireStateChanged(callback);
+ }
+ }
+
+ private void fireStateChanged(Callback callback) {
+ synchronized(mCallbacks) {
+ callback.onStateChanged(mEnabled, mConnecting, mConnectedRouteName);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Listenable.java
index 158e9c1..4fa59fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Listenable.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.policy;
-/** Common interface for items requiring manual cleanup. **/
-public interface Disposable {
- void dispose();
+/** Common interface for components with an active listening state. **/
+public interface Listenable {
+ void setListening(boolean listening);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 9e5ad18..d5b2548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -92,6 +92,7 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
*/
public void addSettingsChangedCallback(LocationSettingsChangeCallback cb) {
mSettingsChangeCallbacks.add(cb);
+ locationSettingsChanged(cb);
}
public void removeSettingsChangedCallback(LocationSettingsChangeCallback cb) {
@@ -204,6 +205,10 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
}
}
+ private void locationSettingsChanged(LocationSettingsChangeCallback cb) {
+ cb.onLocationSettingsChanged(isLocationEnabled());
+ }
+
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
index 1eb678d..93c4691 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.policy;
-public interface RotationLockController extends Disposable {
+public interface RotationLockController extends Listenable {
int getRotationLockOrientation();
boolean isRotationLockAffordanceVisible();
boolean isRotationLocked();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
index caa07ef..c3bcd94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
@@ -39,12 +39,12 @@ public final class RotationLockControllerImpl implements RotationLockController
public RotationLockControllerImpl(Context context) {
mContext = context;
- RotationPolicy.registerRotationPolicyListener(mContext,
- mRotationPolicyListener, UserHandle.USER_ALL);
+ setListening(true);
}
public void addRotationLockControllerCallback(RotationLockControllerCallback callback) {
mCallbacks.add(callback);
+ notifyChanged(callback);
}
public void removeRotationLockControllerCallback(RotationLockControllerCallback callback) {
@@ -68,14 +68,23 @@ public final class RotationLockControllerImpl implements RotationLockController
}
@Override
- public void dispose() {
- RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
+ public void setListening(boolean listening) {
+ if (listening) {
+ RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener,
+ UserHandle.USER_ALL);
+ } else {
+ RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
+ }
}
private void notifyChanged() {
for (RotationLockControllerCallback callback : mCallbacks) {
- callback.onRotationLockStateChanged(RotationPolicy.isRotationLocked(mContext),
- RotationPolicy.isRotationLockToggleVisible(mContext));
+ notifyChanged(callback);
}
}
+
+ private void notifyChanged(RotationLockControllerCallback callback) {
+ callback.onRotationLockStateChanged(RotationPolicy.isRotationLocked(mContext),
+ RotationPolicy.isRotationLockToggleVisible(mContext));
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index d760f78..adf2935 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -52,6 +52,7 @@ public class ZenModeControllerImpl implements ZenModeController {
fireZenChanged(value != 0);
}
};
+ mSetting.setListening(true);
mNoMan = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index deab757..b21e12c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -30,6 +30,7 @@ public class AmbientState {
private View mActivatedChild;
private float mOverScrollTopAmount;
private float mOverScrollBottomAmount;
+ private int mSpeedBumpIndex = -1;
public int getScrollY() {
return mScrollY;
@@ -86,4 +87,12 @@ public class AmbientState {
public float getOverScrollAmount(boolean top) {
return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
}
+
+ public int getSpeedBumpIndex() {
+ return mSpeedBumpIndex;
+ }
+
+ public void setSpeedBumpIndex(int speedBumpIndex) {
+ mSpeedBumpIndex = speedBumpIndex;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index fbb6695..58ada75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -39,6 +39,7 @@ import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.SpeedBumpView;
import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
import com.android.systemui.statusbar.policy.ScrollAdapter;
@@ -107,6 +108,7 @@ public class NotificationStackScrollLayout extends ViewGroup
= new ArrayList<AnimationEvent>();
private ArrayList<View> mSwipedOutViews = new ArrayList<View>();
private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
+ private boolean mAnimationsEnabled;
/**
* The raw amount of the overScroll on the top, which is not rubber-banded.
@@ -126,6 +128,8 @@ public class NotificationStackScrollLayout extends ViewGroup
private boolean mActivateNeedsAnimation;
private boolean mIsExpanded = true;
private boolean mChildrenUpdateRequested;
+ private SpeedBumpView mSpeedBumpView;
+ private boolean mIsExpansionChanging;
private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
= new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -244,6 +248,22 @@ public class NotificationStackScrollLayout extends ViewGroup
requestChildrenUpdate();
}
+ public void updateSpeedBumpIndex(int newIndex) {
+ int currentIndex = indexOfChild(mSpeedBumpView);
+
+ // If we are currently layouted before the new speed bump index, we have to decrease it.
+ boolean validIndex = newIndex > 0;
+ if (newIndex > getChildCount() - 1) {
+ validIndex = false;
+ newIndex = -1;
+ }
+ if (validIndex && currentIndex != newIndex) {
+ changeViewPosition(mSpeedBumpView, newIndex);
+ }
+ updateSpeedBump(validIndex);
+ mAmbientState.setSpeedBumpIndex(newIndex);
+ }
+
public void setChildLocationsChangedListener(OnChildLocationsChangedListener listener) {
mListener = listener;
}
@@ -333,7 +353,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mTopPadding = topPadding;
updateAlgorithmHeightAndPadding();
updateContentHeight();
- if (animate) {
+ if (animate && mAnimationsEnabled && mIsExpanded) {
mTopPaddingNeedsAnimation = true;
mNeedsAnimation = true;
}
@@ -421,9 +441,11 @@ public class NotificationStackScrollLayout extends ViewGroup
public void onChildSnappedBack(View animView) {
mAmbientState.onDragFinished(animView);
if (!mDragAnimPendingChildren.contains(animView)) {
- mSnappedBackChildren.add(animView);
+ if (mAnimationsEnabled) {
+ mSnappedBackChildren.add(animView);
+ mNeedsAnimation = true;
+ }
requestChildrenUpdate();
- mNeedsAnimation = true;
} else {
// We start the swipe and snap back in the same frame, we don't want any animation
mDragAnimPendingChildren.remove(animView);
@@ -432,10 +454,12 @@ public class NotificationStackScrollLayout extends ViewGroup
public void onBeginDrag(View v) {
setSwipingInProgress(true);
- mDragAnimPendingChildren.add(v);
mAmbientState.onBeginDrag(v);
+ if (mAnimationsEnabled) {
+ mDragAnimPendingChildren.add(v);
+ mNeedsAnimation = true;
+ }
requestChildrenUpdate();
- mNeedsAnimation = true;
}
public void onDragCancelled(View v) {
@@ -942,6 +966,21 @@ public class NotificationStackScrollLayout extends ViewGroup
return null;
}
+ /**
+ * @return the number of children which have visibility unequal to GONE
+ */
+ public int getNotGoneChildCount() {
+ int childCount = getChildCount();
+ int count = 0;
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child.getVisibility() != View.GONE) {
+ count++;
+ }
+ }
+ return count;
+ }
+
private int getMaxExpandHeight(View view) {
if (view instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
@@ -1044,8 +1083,11 @@ public class NotificationStackScrollLayout extends ViewGroup
mCurrentStackScrollState.removeViewStateForView(child);
mStackScrollAlgorithm.notifyChildrenChanged(this);
updateScrollStateForRemovedChild(child);
- if (mIsExpanded) {
+ generateRemoveAnimation(child);
+ }
+ private void generateRemoveAnimation(View child) {
+ if (mIsExpanded && mAnimationsEnabled) {
if (!mChildrenToAddAnimated.contains(child)) {
// Generate Animations
mChildrenToRemoveAnimated.add(child);
@@ -1103,8 +1145,17 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ public void setAnimationsEnabled(boolean animationsEnabled) {
+ mAnimationsEnabled = animationsEnabled;
+ }
+
+ public boolean isAddOrRemoveAnimationPending() {
+ return mNeedsAnimation
+ && (!mChildrenToAddAnimated.isEmpty() || !mChildrenToRemoveAnimated.isEmpty());
+ }
+
public void generateAddAnimation(View child) {
- if (mIsExpanded) {
+ if (mIsExpanded && mAnimationsEnabled) {
// Generate Animations
mChildrenToAddAnimated.add(child);
@@ -1120,7 +1171,9 @@ public class NotificationStackScrollLayout extends ViewGroup
*/
public void changeViewPosition(View child, int newIndex) {
if (child != null && child.getParent() == this) {
- // TODO: handle this
+ removeView(child);
+ addView(child, newIndex);
+ // TODO: handle events
}
}
@@ -1362,10 +1415,12 @@ public class NotificationStackScrollLayout extends ViewGroup
}
public void onExpansionStarted() {
+ mIsExpansionChanging = true;
mStackScrollAlgorithm.onExpansionStarted(mCurrentStackScrollState);
}
public void onExpansionStopped() {
+ mIsExpansionChanging = false;
mStackScrollAlgorithm.onExpansionStopped();
}
@@ -1374,6 +1429,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mStackScrollAlgorithm.setIsExpanded(isExpanded);
if (!isExpanded) {
mOwnScrollY = 0;
+ mSpeedBumpView.collapse();
}
}
@@ -1404,7 +1460,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mStackScrollAlgorithm.setDimmed(dimmed);
mAmbientState.setDimmed(dimmed);
updatePadding(dimmed);
- if (animate) {
+ if (animate && mAnimationsEnabled) {
mDimmedNeedsAnimation = true;
mNeedsAnimation = true;
}
@@ -1416,8 +1472,10 @@ public class NotificationStackScrollLayout extends ViewGroup
*/
public void setActivatedChild(View activatedChild) {
mAmbientState.setActivatedChild(activatedChild);
- mActivateNeedsAnimation = true;
- mNeedsAnimation = true;
+ if (mAnimationsEnabled) {
+ mActivateNeedsAnimation = true;
+ mNeedsAnimation = true;
+ }
requestChildrenUpdate();
}
@@ -1432,6 +1490,34 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ public void setSpeedBumpView(SpeedBumpView speedBumpView) {
+ mSpeedBumpView = speedBumpView;
+ addView(speedBumpView);
+ }
+
+ private void updateSpeedBump(boolean visible) {
+ int newVisibility = visible ? VISIBLE : GONE;
+ int oldVisibility = mSpeedBumpView.getVisibility();
+ if (newVisibility != oldVisibility) {
+ mSpeedBumpView.setVisibility(newVisibility);
+ if (visible) {
+ mSpeedBumpView.collapse();
+ // Make invisible to ensure that the appear animation is played.
+ mSpeedBumpView.setInvisible();
+ if (!mIsExpansionChanging) {
+ generateAddAnimation(mSpeedBumpView);
+ }
+ } else {
+ mSpeedBumpView.performVisibilityAnimation(false);
+ generateRemoveAnimation(mSpeedBumpView);
+ }
+ }
+ }
+
+ public void goToFullShade() {
+ updateSpeedBump(true);
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 8fc26d8..011411c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -23,6 +23,7 @@ import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.SpeedBumpView;
import java.util.HashMap;
import java.util.Map;
@@ -167,11 +168,48 @@ public class StackScrollState {
clipHeight,
(int) (newHeight - (previousNotificationStart - newYTranslation)));
- previousNotificationStart = newYTranslation + child.getClipTopAmount();
- previousNotificationEnd = newNotificationEnd;
- previousNotificationIsSwiped = child.getTranslationX() != 0;
+ if (!child.isTransparent()) {
+ // Only update the previous values if we are not transparent,
+ // otherwise we would clip to a transparent view.
+ previousNotificationStart = newYTranslation + child.getClipTopAmount();
+ previousNotificationEnd = newNotificationEnd;
+ previousNotificationIsSwiped = child.getTranslationX() != 0;
+ }
+
+ if(child instanceof SpeedBumpView) {
+ performSpeedBumpAnimation(i, (SpeedBumpView) child, newNotificationEnd,
+ newYTranslation);
+ }
+ }
+ }
+ }
+
+ private void performSpeedBumpAnimation(int i, SpeedBumpView speedBump, float speedBumpEnd,
+ float speedBumpStart) {
+ View nextChild = getNextChildNotGone(i);
+ if (nextChild != null) {
+ ViewState nextState = getViewStateForView(nextChild);
+ boolean startIsAboveNext = nextState.yTranslation > speedBumpStart;
+ speedBump.animateDivider(startIsAboveNext);
+
+ // handle expanded case
+ if (speedBump.isExpanded()) {
+ boolean endIsAboveNext = nextState.yTranslation > speedBumpEnd;
+ speedBump.animateExplanationText(endIsAboveNext);
+ }
+
+ }
+ }
+
+ private View getNextChildNotGone(int childIndex) {
+ int childCount = mHostView.getChildCount();
+ for (int i = childIndex + 1; i < childCount; i++) {
+ View child = mHostView.getChildAt(i);
+ if (child.getVisibility() != View.GONE) {
+ return child;
}
}
+ return null;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 5ac51f8..a9dcdd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -434,7 +434,7 @@ public class StackStateAnimator {
/**
* Start an animator instantly instead of waiting on the next synchronization frame
*/
- private void startInstantly(ValueAnimator animator) {
+ public static void startInstantly(ValueAnimator animator) {
animator.start();
animator.setCurrentPlayTime(0);
}