From d2fb185677dda6d0701f3d894e432c642c4d5b1f Mon Sep 17 00:00:00 2001 From: Alejandro Nijamkin Date: Fri, 24 Mar 2023 15:38:30 -0700 Subject: [PATCH] Moves lock screen shortcuts summary loading to the background. To load the summary for the Settings > Display > Lock screen > Shortcuts, we need to issue a binder/IPC call to query the content provider that resides in the System UI process. Previously, this was being done on the main thread. The thinking was that it's critical to load this as soon as the Settings page is shown. This results in ANRs, as per the attached bug. The fix is to move the loading off the main thread and onto a background thread. Fix: 274788437 Test: unit tests updated Test: manually verified that the summary is correct and that it updates correctly after clicking on it, changing the lock screen shortcuts, and going back Change-Id: I41a5e883236de4f16c105f3930b8849538807f00 --- ...nQuickAffordancesPreferenceController.java | 9 +++++-- ...ckAffordancesPreferenceControllerTest.java | 26 ++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceController.java b/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceController.java index 96ca4e580b1..27e2a139d42 100644 --- a/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceController.java +++ b/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceController.java @@ -26,6 +26,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.utils.ThreadUtils; /** * Preference for accessing an experience to customize lock screen quick affordances. @@ -65,7 +66,11 @@ public class CustomizableLockScreenQuickAffordancesPreferenceController extends } @Override - public CharSequence getSummary() { - return CustomizableLockScreenUtils.getQuickAffordanceSummary(mContext); + protected void refreshSummary(Preference preference) { + ThreadUtils.postOnBackgroundThread(() -> { + final CharSequence summary = + CustomizableLockScreenUtils.getQuickAffordanceSummary(mContext); + ThreadUtils.postOnMainThread(() -> preference.setSummary(summary)); + }); } } diff --git a/tests/robotests/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceControllerTest.java index 78a9e998422..e92dbe6cb5e 100644 --- a/tests/robotests/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceControllerTest.java @@ -35,7 +35,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.MatrixCursor; -import android.text.TextUtils; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; @@ -43,6 +42,7 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; import com.android.settings.R; +import com.android.settings.testutils.shadow.ShadowThreadUtils; import org.junit.Before; import org.junit.Test; @@ -71,6 +71,7 @@ public class CustomizableLockScreenQuickAffordancesPreferenceControllerTest { when(mContext.getResources()) .thenReturn(ApplicationProvider.getApplicationContext().getResources()); when(mContext.getPackageManager()).thenReturn(mPackageManager); + ShadowThreadUtils.setIsMainThread(true); mUnderTest = new CustomizableLockScreenQuickAffordancesPreferenceController(mContext, KEY); } @@ -99,11 +100,7 @@ public class CustomizableLockScreenQuickAffordancesPreferenceControllerTest { @Test public void displayPreference_click() { setSelectedAffordanceNames("one", "two"); - final PreferenceScreen screen = mock(PreferenceScreen.class); - final Preference preference = mock(Preference.class); - when(screen.findPreference(KEY)).thenReturn(preference); - - mUnderTest.displayPreference(screen); + final Preference preference = invokeDisplayPreference(); final ArgumentCaptor clickCaptor = ArgumentCaptor.forClass(Preference.OnPreferenceClickListener.class); @@ -124,22 +121,25 @@ public class CustomizableLockScreenQuickAffordancesPreferenceControllerTest { @Test public void getSummary_whenNoneAreSelected() { setSelectedAffordanceNames(); + final Preference preference = invokeDisplayPreference(); - assertThat(mUnderTest.getSummary()).isNull(); + verify(preference).setSummary(null); } @Test public void getSummary_whenOneIsSelected() { setSelectedAffordanceNames("one"); + final Preference preference = invokeDisplayPreference(); - assertThat(TextUtils.equals(mUnderTest.getSummary(), "one")).isTrue(); + verify(preference).setSummary("one"); } @Test public void getSummary_whenTwoAreSelected() { setSelectedAffordanceNames("one", "two"); + final Preference preference = invokeDisplayPreference(); - assertThat(TextUtils.equals(mUnderTest.getSummary(), "one, two")).isTrue(); + verify(preference).setSummary("one, two"); } private void setEnabled(boolean isWallpaperPickerInstalled, boolean isFeatureEnabled) { @@ -183,4 +183,12 @@ public class CustomizableLockScreenQuickAffordancesPreferenceControllerTest { CustomizableLockScreenUtils.SELECTIONS_URI, null, null, null)) .thenReturn(cursor); } + + private Preference invokeDisplayPreference() { + final PreferenceScreen screen = mock(PreferenceScreen.class); + final Preference preference = mock(Preference.class); + when(screen.findPreference(KEY)).thenReturn(preference); + mUnderTest.displayPreference(screen); + return preference; + } }