am 0ad0f097: Optimized and improved the status bar performance a lot

* commit '0ad0f0975a607f84a16ba18553fda7982bd95e3e':
  Optimized and improved the status bar performance a lot
This commit is contained in:
Selim Cinek
2014-09-19 19:05:36 +00:00
committed by Android Git Automerger
7 changed files with 279 additions and 36 deletions

View File

@@ -26,7 +26,7 @@
android:fitsSystemWindows="true"
android:descendantFocusability="afterDescendants">
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
<com.android.systemui.statusbar.BackDropView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -41,9 +41,9 @@
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:visibility="invisible" />
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
</com.android.systemui.statusbar.BackDropView>
<View android:id="@+id/scrim_behind"
<com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_behind"
android:layout_width="match_parent"
android:layout_height="match_parent" />
@@ -80,7 +80,7 @@
android:visibility="gone" />
</com.android.systemui.statusbar.phone.PanelHolder>
<View android:id="@+id/scrim_in_front"
<com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_in_front"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -0,0 +1,65 @@
/*
* 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.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
/**
* A view who contains media artwork.
*/
public class BackDropView extends FrameLayout
{
private Runnable mOnVisibilityChangedRunnable;
public BackDropView(Context context) {
super(context);
}
public BackDropView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BackDropView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BackDropView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (changedView == this && mOnVisibilityChangedRunnable != null) {
mOnVisibilityChangedRunnable.run();
}
}
public void setOnVisibilityChangedRunnable(Runnable runnable) {
mOnVisibilityChangedRunnable = runnable;
}
}

View File

@@ -0,0 +1,123 @@
/*
* 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.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;
/**
* A view which can draw a scrim
*/
public class ScrimView extends View
{
private int mScrimColor;
private boolean mIsEmpty;
private boolean mDrawAsSrc;
private float mViewAlpha = 1.0f;
private ValueAnimator mAlphaAnimator;
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mViewAlpha = (float) animation.getAnimatedValue();
invalidate();
}
};
private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mAlphaAnimator = null;
}
};
public ScrimView(Context context) {
this(context, null);
}
public ScrimView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrimView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public ScrimView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onDraw(Canvas canvas) {
if (mDrawAsSrc || !mIsEmpty) {
PorterDuff.Mode mode = mDrawAsSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
int color = mScrimColor;
color = Color.argb((int) (Color.alpha(color) * mViewAlpha), Color.red(color),
Color.green(color), Color.blue(color));
canvas.drawColor(color, mode);
}
}
public void setDrawAsSrc(boolean asSrc) {
mDrawAsSrc = asSrc;
invalidate();
}
public void setScrimColor(int color) {
if (color != mScrimColor) {
mIsEmpty = Color.alpha(color) == 0;
mScrimColor = color;
invalidate();
}
}
public int getScrimColor() {
return mScrimColor;
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
public void setViewAlpha(float alpha) {
if (mAlphaAnimator != null) {
mAlphaAnimator.cancel();
}
mViewAlpha = alpha;
invalidate();
}
public void animateViewAlpha(float alpha, long durationOut, Interpolator interpolator) {
if (mAlphaAnimator != null) {
mAlphaAnimator.cancel();
}
mAlphaAnimator = ValueAnimator.ofFloat(mViewAlpha, alpha);
mAlphaAnimator.addUpdateListener(mAlphaUpdateListener);
mAlphaAnimator.addListener(mClearAnimatorListener);
mAlphaAnimator.setInterpolator(interpolator);
mAlphaAnimator.setDuration(durationOut);
mAlphaAnimator.start();
}
}

View File

@@ -51,7 +51,9 @@ import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Xfermode;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.InputMethodService;
@@ -120,6 +122,7 @@ import com.android.systemui.doze.DozeService;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DismissView;
@@ -131,6 +134,7 @@ import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.NotificationOverflowContainer;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.SpeedBumpView;
import com.android.systemui.statusbar.StatusBarIconView;
@@ -431,8 +435,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
private FrameLayout mBackdrop;
private BackDropView mBackdrop;
private ImageView mBackdropFront, mBackdropBack;
private PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
private PorterDuffXfermode mSrcOverXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
private MediaSessionManager mMediaSessionManager;
private MediaController mMediaController;
@@ -723,8 +729,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStackScroller.setDismissView(mDismissView);
mExpandedContents = mStackScroller;
mScrimController = new ScrimController(mStatusBarWindow.findViewById(R.id.scrim_behind),
mStatusBarWindow.findViewById(R.id.scrim_in_front));
mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop);
mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);
ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
mScrimController = new ScrimController(scrimBehind, scrimInFront);
mScrimController.setBackDropView(mBackdrop);
mStatusBarView.setScrimController(mScrimController);
mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
@@ -863,10 +875,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
});
}
mBackdrop = (FrameLayout) mStatusBarWindow.findViewById(R.id.backdrop);
mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);
// User info. Trigger first load.
mHeader.setUserInfoController(mUserInfoController);
mKeyguardStatusBar.setUserInfoController(mUserInfoController);
@@ -1852,7 +1860,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
if (metaDataChanged) {
if (mBackdropBack.getDrawable() != null) {
mBackdropFront.setImageDrawable(mBackdropBack.getDrawable());
Drawable drawable = mBackdropBack.getDrawable();
mBackdropFront.setImageDrawable(drawable);
mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode);
mBackdropFront.setAlpha(1f);
mBackdropFront.setVisibility(View.VISIBLE);
} else {
@@ -1867,6 +1877,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
} else {
mBackdropBack.setImageBitmap(artworkBitmap);
}
mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode);
if (mBackdropFront.getVisibility() == View.VISIBLE) {
if (DEBUG_MEDIA) {

View File

@@ -21,7 +21,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
@@ -31,6 +30,8 @@ import android.view.animation.Interpolator;
import com.android.systemui.R;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.ScrimView;
/**
* Controls both the scrim behind the notifications and in front of the notifications (when a
@@ -48,8 +49,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
private static final int TAG_KEY_ANIM = R.id.scrim;
private final View mScrimBehind;
private final View mScrimInFront;
private final ScrimView mScrimBehind;
private final ScrimView mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
private final DozeParameters mDozeParameters;
@@ -70,8 +71,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
private long mPulseEndTime;
private final Interpolator mInterpolator = new DecelerateInterpolator();
private final Interpolator mLinearOutSlowInInterpolator;
private BackDropView mBackDropView;
public ScrimController(View scrimBehind, View scrimInFront) {
public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront) {
mScrimBehind = scrimBehind;
mScrimInFront = scrimInFront;
final Context context = scrimBehind.getContext();
@@ -230,17 +232,17 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
}
}
private void setScrimColor(View scrim, float alpha) {
private void setScrimColor(ScrimView scrim, float alpha) {
int color = Color.argb((int) (alpha * 255), 0, 0, 0);
if (mAnimateChange) {
startScrimAnimation(scrim, color);
} else {
scrim.setBackgroundColor(color);
scrim.setScrimColor(color);
}
}
private void startScrimAnimation(final View scrim, int targetColor) {
int current = getBackgroundAlpha(scrim);
private void startScrimAnimation(final ScrimView scrim, int targetColor) {
int current = Color.alpha(scrim.getScrimColor());
int target = Color.alpha(targetColor);
if (current == targetColor) {
return;
@@ -254,7 +256,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
scrim.setBackgroundColor(Color.argb(value, 0, 0, 0));
scrim.setScrimColor(Color.argb(value, 0, 0, 0));
}
});
anim.setInterpolator(mAnimateKeyguardFadingOut
@@ -278,15 +280,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
mAnimationStarted = true;
}
private int getBackgroundAlpha(View scrim) {
if (scrim.getBackground() instanceof ColorDrawable) {
ColorDrawable drawable = (ColorDrawable) scrim.getBackground();
return Color.alpha(drawable.getColor());
} else {
return 0;
}
}
@Override
public boolean onPreDraw() {
mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
@@ -349,4 +342,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
mPulseEndTime = 0;
}
};
public void setBackDropView(BackDropView backDropView) {
mBackDropView = backDropView;
mBackDropView.setOnVisibilityChangedRunnable(new Runnable() {
@Override
public void run() {
updateScrimBehindDrawingMode();
}
});
updateScrimBehindDrawingMode();
}
private void updateScrimBehindDrawingMode() {
boolean asSrc = mBackDropView.getVisibility() != View.VISIBLE;
mScrimBehind.setDrawAsSrc(asSrc);
}
}

View File

@@ -20,12 +20,17 @@ import android.app.StatusBarManager;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
import com.android.systemui.R;
@@ -45,11 +50,14 @@ public class StatusBarWindowView extends FrameLayout {
private View mBrightnessMirror;
PhoneStatusBar mService;
private final Paint mTransparentSrcPaint = new Paint();
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
setMotionEventSplittingEnabled(false);
setWillNotDraw(!DEBUG);
setWillNotDraw(false);
mTransparentSrcPaint.setColor(0);
mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
}
@Override
@@ -93,6 +101,15 @@ public class StatusBarWindowView extends FrameLayout {
if (root != null) {
root.setDrawDuringWindowsAnimating(true);
}
// We need to ensure that our window doesn't suffer from overdraw which would normally
// occur if our window is translucent. Since we are drawing the whole window anyway with
// the scrim, we don't need the window to be cleared in the beginning.
IBinder windowToken = getWindowToken();
WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
lp.token = windowToken;
setLayoutParams(lp);
WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
}
@Override
@@ -182,6 +199,24 @@ public class StatusBarWindowView extends FrameLayout {
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// We need to ensure that our window is always drawn fully even when we have paddings,
// since we simulate it to be opaque.
int paddedBottom = getHeight() - getPaddingBottom();
int paddedRight = getWidth() - getPaddingRight();
if (getPaddingTop() != 0) {
canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
}
if (getPaddingBottom() != 0) {
canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
}
if (getPaddingLeft() != 0) {
canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
mTransparentSrcPaint);
}
if (getPaddingRight() != 0) {
canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
mTransparentSrcPaint);
}
if (DEBUG) {
Paint pt = new Paint();
pt.setColor(0x80FFFF00);

View File

@@ -17,11 +17,11 @@
package com.android.systemui.statusbar.policy;
import com.android.systemui.R;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;
@@ -33,26 +33,26 @@ public class BrightnessMirrorController {
public long TRANSITION_DURATION_OUT = 150;
public long TRANSITION_DURATION_IN = 200;
private final View mScrimBehind;
private final ScrimView mScrimBehind;
private final View mBrightnessMirror;
private final View mPanelHolder;
private final int[] mInt2Cache = new int[2];
public BrightnessMirrorController(StatusBarWindowView statusBarWindow) {
mScrimBehind = statusBarWindow.findViewById(R.id.scrim_behind);
mScrimBehind = (ScrimView) statusBarWindow.findViewById(R.id.scrim_behind);
mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror);
mPanelHolder = statusBarWindow.findViewById(R.id.panel_holder);
}
public void showMirror() {
mBrightnessMirror.setVisibility(View.VISIBLE);
outAnimation(mScrimBehind.animate());
mScrimBehind.animateViewAlpha(0.0f, TRANSITION_DURATION_OUT, PhoneStatusBar.ALPHA_OUT);
outAnimation(mPanelHolder.animate())
.withLayer();
}
public void hideMirror() {
inAnimation(mScrimBehind.animate());
mScrimBehind.animateViewAlpha(1.0f, TRANSITION_DURATION_IN, PhoneStatusBar.ALPHA_IN);
inAnimation(mPanelHolder.animate())
.withLayer()
.withEndAction(new Runnable() {