Improve the performance of displaying preference.

    - Set a variable to record the status then replace getAvailabilityStatus() with it.

Test: manual test, use command to run MobileNetworkSettings and record it.
Bug: 154061428
Merged-In: Ia13a75a3821bb6c17d0dfeffb5043f47b60adf61
Change-Id: Ia13a75a3821bb6c17d0dfeffb5043f47b60adf61
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index c30a89e..d5e6f5e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -38,6 +38,7 @@
 
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.datausage.BillingCyclePreferenceController;
@@ -52,11 +53,14 @@
 import com.android.settings.widget.PreferenceCategoryController;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -192,16 +196,59 @@
     @Override
     public void onCreate(Bundle icicle) {
         Log.i(LOG_TAG, "onCreate:+");
+
+        final Collection<List<AbstractPreferenceController>> controllerLists =
+                getPreferenceControllers();
+        final Future<Boolean> result = ThreadUtils.postOnBackgroundThread(() ->
+                setupAvailabilityStatus(controllerLists)
+        );
+
         super.onCreate(icicle);
         final Context context = getContext();
-
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mTelephonyManager = context.getSystemService(TelephonyManager.class)
                 .createForSubscriptionId(mSubId);
 
+        // Check the background thread is finished then unset the status of availability.
+        try {
+            result.get();
+        } catch (ExecutionException | InterruptedException exception) {
+            Log.e(LOG_TAG, "onCreate, setup availability status failed!", exception);
+        }
+        unsetAvailabilityStatus(controllerLists);
+
         onRestoreInstance(icicle);
     }
 
+    private Boolean setupAvailabilityStatus(
+            Collection<List<AbstractPreferenceController>> controllerLists) {
+        try {
+            controllerLists.stream().flatMap(Collection::stream)
+                    .filter(controller -> controller instanceof TelephonyAvailabilityHandler)
+                    .map(TelephonyAvailabilityHandler.class::cast)
+                    .forEach(controller -> {
+                        int status = ((BasePreferenceController) controller)
+                                .getAvailabilityStatus();
+                        controller.unsetAvailabilityStatus(true);
+                        controller.setAvailabilityStatus(status);
+                    });
+            return true;
+        } catch (Exception exception) {
+            Log.e(LOG_TAG, "Setup availability status failed!", exception);
+            return false;
+        }
+    }
+
+    private void unsetAvailabilityStatus(
+            Collection<List<AbstractPreferenceController>> controllerLists) {
+        controllerLists.stream().flatMap(Collection::stream)
+                .filter(controller -> controller instanceof TelephonyAvailabilityHandler)
+                .map(TelephonyAvailabilityHandler.class::cast)
+                .forEach(controller -> {
+                    controller.unsetAvailabilityStatus(false);
+                });
+    }
+
     @Override
     public void onExpandButtonClick() {
         final PreferenceScreen screen = getPreferenceScreen();
diff --git a/src/com/android/settings/network/telephony/TelephonyAvailabilityHandler.java b/src/com/android/settings/network/telephony/TelephonyAvailabilityHandler.java
new file mode 100644
index 0000000..50dd26b
--- /dev/null
+++ b/src/com/android/settings/network/telephony/TelephonyAvailabilityHandler.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Interface letting {@link TelephonyTogglePreferenceController and
+ * @link TelephonyBasePreferenceController} can handle availability status.
+ */
+package com.android.settings.network.telephony;
+
+import android.content.Context;
+
+public interface TelephonyAvailabilityHandler {
+
+    /**
+     * Set availability to preference controller.
+     */
+    public void setAvailabilityStatus(int status);
+
+    /**
+     * Do not set availability, use
+     * {@link MobileNetworkUtils#getAvailability(Context, int, TelephonyAvailabilityCallback)}
+     * to get the availability.
+     */
+    public void unsetAvailabilityStatus(boolean enable);
+}
diff --git a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
index 241dc5d..678209d 100644
--- a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
+++ b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
@@ -23,12 +23,17 @@
 
 import com.android.settings.core.BasePreferenceController;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * {@link BasePreferenceController} that used by all preferences that requires subscription id.
  */
 public abstract class TelephonyBasePreferenceController extends BasePreferenceController
-        implements TelephonyAvailabilityCallback {
+        implements TelephonyAvailabilityCallback, TelephonyAvailabilityHandler {
     protected int mSubId;
+    private AtomicInteger mAvailabilityStatus = new AtomicInteger(0);
+    private AtomicBoolean mUnsetAvailabilityStatus = new AtomicBoolean(false);
 
     public TelephonyBasePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
@@ -37,7 +42,21 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return MobileNetworkUtils.getAvailability(mContext, mSubId, this::getAvailabilityStatus);
+        if (!mUnsetAvailabilityStatus.get()) {
+            mAvailabilityStatus.set(MobileNetworkUtils
+                    .getAvailability(mContext, mSubId, this::getAvailabilityStatus));
+        }
+        return mAvailabilityStatus.get();
+    }
+
+    @Override
+    public void setAvailabilityStatus(int status) {
+        mAvailabilityStatus.set(status);
+    }
+
+    @Override
+    public void unsetAvailabilityStatus(boolean enable) {
+        mUnsetAvailabilityStatus.set(enable);
     }
 
     /**
diff --git a/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java b/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java
index fc30030..56d51eb 100644
--- a/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java
+++ b/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java
@@ -23,12 +23,18 @@
 
 import com.android.settings.core.TogglePreferenceController;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * {@link TogglePreferenceController} that used by all preferences that requires subscription id.
  */
 public abstract class TelephonyTogglePreferenceController extends TogglePreferenceController
-        implements TelephonyAvailabilityCallback {
+        implements TelephonyAvailabilityCallback, TelephonyAvailabilityHandler {
     protected int mSubId;
+    private AtomicInteger mAvailabilityStatus = new AtomicInteger(0);
+    private AtomicBoolean mUnsetAvailabilityStatus = new AtomicBoolean(false);
+
 
     public TelephonyTogglePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
@@ -37,7 +43,21 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return MobileNetworkUtils.getAvailability(mContext, mSubId, this::getAvailabilityStatus);
+        if (!mUnsetAvailabilityStatus.get()) {
+            mAvailabilityStatus.set(MobileNetworkUtils
+                    .getAvailability(mContext, mSubId, this::getAvailabilityStatus));
+        }
+        return mAvailabilityStatus.get();
+    }
+
+    @Override
+    public void setAvailabilityStatus(int status) {
+        mAvailabilityStatus.set(status);
+    }
+
+    @Override
+    public void unsetAvailabilityStatus(boolean enable) {
+        mUnsetAvailabilityStatus.set(enable);
     }
 
     /**