Merge changes I03844bce,I8035357c,Ibe7cb6df into nyc-mr1-dev
* changes: Remove lock contention when unlocking users Only get trace name if tracing is enabled Fix multi-window drag jank if vsync-app is before vsync-sf
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -290,6 +314,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
EventBus.getDefault().register(this);
|
||||
mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -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()
|
||||
@@ -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:
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -279,6 +279,7 @@ final class UserController {
|
||||
*/
|
||||
private void finishUserUnlocking(final UserState uss) {
|
||||
final int userId = uss.mHandle.getIdentifier();
|
||||
boolean proceedWithUnlock = false;
|
||||
synchronized (mService) {
|
||||
// Bail if we ended up with a stale user
|
||||
if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
|
||||
@@ -288,20 +289,24 @@ final class UserController {
|
||||
|
||||
if (uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) {
|
||||
getUserManagerInternal().setUserState(userId, uss.state);
|
||||
uss.mUnlockProgress.start();
|
||||
|
||||
// Prepare app storage before we go any further
|
||||
uss.mUnlockProgress.setProgress(5,
|
||||
mService.mContext.getString(R.string.android_start_title));
|
||||
mUserManager.onBeforeUnlockUser(userId);
|
||||
uss.mUnlockProgress.setProgress(20);
|
||||
|
||||
// Dispatch unlocked to system services; when fully dispatched,
|
||||
// that calls through to the next "unlocked" phase
|
||||
mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
|
||||
.sendToTarget();
|
||||
proceedWithUnlock = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (proceedWithUnlock) {
|
||||
uss.mUnlockProgress.start();
|
||||
|
||||
// Prepare app storage before we go any further
|
||||
uss.mUnlockProgress.setProgress(5,
|
||||
mService.mContext.getString(R.string.android_start_title));
|
||||
mUserManager.onBeforeUnlockUser(userId);
|
||||
uss.mUnlockProgress.setProgress(20);
|
||||
|
||||
// Dispatch unlocked to system services; when fully dispatched,
|
||||
// that calls through to the next "unlocked" phase
|
||||
mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
|
||||
.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -962,6 +967,7 @@ final class UserController {
|
||||
|
||||
boolean unlockUserCleared(final int userId, byte[] token, byte[] secret,
|
||||
IProgressListener listener) {
|
||||
UserState uss;
|
||||
synchronized (mService) {
|
||||
// TODO Move this block outside of synchronized if it causes lock contention
|
||||
if (!StorageManager.isUserKeyUnlocked(userId)) {
|
||||
@@ -976,7 +982,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;
|
||||
@@ -984,8 +990,12 @@ final class UserController {
|
||||
uss.mUnlockProgress.addListener(listener);
|
||||
uss.tokenProvided = (token != null);
|
||||
}
|
||||
}
|
||||
|
||||
finishUserUnlocking(uss);
|
||||
finishUserUnlocking(uss);
|
||||
|
||||
final ArraySet<Integer> childProfilesToUnlock = new ArraySet<>();
|
||||
synchronized (mService) {
|
||||
|
||||
// We just unlocked a user, so let's now attempt to unlock any
|
||||
// managed profiles under that user.
|
||||
@@ -995,11 +1005,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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user