Async load eid in SimEidPreferenceController

Avoid data loading in getAvailabilityStatus() to prevent ANR, override
updateNonIndexableKeys() for search availability.

Fix: 304560734
Test: manual - on "About phone" page
Change-Id: I9994abf3787f5db0edc71ff48d08e549a4b70bf7
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 9325969..29c3c62 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -114,7 +114,7 @@
             settings:controller="com.android.settings.deviceinfo.HardwareInfoPreferenceController"/>
 
         <!-- EID -->
-        <com.android.settings.network.telephony.TelephonyPreferenceDialog
+        <com.android.settingslib.CustomDialogPreferenceCompat
             android:key="eid_info"
             android:order="31"
             android:title="@string/status_eid"
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
index 4d1b90b..5a3ff49 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
+++ b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
@@ -21,16 +21,24 @@
 import android.view.WindowManager
 import android.widget.ImageView
 import android.widget.TextView
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import androidx.preference.Preference
 import androidx.preference.PreferenceScreen
 import com.android.settings.R
 import com.android.settings.core.BasePreferenceController
 import com.android.settings.deviceinfo.PhoneNumberUtil
 import com.android.settings.network.SubscriptionUtil
-import com.android.settings.network.telephony.TelephonyPreferenceDialog
+import com.android.settingslib.CustomDialogPreferenceCompat
 import com.android.settingslib.Utils
 import com.android.settingslib.qrcode.QrCodeGenerator
 import com.android.settingslib.spaprivileged.framework.common.userManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 
 /**
  * This is to show a preference regarding EID of SIM card.
@@ -41,7 +49,8 @@
     BasePreferenceController(context, preferenceKey) {
     private var slotSimStatus: SlotSimStatus? = null
     private var eidStatus: EidStatus? = null
-    private lateinit var preference: TelephonyPreferenceDialog
+    private lateinit var preference: CustomDialogPreferenceCompat
+    private var coroutineScope: CoroutineScope? = null
     private lateinit var eid: String
 
     fun init(slotSimStatus: SlotSimStatus?, eidStatus: EidStatus?) {
@@ -49,21 +58,51 @@
         this.eidStatus = eidStatus
     }
 
-    override fun getAvailabilityStatus(): Int {
-        if (!SubscriptionUtil.isSimHardwareVisible(mContext)) return UNSUPPORTED_ON_DEVICE
-        eid = eidStatus?.eid ?: ""
-        val isAvailable = mContext.userManager.isAdminUser &&
-            !Utils.isWifiOnly(mContext) &&
-            eid.isNotEmpty()
-        return if (isAvailable) AVAILABLE else CONDITIONALLY_UNAVAILABLE
-    }
+    /**
+     * Returns available here, but UI availability is retrieved asynchronously later.
+     *
+     * Check [updateNonIndexableKeys] for search availability.
+     */
+    override fun getAvailabilityStatus() = AVAILABLE
 
     override fun displayPreference(screen: PreferenceScreen) {
         super.displayPreference(screen)
         preference = screen.findPreference(preferenceKey)!!
-        val title = getTitle()
-        preference.title = title
-        preference.dialogTitle = title
+    }
+
+    override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        coroutineScope = viewLifecycleOwner.lifecycleScope
+        coroutineScope?.launch {
+            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                update()
+            }
+        }
+    }
+
+    private suspend fun update() {
+        val isAvailable = withContext(Dispatchers.Default) {
+            getIsAvailableAndUpdateEid()
+        }
+        preference.isVisible = isAvailable
+        if (isAvailable) {
+            val title = withContext(Dispatchers.Default) {
+                getTitle()
+            }
+            preference.title = title
+            preference.dialogTitle = title
+            updateDialog()
+        }
+    }
+
+    private fun getIsAvailableAndUpdateEid(): Boolean {
+        if (!SubscriptionUtil.isSimHardwareVisible(mContext) ||
+            !mContext.userManager.isAdminUser ||
+            Utils.isWifiOnly(mContext)
+        ) {
+            return false
+        }
+        eid = eidStatus?.eid ?: ""
+        return eid.isNotEmpty()
     }
 
     /** Constructs title string. */
@@ -82,13 +121,7 @@
         return mContext.getString(R.string.status_eid)
     }
 
-    override fun updateState(preference: Preference?) {
-        super.updateState(preference)
-
-        updateDialog()
-    }
-
-    private fun updateDialog() {
+    private suspend fun updateDialog() {
         val dialog = preference.dialog ?: return
         dialog.window?.setFlags(
             WindowManager.LayoutParams.FLAG_SECURE,
@@ -106,11 +139,17 @@
     }
 
     override fun handlePreferenceTreeClick(preference: Preference): Boolean {
-        if (preference.key == preferenceKey) {
-            this.preference.setOnShowListener { updateDialog() }
-            return true
+        if (preference.key != preferenceKey) return false
+        this.preference.setOnShowListener {
+            coroutineScope?.launch { updateDialog() }
         }
-        return super.handlePreferenceTreeClick(preference)
+        return true
+    }
+
+    override fun updateNonIndexableKeys(keys: MutableList<String>) {
+        if (!getIsAvailableAndUpdateEid()) {
+            keys.add(preferenceKey)
+        }
     }
 
     companion object {
@@ -122,11 +161,13 @@
          * @param eid is the EID string
          * @return a Bitmap of QR code
          */
-        private fun getEidQrCode(eid: String): Bitmap? = try {
-            QrCodeGenerator.encodeQrCode(eid, QR_CODE_SIZE)
-        } catch (exception: Exception) {
-            Log.w(TAG, "Error when creating QR code width $QR_CODE_SIZE", exception)
-            null
+        private suspend fun getEidQrCode(eid: String): Bitmap? = withContext(Dispatchers.Default) {
+            try {
+                QrCodeGenerator.encodeQrCode(contents = eid, size = QR_CODE_SIZE)
+            } catch (exception: Exception) {
+                Log.w(TAG, "Error when creating QR code width $QR_CODE_SIZE", exception)
+                null
+            }
         }
     }
 }
diff --git a/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java b/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java
deleted file mode 100644
index 7dbef0c..0000000
--- a/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-package com.android.settings.network.telephony;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import com.android.settingslib.CustomDialogPreferenceCompat;
-
-/**
- * This is DialogPreference for supporting connectivity features.
- */
-public class TelephonyPreferenceDialog extends CustomDialogPreferenceCompat {
-
-    public TelephonyPreferenceDialog(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    public TelephonyPreferenceDialog(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    public TelephonyPreferenceDialog(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public TelephonyPreferenceDialog(Context context) {
-        super(context);
-    }
-}