From dda58d5255920658d7c693e94a43cfe2edc87fc2 Mon Sep 17 00:00:00 2001 From: Bonian Chen Date: Tue, 20 Dec 2022 11:55:08 +0000 Subject: [PATCH] [Settings] Present EID in About phone page Present EID within about phone page. Bug: 260540995 Test: local Change-Id: If5f512c1da6b4b3b1adc1d13dbe11226b7ecad41 --- res/layout/dialog_eid_status.xml | 40 ++++ res/values/strings.xml | 4 + res/xml/my_device_info.xml | 14 +- .../aboutphone/MyDeviceInfoFragment.java | 9 + .../deviceinfo/simstatus/EidStatus.java | 151 +++++++++++++++ .../simstatus/SimEidPreferenceController.java | 178 ++++++++++++++++++ 6 files changed, 395 insertions(+), 1 deletion(-) create mode 100644 res/layout/dialog_eid_status.xml create mode 100644 src/com/android/settings/deviceinfo/simstatus/EidStatus.java create mode 100644 src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.java diff --git a/res/layout/dialog_eid_status.xml b/res/layout/dialog_eid_status.xml new file mode 100644 index 00000000000..95d4872cd7f --- /dev/null +++ b/res/layout/dialog_eid_status.xml @@ -0,0 +1,40 @@ + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index a97c3d56eb0..2a2cccf4bd2 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2415,6 +2415,10 @@ Storage & cache Storage settings + + EID + + EID (sim slot %1$d) IMEI (sim slot %1$d) diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml index 9f14026ebd7..4cbe13f1207 100644 --- a/res/xml/my_device_info.xml +++ b/res/xml/my_device_info.xml @@ -105,7 +105,7 @@ + + + mEid = new AtomicReference(); + + /** + * Construct of class. + * @param slotSimStatus SlotSimStatus + * @param context Context + */ + public EidStatus(SlotSimStatus slotSimStatus, Context context) { + this(slotSimStatus, context, null); + } + + /** + * Construct of class. + * @param slotSimStatus SlotSimStatus + * @param context Context + * @param executor executor for offload to thread + */ + public EidStatus(SlotSimStatus slotSimStatus, Context context, Executor executor) { + mSlotSimStatus = slotSimStatus; + + if (executor == null) { + getEidOperation(context); + } else { + executor.execute(() -> getEidOperation(context)); + } + } + + /** + * Get the EID + * @return EID string + */ + public String getEid() { + mBlocker.awaitAdvance(0); + return mEid.get(); + } + + protected TelephonyManager getTelephonyManager(Context context) { + return context.getSystemService(TelephonyManager.class); + } + + protected EuiccManager getEuiccManager(Context context) { + return context.getSystemService(EuiccManager.class); + } + + protected String getDefaultEid(EuiccManager euiccMgr) { + if ((euiccMgr == null) || (!euiccMgr.isEnabled())) { + return null; + } + return euiccMgr.getEid(); + } + + protected void getEidOperation(Context context) { + EuiccManager euiccMgr = getEuiccManager(context); + String eid = getEidPerSlot(context, euiccMgr); + if (eid == null) { + eid = getDefaultEid(euiccMgr); + } + mEid.set(eid); + mBlocker.arrive(); + } + + protected String getEidPerSlot(Context context, EuiccManager euiccMgr) { + if (mSlotSimStatus.size() <= SimStatusDialogController.MAX_PHONE_COUNT_SINGLE_SIM) { + return null; + } + + TelephonyManager telMgr = getTelephonyManager(context); + if (telMgr == null) { + return null; + } + + List uiccCardInfoList = telMgr.getUiccCardsInfo(); + if (uiccCardInfoList == null) { + return null; + } + + // Collects all card ID from all eSIM(s) reported from SubscsriptionManager + final int [] cardIdList = IntStream.range(0, mSlotSimStatus.size()) + .mapToObj(slotIdx -> mSlotSimStatus.getSubscriptionInfo(slotIdx)) + .filter(Objects::nonNull) + .filter(SubscriptionInfo::isEmbedded) + .mapToInt(SubscriptionInfo::getCardId) + .sorted() + .distinct() + .toArray(); + if (cardIdList.length == 0) { + return null; + } + + /** + * Find EID from first slot which contains an eSIM and with card ID listed within + * the eSIM card ID provided by SubscsriptionManager. + */ + return uiccCardInfoList.stream() + .filter(UiccCardInfo::isEuicc) + .filter(cardInfo -> { + int cardId = cardInfo.getCardId(); + return Arrays.binarySearch(cardIdList, cardId) >= 0; + }) + .map(cardInfo -> { + String eid = cardInfo.getEid(); + if (TextUtils.isEmpty(eid)) { + eid = euiccMgr.createForCardId(cardInfo.getCardId()).getEid(); + } + return eid; + }) + .findFirst() + .orElse(null); + } + +} diff --git a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.java b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.java new file mode 100644 index 00000000000..e0a8af67fc9 --- /dev/null +++ b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.java @@ -0,0 +1,178 @@ +/* + * 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.deviceinfo.simstatus; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.os.UserManager; +import android.telephony.SubscriptionInfo; +import android.text.TextUtils; +import android.util.Log; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; +import androidx.annotation.VisibleForTesting; +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.Utils; +import com.android.settingslib.qrcode.QrCodeGenerator; + +/** + * This is to show a preference regarding EID of SIM card. + */ +public class SimEidPreferenceController extends BasePreferenceController + implements DialogInterface.OnShowListener { + + private static final String TAG = "SimEidPreferenceController"; + + private SlotSimStatus mSlotSimStatus; + private EidStatus mEidStatus; + private boolean mShowEidOnSummary; + private TelephonyPreferenceDialog mPreference; + + /** + * Constructer. + * @param context Context + * @param preferenceKey is the key for Preference + */ + public SimEidPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + /** + * Update status. + * + * @param slotSimStatus sim status per slot + * @param eidStatus status of EID + */ + public void init(SlotSimStatus slotSimStatus, EidStatus eidStatus) { + mSlotSimStatus = slotSimStatus; + mEidStatus = eidStatus; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + if ((!SubscriptionUtil.isSimHardwareVisible(mContext)) || (mSlotSimStatus == null)) { + return; + } + TelephonyPreferenceDialog preference = (TelephonyPreferenceDialog) + screen.findPreference(getPreferenceKey()); + if (preference == null) { + return; + } + + preference.setTitle(getTitle()); + mPreference = preference; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (TextUtils.equals(preference.getKey(), getPreferenceKey())) { + TelephonyPreferenceDialog preferenceDialog = (TelephonyPreferenceDialog)preference; + preferenceDialog.setDialogTitle(getTitle()); + preferenceDialog.setDialogMessage(mEidStatus.getEid()); + preferenceDialog.setOnShowListener(this); + return true; + } + return super.handlePreferenceTreeClick(preference); + } + + /** + * Construct title string. + * @return title string + */ + @VisibleForTesting + protected CharSequence getTitle() { + int slotSize = (mSlotSimStatus == null) ? 0 : mSlotSimStatus.size(); + if (slotSize <= SimStatusDialogController.MAX_PHONE_COUNT_SINGLE_SIM) { + return mContext.getString(R.string.status_eid); + } + // Only append slot index to title when more than 1 is available + for (int idxSlot = 0; idxSlot < slotSize; idxSlot++) { + SubscriptionInfo subInfo = mSlotSimStatus.getSubscriptionInfo(idxSlot); + if ((subInfo != null) && subInfo.isEmbedded()) { + return mContext.getString(R.string.eid_multi_sim, idxSlot+1); + } + } + return mContext.getString(R.string.status_eid); + } + + @Override + public CharSequence getSummary() { + String summary = mShowEidOnSummary ? mEidStatus.getEid() : null; + if (TextUtils.isEmpty(summary)) { + summary = mContext.getString(R.string.device_info_protected_single_press); + } + return summary; + } + + @Override + public int getAvailabilityStatus() { + if (!SubscriptionUtil.isSimHardwareVisible(mContext)) { + return UNSUPPORTED_ON_DEVICE; + } + boolean isAvailable = SubscriptionUtil.isSimHardwareVisible(mContext) && + mContext.getSystemService(UserManager.class).isAdminUser() && + !Utils.isWifiOnly(mContext); + return isAvailable ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; + } + + /** + * Callback when dialog end of show(). + */ + public void onShow(DialogInterface dialog) { + Dialog dialogShwon = mPreference.getDialog(); + + dialogShwon.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, + WindowManager.LayoutParams.FLAG_SECURE); + dialogShwon.setCanceledOnTouchOutside(false); + + TextView textView = dialogShwon.findViewById(R.id.esim_id_value); + textView.setText(PhoneNumberUtil.expandByTts(mEidStatus.getEid())); + textView.setTextIsSelectable(true); + + ImageView qrCodeView = dialogShwon.findViewById(R.id.esim_id_qrcode); + qrCodeView.setImageBitmap(getEidQRcode(mEidStatus.getEid().toString(), + qrCodeView.getWidth())); + + mShowEidOnSummary = true; + } + + /** + * Get the QR code for EID + * @param eid is the EID string + * @param widthInPixel is the width of Bitmap in pixel + * @return a Bitmap of QR code + */ + public Bitmap getEidQRcode(String eid, int widthInPixel) { + Bitmap qrCodeBitmap = null; + try { + qrCodeBitmap = QrCodeGenerator.encodeQrCode(eid, widthInPixel); + } catch (Exception exception) { + Log.w(TAG, "Error when creating QR code width " + widthInPixel, exception); + } + return qrCodeBitmap; + } +}