Loading core/java/android/os/Looper.java +1 −1 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ public final class Looper { } final long traceTag = me.mTraceTag; if (traceTag != 0) { if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { Loading packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +71 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.graphics.Region.Op; import android.hardware.display.DisplayManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.Display; import android.view.DisplayInfo; Loading Loading @@ -106,6 +107,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, private static final Interpolator IME_ADJUST_INTERPOLATOR = new PathInterpolator(0.2f, 0f, 0.1f, 1f); private static final long ONE_MS_IN_NS = 1000000; private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000; private static final int MSG_RESIZE_STACK = 0; private DividerHandleView mHandle; private View mBackground; private MinimizedDockShadow mMinimizedShadow; Loading Loading @@ -150,7 +156,25 @@ public class DividerView extends FrameLayout implements OnTouchListener, private boolean mDockedStackMinimized; private boolean mAdjustedForIme; private DividerState mState; private final Handler mHandler = new Handler(); /** * The offset between vsync-app and vsync-surfaceflinger. See * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary. */ private long mSurfaceFlingerOffsetMs; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_RESIZE_STACK: resizeStack(msg.arg1, msg.arg2, (SnapTarget) msg.obj); break; default: super.handleMessage(msg); } } }; private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() { @Override Loading Loading @@ -290,6 +314,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, protected void onAttachedToWindow() { super.onAttachedToWindow(); EventBus.getDefault().register(this); mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs(); } @Override Loading @@ -298,6 +323,25 @@ public class DividerView extends FrameLayout implements OnTouchListener, EventBus.getDefault().unregister(this); } /** * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app * is a couple of milliseconds before vsync-sf, a touch or animation event that causes the * stacks to be resized are sometimes processed before the vsync-sf tick, and sometimes after, * which leads to jank. Figure out this difference here and then post all the touch/animation * events to start being processed at vsync-sf. * * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf. */ private long calculateAppSurfaceFlingerVsyncOffsetMs() { Display display = getDisplay(); // Calculate vsync offset from SurfaceFlinger. // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate()); long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS); return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS); } @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { if (mStableInsets.left != insets.getStableInsetLeft() Loading Loading @@ -453,7 +497,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) { SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget( mStartPosition, 0 /* velocity */, false /* hardDismiss */); resizeStack(calculatePosition(x, y), mStartPosition, snapTarget); resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget); } break; case MotionEvent.ACTION_UP: Loading Loading @@ -532,10 +576,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, final long endDelay) { final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE; ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position); anim.addUpdateListener(animation -> resizeStack((Integer) animation.getAnimatedValue(), anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(), taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f ? TASK_POSITION_SAME : snapTarget.taskPosition, snapTarget)); : snapTarget.taskPosition, snapTarget)); Runnable endAction = () -> { commitSnapFlags(snapTarget); mWindowManagerProxy.setResizing(false); Loading @@ -551,15 +596,24 @@ public class DividerView extends FrameLayout implements OnTouchListener, @Override public void onAnimationCancel(Animator animation) { mHandler.removeMessages(MSG_RESIZE_STACK); mCancelled = true; } @Override public void onAnimationEnd(Animator animation) { if (endDelay == 0 || mCancelled) { long delay = 0; if (endDelay != 0) { delay = endDelay; } else if (mCancelled) { delay = 0; } else if (mSurfaceFlingerOffsetMs != 0) { delay = mSurfaceFlingerOffsetMs; } if (delay == 0) { endAction.run(); } else { mHandler.postDelayed(endAction, endDelay); mHandler.postDelayed(endAction, delay); } } }); Loading Loading @@ -793,6 +847,17 @@ public class DividerView extends FrameLayout implements OnTouchListener, mDisplayHeight, mDividerSize); } public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) { if (mSurfaceFlingerOffsetMs != 0) { Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition, taskSnapTarget); message.setAsynchronous(true); mHandler.sendMessageDelayed(message, mSurfaceFlingerOffsetMs); } else { resizeStack(position, taskPosition, taskSnapTarget); } } public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) { calculateBoundsForPosition(position, mDockSide, mDockedRect); Loading services/core/java/com/android/server/am/UserController.java +28 −13 Original line number Diff line number Diff line Loading @@ -292,6 +292,7 @@ final class UserController { */ private void finishUserUnlocking(final UserState uss) { final int userId = uss.mHandle.getIdentifier(); boolean proceedWithUnlock = false; synchronized (mLock) { // Bail if we ended up with a stale user if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return; Loading @@ -301,6 +302,11 @@ final class UserController { if (uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) { mInjector.getUserManagerInternal().setUserState(userId, uss.state); proceedWithUnlock = true; } } if (proceedWithUnlock) { uss.mUnlockProgress.start(); // Prepare app storage before we go any further Loading @@ -315,7 +321,6 @@ final class UserController { .sendToTarget(); } } } /** * Step from {@link UserState#STATE_RUNNING_UNLOCKING} to Loading Loading @@ -961,6 +966,7 @@ final class UserController { boolean unlockUserCleared(final int userId, byte[] token, byte[] secret, IProgressListener listener) { UserState uss; synchronized (mLock) { // TODO Move this block outside of synchronized if it causes lock contention if (!StorageManager.isUserKeyUnlocked(userId)) { Loading @@ -975,7 +981,7 @@ final class UserController { } // Bail if user isn't actually running, otherwise register the given // listener to watch for unlock progress final UserState uss = mStartedUsers.get(userId); uss = mStartedUsers.get(userId); if (uss == null) { notifyFinished(userId, listener); return false; Loading @@ -983,9 +989,13 @@ final class UserController { uss.mUnlockProgress.addListener(listener); uss.tokenProvided = (token != null); } } finishUserUnlocking(uss); final ArraySet<Integer> childProfilesToUnlock = new ArraySet<>(); synchronized (mLock) { // We just unlocked a user, so let's now attempt to unlock any // managed profiles under that user. for (int i = 0; i < mStartedUsers.size(); i++) { Loading @@ -994,11 +1004,16 @@ final class UserController { if (parent != null && parent.id == userId && testUserId != userId) { Slog.d(TAG, "User " + testUserId + " (parent " + parent.id + "): attempting unlock because parent was just unlocked"); maybeUnlockUser(testUserId); childProfilesToUnlock.add(testUserId); } } } final int size = childProfilesToUnlock.size(); for (int i = 0; i < size; i++) { maybeUnlockUser(childProfilesToUnlock.valueAt(i)); } return true; } Loading Loading
core/java/android/os/Looper.java +1 −1 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ public final class Looper { } final long traceTag = me.mTraceTag; if (traceTag != 0) { if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { Loading
packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +71 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.graphics.Region.Op; import android.hardware.display.DisplayManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.Display; import android.view.DisplayInfo; Loading Loading @@ -106,6 +107,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, private static final Interpolator IME_ADJUST_INTERPOLATOR = new PathInterpolator(0.2f, 0f, 0.1f, 1f); private static final long ONE_MS_IN_NS = 1000000; private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000; private static final int MSG_RESIZE_STACK = 0; private DividerHandleView mHandle; private View mBackground; private MinimizedDockShadow mMinimizedShadow; Loading Loading @@ -150,7 +156,25 @@ public class DividerView extends FrameLayout implements OnTouchListener, private boolean mDockedStackMinimized; private boolean mAdjustedForIme; private DividerState mState; private final Handler mHandler = new Handler(); /** * The offset between vsync-app and vsync-surfaceflinger. See * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary. */ private long mSurfaceFlingerOffsetMs; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_RESIZE_STACK: resizeStack(msg.arg1, msg.arg2, (SnapTarget) msg.obj); break; default: super.handleMessage(msg); } } }; private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() { @Override Loading Loading @@ -290,6 +314,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, protected void onAttachedToWindow() { super.onAttachedToWindow(); EventBus.getDefault().register(this); mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs(); } @Override Loading @@ -298,6 +323,25 @@ public class DividerView extends FrameLayout implements OnTouchListener, EventBus.getDefault().unregister(this); } /** * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app * is a couple of milliseconds before vsync-sf, a touch or animation event that causes the * stacks to be resized are sometimes processed before the vsync-sf tick, and sometimes after, * which leads to jank. Figure out this difference here and then post all the touch/animation * events to start being processed at vsync-sf. * * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf. */ private long calculateAppSurfaceFlingerVsyncOffsetMs() { Display display = getDisplay(); // Calculate vsync offset from SurfaceFlinger. // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate()); long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS); return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS); } @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { if (mStableInsets.left != insets.getStableInsetLeft() Loading Loading @@ -453,7 +497,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) { SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget( mStartPosition, 0 /* velocity */, false /* hardDismiss */); resizeStack(calculatePosition(x, y), mStartPosition, snapTarget); resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget); } break; case MotionEvent.ACTION_UP: Loading Loading @@ -532,10 +576,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, final long endDelay) { final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE; ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position); anim.addUpdateListener(animation -> resizeStack((Integer) animation.getAnimatedValue(), anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(), taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f ? TASK_POSITION_SAME : snapTarget.taskPosition, snapTarget)); : snapTarget.taskPosition, snapTarget)); Runnable endAction = () -> { commitSnapFlags(snapTarget); mWindowManagerProxy.setResizing(false); Loading @@ -551,15 +596,24 @@ public class DividerView extends FrameLayout implements OnTouchListener, @Override public void onAnimationCancel(Animator animation) { mHandler.removeMessages(MSG_RESIZE_STACK); mCancelled = true; } @Override public void onAnimationEnd(Animator animation) { if (endDelay == 0 || mCancelled) { long delay = 0; if (endDelay != 0) { delay = endDelay; } else if (mCancelled) { delay = 0; } else if (mSurfaceFlingerOffsetMs != 0) { delay = mSurfaceFlingerOffsetMs; } if (delay == 0) { endAction.run(); } else { mHandler.postDelayed(endAction, endDelay); mHandler.postDelayed(endAction, delay); } } }); Loading Loading @@ -793,6 +847,17 @@ public class DividerView extends FrameLayout implements OnTouchListener, mDisplayHeight, mDividerSize); } public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) { if (mSurfaceFlingerOffsetMs != 0) { Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition, taskSnapTarget); message.setAsynchronous(true); mHandler.sendMessageDelayed(message, mSurfaceFlingerOffsetMs); } else { resizeStack(position, taskPosition, taskSnapTarget); } } public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) { calculateBoundsForPosition(position, mDockSide, mDockedRect); Loading
services/core/java/com/android/server/am/UserController.java +28 −13 Original line number Diff line number Diff line Loading @@ -292,6 +292,7 @@ final class UserController { */ private void finishUserUnlocking(final UserState uss) { final int userId = uss.mHandle.getIdentifier(); boolean proceedWithUnlock = false; synchronized (mLock) { // Bail if we ended up with a stale user if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return; Loading @@ -301,6 +302,11 @@ final class UserController { if (uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) { mInjector.getUserManagerInternal().setUserState(userId, uss.state); proceedWithUnlock = true; } } if (proceedWithUnlock) { uss.mUnlockProgress.start(); // Prepare app storage before we go any further Loading @@ -315,7 +321,6 @@ final class UserController { .sendToTarget(); } } } /** * Step from {@link UserState#STATE_RUNNING_UNLOCKING} to Loading Loading @@ -961,6 +966,7 @@ final class UserController { boolean unlockUserCleared(final int userId, byte[] token, byte[] secret, IProgressListener listener) { UserState uss; synchronized (mLock) { // TODO Move this block outside of synchronized if it causes lock contention if (!StorageManager.isUserKeyUnlocked(userId)) { Loading @@ -975,7 +981,7 @@ final class UserController { } // Bail if user isn't actually running, otherwise register the given // listener to watch for unlock progress final UserState uss = mStartedUsers.get(userId); uss = mStartedUsers.get(userId); if (uss == null) { notifyFinished(userId, listener); return false; Loading @@ -983,9 +989,13 @@ final class UserController { uss.mUnlockProgress.addListener(listener); uss.tokenProvided = (token != null); } } finishUserUnlocking(uss); final ArraySet<Integer> childProfilesToUnlock = new ArraySet<>(); synchronized (mLock) { // We just unlocked a user, so let's now attempt to unlock any // managed profiles under that user. for (int i = 0; i < mStartedUsers.size(); i++) { Loading @@ -994,11 +1004,16 @@ final class UserController { if (parent != null && parent.id == userId && testUserId != userId) { Slog.d(TAG, "User " + testUserId + " (parent " + parent.id + "): attempting unlock because parent was just unlocked"); maybeUnlockUser(testUserId); childProfilesToUnlock.add(testUserId); } } } final int size = childProfilesToUnlock.size(); for (int i = 0; i < size; i++) { maybeUnlockUser(childProfilesToUnlock.valueAt(i)); } return true; } Loading