From f9ff6344e4b469f6ab2b6b92c969f50e0526fb86 Mon Sep 17 00:00:00 2001 From: Tsung-Mao Fang Date: Thu, 8 Jul 2021 17:58:50 +0800 Subject: [PATCH] Fix the flickering on display/font size page In framework design, framework needs to have a snapshot when there's a config change event since redrawing window takes some time. Flickering problem is caused by the timing issue between the snapshot mechinsm and local preview update. User can observe the flickering problem if config commit()-> snapshot in framework(old screenshot) -> app update the preview -> snapshot(old screen) fade out. To prevent this problem, we make sure that we update the local preview first and then we do the commit later. In this proposal, snapshot action is able to get the new snaptshot for the new preview. So, the core workaround is commitOnNextFrame, we ask a delay before we submit the commit(). Note: It doesn't matter that we use Choreographer or main thread handler since the delay time is longer than 1 frame. Use Choreographer to let developer understand it's a window update. Fix: 148192402 Test: manual test Change-Id: I9bfc5eb39e7a9ebce2fe1414d6f0a9dd470708e8 --- .../PreviewSeekBarPreferenceFragment.java | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/display/PreviewSeekBarPreferenceFragment.java b/src/com/android/settings/display/PreviewSeekBarPreferenceFragment.java index bb9e3d71024..abd14d25d9e 100644 --- a/src/com/android/settings/display/PreviewSeekBarPreferenceFragment.java +++ b/src/com/android/settings/display/PreviewSeekBarPreferenceFragment.java @@ -19,6 +19,8 @@ package com.android.settings.display; import android.content.Context; import android.content.res.Configuration; import android.os.Bundle; +import android.os.SystemClock; +import android.view.Choreographer; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -58,14 +60,35 @@ public abstract class PreviewSeekBarPreferenceFragment extends SettingsPreferenc private View mLarger; private View mSmaller; + private static final long MIN_COMMIT_INTERVAL_MS = 800; + private long mLastCommitTime; + private class onPreviewSeekBarChangeListener implements OnSeekBarChangeListener { + private static final long CHANGE_BY_SEEKBAR_DELAY_MS = 100; + private static final long CHANGE_BY_BUTTON_DELAY_MS = 300; + private boolean mSeekByTouch; + private boolean mIsChanged; + private long mCommitDelayMs; + + private final Choreographer.FrameCallback mCommit = f -> { + commit(); + mLastCommitTime = SystemClock.elapsedRealtime(); + }; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (mCurrentIndex == progress) { + mIsChanged = false; + return; + } + mIsChanged = true; setPreviewLayer(progress, false); - if (!mSeekByTouch) { - commit(); + if (mSeekByTouch) { + mCommitDelayMs = CHANGE_BY_SEEKBAR_DELAY_MS; + } else { + mCommitDelayMs = CHANGE_BY_BUTTON_DELAY_MS; + commitOnNextFrame(); } } @@ -76,18 +99,39 @@ public abstract class PreviewSeekBarPreferenceFragment extends SettingsPreferenc @Override public void onStopTrackingTouch(SeekBar seekBar) { - if (mPreviewPagerAdapter.isAnimating()) { - mPreviewPagerAdapter.setAnimationEndAction(() -> commit()); - } else { - commit(); - } mSeekByTouch = false; + if (!mIsChanged) { + return; + } + if (mPreviewPagerAdapter.isAnimating()) { + mPreviewPagerAdapter.setAnimationEndAction(this::commitOnNextFrame); + } else { + commitOnNextFrame(); + } } + + private void commitOnNextFrame() { + if (SystemClock.elapsedRealtime() - mLastCommitTime < MIN_COMMIT_INTERVAL_MS) { + mCommitDelayMs += MIN_COMMIT_INTERVAL_MS; + } + final Choreographer choreographer = Choreographer.getInstance(); + choreographer.removeFrameCallback(mCommit); + choreographer.postFrameCallbackDelayed(mCommit, mCommitDelayMs); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putLong("mLastCommitTime", mLastCommitTime); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (savedInstanceState != null) { + mLastCommitTime = savedInstanceState.getLong("mLastCommitTime"); + } final View root = super.onCreateView(inflater, container, savedInstanceState); final ViewGroup listContainer = root.findViewById(android.R.id.list_container); listContainer.removeAllViews(); @@ -240,4 +284,4 @@ public abstract class PreviewSeekBarPreferenceFragment extends SettingsPreferenc setPagerIndicatorContentDescription(position); } }; -} +} \ No newline at end of file