From 18bbda7eff5bfdaf1161d035055c25e58820aa69 Mon Sep 17 00:00:00 2001 From: Hyunho Date: Tue, 21 Nov 2023 06:20:34 +0000 Subject: [PATCH] Enalbe the convert to eSIM menu Bug : b/314881248 Test: manual done Change-Id: Ib320cf3b3fc06ccf46be98f8c7afbe480df3bb79 --- .../ConvertToEsimPreferenceController.java | 110 +++++++++++++++--- 1 file changed, 96 insertions(+), 14 deletions(-) diff --git a/src/com/android/settings/network/telephony/ConvertToEsimPreferenceController.java b/src/com/android/settings/network/telephony/ConvertToEsimPreferenceController.java index b4e768c8f9d..a17144fcf34 100644 --- a/src/com/android/settings/network/telephony/ConvertToEsimPreferenceController.java +++ b/src/com/android/settings/network/telephony/ConvertToEsimPreferenceController.java @@ -19,7 +19,19 @@ package com.android.settings.network.telephony; import static androidx.lifecycle.Lifecycle.Event.ON_START; import static androidx.lifecycle.Lifecycle.Event.ON_STOP; +import android.Manifest; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ComponentInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.service.euicc.EuiccService; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.euicc.EuiccManager; import android.text.TextUtils; import androidx.annotation.VisibleForTesting; @@ -29,12 +41,12 @@ import androidx.lifecycle.OnLifecycleEvent; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; +import com.android.internal.telephony.util.TelephonyUtils; import com.android.settings.network.MobileNetworkRepository; import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.mobile.dataservice.DataServiceUtils; -import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; -import com.android.settingslib.mobile.dataservice.UiccInfoEntity; + +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -47,6 +59,9 @@ public class ConvertToEsimPreferenceController extends TelephonyBasePreferenceCo private MobileNetworkRepository mMobileNetworkRepository; private List mSubscriptionInfoEntityList = new ArrayList<>(); private SubscriptionInfoEntity mSubscriptionInfoEntity; + private static int sQueryFlag = + PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DIRECT_BOOT_AUTO + | PackageManager.GET_RESOLVED_FILTER; public ConvertToEsimPreferenceController(Context context, String key, Lifecycle lifecycle, LifecycleOwner lifecycleOwner, int subId) { @@ -83,11 +98,14 @@ public class ConvertToEsimPreferenceController extends TelephonyBasePreferenceCo @Override public int getAvailabilityStatus(int subId) { - return CONDITIONALLY_UNAVAILABLE; // TODO(b/262195754): Need the intent to enabled the feature. -// return mSubscriptionInfoEntity != null && mSubscriptionInfoEntity.isActiveSubscriptionId -// && !mSubscriptionInfoEntity.isEmbedded ? AVAILABLE -// : CONDITIONALLY_UNAVAILABLE; + if (findConversionSupportComponent()) { + return mSubscriptionInfoEntity != null && mSubscriptionInfoEntity.isActiveSubscriptionId + && !mSubscriptionInfoEntity.isEmbedded && isActiveSubscription(subId) + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + return CONDITIONALLY_UNAVAILABLE; } @VisibleForTesting @@ -104,6 +122,9 @@ public class ConvertToEsimPreferenceController extends TelephonyBasePreferenceCo return false; } // Send intent to launch LPA + Intent intent = new Intent(EuiccManager.ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION); + intent.putExtra("subId", mSubId); + mContext.startActivity(intent); return true; } @@ -115,12 +136,73 @@ public class ConvertToEsimPreferenceController extends TelephonyBasePreferenceCo @Override public void onActiveSubInfoChanged(List subInfoEntityList) { // TODO(b/262195754): Need the intent to enabled the feature. -// mSubscriptionInfoEntityList = subInfoEntityList; -// mSubscriptionInfoEntityList.forEach(entity -> { -// if (Integer.parseInt(entity.subId) == mSubId) { -// mSubscriptionInfoEntity = entity; -// update(); -// } -// }); + mSubscriptionInfoEntityList = subInfoEntityList; + mSubscriptionInfoEntityList.forEach(entity -> { + if (Integer.parseInt(entity.subId) == mSubId) { + mSubscriptionInfoEntity = entity; + update(); + } + }); + } + + private boolean isActiveSubscription(int subId) { + SubscriptionManager subscriptionManager = mContext.getSystemService( + SubscriptionManager.class); + SubscriptionInfo subInfo = subscriptionManager.getActiveSubscriptionInfo(subId); + if (subInfo == null) { + return false; + } + return true; + } + + private boolean findConversionSupportComponent() { + Intent intent = new Intent(EuiccService.ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION); + PackageManager packageManager = mContext.getPackageManager(); + List resolveInfoList = packageManager + .queryIntentActivities(intent, sQueryFlag); + if (resolveInfoList == null || resolveInfoList.isEmpty()) { + return false; + } + for (ResolveInfo resolveInfo : resolveInfoList) { + if (!isValidEuiccComponent(packageManager, resolveInfo)) { + continue; + } else { + return true; + } + } + return true; + } + + private boolean isValidEuiccComponent( + PackageManager packageManager, @NotNull ResolveInfo resolveInfo) { + ComponentInfo componentInfo = TelephonyUtils.getComponentInfo(resolveInfo); + String packageName = new ComponentName(componentInfo.packageName, componentInfo.name) + .getPackageName(); + + // Verify that the app is privileged (via granting of a privileged permission). + if (packageManager.checkPermission( + Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS, packageName) + != PackageManager.PERMISSION_GRANTED) { + return false; + } + + // Verify that only the system can access the component. + final String permission; + if (componentInfo instanceof ServiceInfo) { + permission = ((ServiceInfo) componentInfo).permission; + } else if (componentInfo instanceof ActivityInfo) { + permission = ((ActivityInfo) componentInfo).permission; + } else { + return false; + } + if (!TextUtils.equals(permission, Manifest.permission.BIND_EUICC_SERVICE)) { + return false; + } + + // Verify that the component declares a priority. + if (resolveInfo.filter == null || resolveInfo.filter.getPriority() == 0) { + return false; + } + return true; } }