Fix settings page flicker in two ways:
1. On create use UiBlocker as recommended by settings team
2. On resume only update the preferences list if the system setting has
   changed.

Bug: 220837804
Test: manual
Change-Id: Ieebd2e7fd74ab05d4fb73aede6868553d7d84af1
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index ab3ed20..ff8b4be 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -20,8 +20,12 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.database.ContentObserver;
 import android.location.SettingInjectorService;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceGroup;
@@ -66,6 +70,7 @@
     private LocationSwitchBarController mSwitchBarController;
     private LocationEnabler mLocationEnabler;
     private RecentLocationAccessPreferenceController mController;
+    private ContentObserver mContentObserver;
 
     @Override
     public int getMetricsCategory() {
@@ -82,6 +87,16 @@
         mSwitchBarController = new LocationSwitchBarController(activity, switchBar,
                 getSettingsLifecycle());
         mLocationEnabler = new LocationEnabler(getContext(), this, getSettingsLifecycle());
+        mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+            @Override
+            public void onChange(boolean selfChange) {
+                mController.updateShowSystem();
+            }
+        };
+        getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(
+                        Settings.Secure.LOCATION_SHOW_SYSTEM_OPS), /* notifyForDescendants= */
+                false, mContentObserver);
     }
 
     @Override
@@ -97,11 +112,9 @@
     }
 
     @Override
-    public void onPause() {
-        super.onPause();
-        if (mController != null) {
-            mController.clearPreferenceList();
-        }
+    public void onDestroy() {
+        super.onDestroy();
+        getContentResolver().unregisterContentObserver(mContentObserver);
     }
 
     @Override
diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
index ea3704c..18221d0 100644
--- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
@@ -28,6 +28,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settingslib.applications.RecentAppOpsAccess;
@@ -40,12 +41,15 @@
 /**
  * Preference controller that handles the display of apps that access locations.
  */
-public class RecentLocationAccessPreferenceController extends LocationBasePreferenceController {
+public class RecentLocationAccessPreferenceController extends LocationBasePreferenceController
+        implements BasePreferenceController.UiBlocker {
     public static final int MAX_APPS = 3;
     @VisibleForTesting
     RecentAppOpsAccess mRecentLocationApps;
     private PreferenceCategory mCategoryRecentLocationRequests;
     private int mType = ProfileSelectFragment.ProfileType.ALL;
+    private boolean mShowSystem = false;
+    private boolean mSystemSettingChanged = false;
 
     private static class PackageEntryClickedListener implements
             Preference.OnPreferenceClickListener {
@@ -80,23 +84,32 @@
             RecentAppOpsAccess recentLocationApps) {
         super(context, key);
         mRecentLocationApps = recentLocationApps;
+        mShowSystem = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1;
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         mCategoryRecentLocationRequests = screen.findPreference(getPreferenceKey());
+        loadRecentAccesses();
     }
 
     @Override
     public void updateState(Preference preference) {
+        // Only reload the recent accesses in updateState if the system setting has changed.
+        if (mSystemSettingChanged) {
+            loadRecentAccesses();
+            mSystemSettingChanged = false;
+        }
+    }
+
+    private void loadRecentAccesses() {
         mCategoryRecentLocationRequests.removeAll();
         final Context prefContext = mCategoryRecentLocationRequests.getContext();
         final List<RecentAppOpsAccess.Access> recentLocationAccesses = new ArrayList<>();
         final UserManager userManager = UserManager.get(mContext);
-        final boolean showSystem = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1;
-        for (RecentAppOpsAccess.Access access : mRecentLocationApps.getAppListSorted(showSystem)) {
+        for (RecentAppOpsAccess.Access access : mRecentLocationApps.getAppListSorted(mShowSystem)) {
             if (isRequestMatchesProfileType(userManager, access, mType)) {
                 recentLocationAccesses.add(access);
                 if (recentLocationAccesses.size() == MAX_APPS) {
@@ -177,4 +190,14 @@
         }
         return false;
     }
+
+    /**
+     * Update the state of the showSystem setting flag and load the new results.
+     */
+    void updateShowSystem() {
+        mSystemSettingChanged = true;
+        mShowSystem = !mShowSystem;
+        clearPreferenceList();
+        loadRecentAccesses();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/location/LocationSettingsTest.java b/tests/robotests/src/com/android/settings/location/LocationSettingsTest.java
index 3d624c0..aae8cec 100644
--- a/tests/robotests/src/com/android/settings/location/LocationSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationSettingsTest.java
@@ -20,6 +20,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Bundle;
 
@@ -41,6 +42,8 @@
     private SettingsActivity mActivity;
     @Mock
     private SettingsMainSwitchBar mSwitchBar;
+    @Mock
+    private ContentResolver mContentResolver;
 
     private Context mContext;
     private LocationSettings mLocationSettings;
@@ -52,6 +55,7 @@
         mLocationSettings = spy(new LocationSettings());
         doReturn(mActivity).when(mLocationSettings).getActivity();
         doReturn(mContext).when(mLocationSettings).getContext();
+        doReturn(mContentResolver).when(mActivity).getContentResolver();
         when(mActivity.getSwitchBar()).thenReturn(mSwitchBar);
     }