diff options
author | Jorim Jaggi <jjaggi@google.com> | 2015-07-14 18:08:43 -0700 |
---|---|---|
committer | Jorim Jaggi <jjaggi@google.com> | 2015-07-20 21:50:33 +0000 |
commit | 86b273f1cc59185a14d5bab8a3f4db30c1a4c8a9 (patch) | |
tree | f3cf08a23ec6c05f2dfb42b3f766e7094e871f2d | |
parent | f87635813cabbf4f7dc0236fffc6b07a2715aff3 (diff) | |
download | frameworks_base-86b273f1cc59185a14d5bab8a3f4db30c1a4c8a9.zip frameworks_base-86b273f1cc59185a14d5bab8a3f4db30c1a4c8a9.tar.gz frameworks_base-86b273f1cc59185a14d5bab8a3f4db30c1a4c8a9.tar.bz2 |
Fix jank in swipe-up to unlock
Some stuff is slow in the swipe-up to unlock transition. Introduce
DejankUtils to execute it when RenderThread is doing its work.
Bug: 22205322
Change-Id: I7089f0a1bdca13ad13a1e305a7bff32276a3cd53
3 files changed, 87 insertions, 8 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/DejankUtils.java b/packages/SystemUI/src/com/android/systemui/DejankUtils.java new file mode 100644 index 0000000..fc98ec4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/DejankUtils.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui; + +import android.os.Handler; +import android.os.Looper; +import android.os.StrictMode; +import android.view.Choreographer; + +import java.util.ArrayList; + +/** + * Utility class for methods used to dejank the UI. + */ +public class DejankUtils { + + private static final Choreographer sChoreographer = Choreographer.getInstance(); + private static final Handler sHandler = new Handler(); + + private static final ArrayList<Runnable> sPendingRunnables = new ArrayList<>(); + + private static final Runnable sAnimationCallbackRunnable = new Runnable() { + @Override + public void run() { + for (int i = 0; i < sPendingRunnables.size(); i++) { + sHandler.post(sPendingRunnables.get(i)); + } + sPendingRunnables.clear(); + } + }; + + /** + * Executes {@code r} after performTraversals. Use this do to CPU heavy work for which the + * timing is not critical for animation. The work is then scheduled at the same time + * RenderThread is doing its thing, leading to better parallelization. + * + * <p>Needs to be called from the main thread. + */ + public static void postAfterTraversal(Runnable r) { + throwIfNotCalledOnMainThread(); + sPendingRunnables.add(r); + postAnimationCallback(); + } + + /** + * Removes a previously scheduled runnable. + * + * <p>Needs to be called from the main thread. + */ + public static void removeCallbacks(Runnable r) { + throwIfNotCalledOnMainThread(); + sPendingRunnables.remove(r); + sHandler.removeCallbacks(r); + } + + private static void postAnimationCallback() { + sChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, sAnimationCallbackRunnable, + null); + } + + private static void throwIfNotCalledOnMainThread() { + if (!Looper.getMainLooper().isCurrentThread()) { + throw new IllegalStateException("should be called from the main thread."); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index a7afec4..e9b2c61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -29,6 +29,7 @@ import com.android.keyguard.KeyguardHostView; import com.android.keyguard.KeyguardSecurityView; import com.android.keyguard.R; import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.DejankUtils; import static com.android.keyguard.KeyguardHostView.OnDismissAction; import static com.android.keyguard.KeyguardSecurityModel.SecurityMode; @@ -46,7 +47,6 @@ public class KeyguardBouncer { private KeyguardHostView mKeyguardView; private ViewGroup mRoot; private boolean mShowingSoon; - private Choreographer mChoreographer = Choreographer.getInstance(); private int mBouncerPromptReason; public KeyguardBouncer(Context context, ViewMediatorCallback callback, @@ -70,16 +70,13 @@ public class KeyguardBouncer { return; } - mBouncerPromptReason = mCallback.getBouncerPromptReason(); - // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole // Keyguard. If we need to authenticate, show the bouncer. if (!mKeyguardView.dismiss()) { mShowingSoon = true; // Split up the work over multiple frames. - mChoreographer.postCallbackDelayed(Choreographer.CALLBACK_ANIMATION, mShowRunnable, - null, 16); + DejankUtils.postAfterTraversal(mShowRunnable); } } @@ -107,7 +104,7 @@ public class KeyguardBouncer { } private void cancelShowRunnable() { - mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null); + DejankUtils.removeCallbacks(mShowRunnable); mShowingSoon = false; } @@ -165,6 +162,7 @@ public class KeyguardBouncer { if (wasInitialized) { mKeyguardView.showPrimarySecurityScreen(); } + mBouncerPromptReason = mCallback.getBouncerPromptReason(); } private void ensureView() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 6d04b28..c0887ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -24,6 +24,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; +import com.android.systemui.DejankUtils; import com.android.systemui.EventLogTags; import com.android.systemui.R; @@ -117,12 +118,12 @@ public class PhoneStatusBarView extends PanelBar { public void onAllPanelsCollapsed() { super.onAllPanelsCollapsed(); // Close the status bar in the next frame so we can show the end of the animation. - postOnAnimation(mHideExpandedRunnable); + DejankUtils.postAfterTraversal(mHideExpandedRunnable); mLastFullyOpenedPanel = null; } public void removePendingHideExpandedRunnables() { - removeCallbacks(mHideExpandedRunnable); + DejankUtils.removeCallbacks(mHideExpandedRunnable); } @Override |