• [MT8766][Android12] 使用谷歌LPA实现ESIM功能的流程


    开发平台基本信息

    芯片: MT8766
    版本: Android 12
    kernel: msm-4.19

    问题描述

    客户需要我们设备支持ESIM功能,5月份的时候在高通6125上面预研过ESIM功能,当时ESIM供应商是Links field,集成流程只是内置了ESIM厂商的apk,并且开启了feature以及默认给了一些权限,具体ESIM功能的实现都是在厂商的apk中,所以就没去深入研究ESIM功能。但是,由于Links field报价过高,所以这次又找了两家ESIM厂商,分别是鹏越与紫光;鹏越只把他们的ESIM芯片寄给了我们,然后让我们去找GMS实验室要LPA的相关资料,按照谷歌的标准流程操作,即可实现ESIM功能;而紫光则提供了一个他们的apk,并且要求给权限与feature,与之前的Links field类似。GMS实验室提供了一份资料,里面包含了3份文档以及一个apk。
    三份文档的内容大致为:

    • 1、如何集成LPA
    • 2、如何实现overlay app
    • 3、如何在开机向导和系统设置增加ESIM选项

    ESIM功能可以简单理解为,ESIM厂家提供芯片,芯片分为贴片式跟拔插式,贴片式是贴到主板上,类似于各种单片机;而拔插式则是一张实体ESIM卡,长得跟普通的SIM卡一样,需要插入到卡槽中才能使用;然后,就到ESIM运营商购买ESIM卡号,安卓系统就可以通过谷歌LPA服务将购买的ESIM卡号下载到ESIM芯片中,下载完成启用ESIM卡就能正常使用了,一张ESIM芯片可以下载多个ESIM卡,但是,设备最多只能启用一张ESIM。

    实现流程

    在验证ESIM功能之前,可以先到设置-关于手机-sim卡详细信息中查看是否有EID,EID是ESIM芯片的唯一标识,代表着ESIM的正常使用,如果设备无法读取到EID,得排查硬件通路以及modem。

    ESIM功能都实现流程可以分为以下几个步骤:

    • 启用euicc的feature
    • 内置谷歌LPA服务到system/priv-app/
    • 给LPA服务增加priv-app权限或者关闭权限校验
    • 增加overlay app
    • 在系统设置中,调起LPA服务下载ESIM卡号,并启用ESIM

    framework中已经有euicc的feature,只需要拷贝到设备即可

    --- a/device/mediateksample/custom_go/full_custom_go.mk
    +++ b/device/mediateksample/custom_go/full_custom_go.mk
    @@ -7,3 +7,11 @@ MTK_TARGET_PROJECT_FOLDER := $(LOCAL_PATH)
     -include $(MTK_TARGET_PROJECT_FOLDER)/vnd_$(MTK_TARGET_PROJECT).mk
     
     PRODUCT_NAME := full_custom_go
     
    +PRODUCT_COPY_FILES += \
    +	frameworks/native/data/etc/android.hardware.telephony.euicc.xml:system/etc/permissions/android.hardware.telephony.euicc.xml \
    +
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    内置谷歌LPA服务到system/priv-app/

    --- a/device/mediateksample/p8_go/full_custom_go.mk
    +++ b/device/mediateksample/p8_go/full_custom_go.mk
    @@ -7,3 +7,11 @@ MTK_TARGET_PROJECT_FOLDER := $(LOCAL_PATH)
     -include $(MTK_TARGET_PROJECT_FOLDER)/vnd_$(MTK_TARGET_PROJECT).mk
     
     PRODUCT_NAME := full_custom_go
    +
    +PRODUCT_PACKAGES += \
    +	EuiccGoogle \
    +
    
    
    LOCAL_PATH := $(call my-dir)
    
    ###############################################################################
    include $(CLEAR_VARS)
    LOCAL_MODULE 				:= EuiccGoogle
    LOCAL_SRC_FILES 			:= EuiccGoogle.apk
    LOCAL_MODULE_CLASS 			:= APPS
    LOCAL_CERTIFICATE 			:= PRESIGNED
    LOCAL_PRIVILEGED_MODULE 	:= true
    LOCAL_MODULE_TAGS 			:= optional
    include $(BUILD_PREBUILT)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    给LPA服务增加priv-app权限或者关闭权限校验,这里选择的是关闭权限校验

    --- a/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
    +++ b/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
    @@ -3469,6 +3469,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                 @NonNull PackageSetting packageSetting, @NonNull Permission permission) {
             if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) {
                 return true;
    +        }else if (!RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) {
    +            return true;
             }
             final String packageName = pkg.getPackageName();
             if (Objects.equals(packageName, PLATFORM_PACKAGE_NAME)) {
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    增加overlay app,这个app是自己写的,需要实现几个功能

    • 在AndroidManifest.xml中注册广播
            <receiver
                android:name=".PartnerReceiver"
                android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
                android:directBootAware="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="com.google.android.euicc.action.PARTNER_CUSTOMIZATION" />
                </intent-filter>
            </receiver>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 在java文件中实现广播,并且广播方法中必须为空
    package com.tp.euicc.overlay;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    
    public class PartnerReceiver extends BroadcastReceiver {
    
        public PartnerReceiver() {
    
        }
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • res/values/strings.xml中增加两个字段
        <string name="sim_slot_mappings_json" translatable="false">{"sim-slot-mappings":[{"devices":["custom_go"],"esim-slot-ids":[0],"psim-slot-ids":[1]}]}string>
    
        <integer name="download_type">3integer>
    
    • 1
    • 2
    • 3

    谷歌LPA就是通过广播找到overlay app,然后从app的资源文件中获取sim_slot_mappings_json的值,拿到配置数据,其中devices的值要修改为Build.DEVICE,如果是其他项目移植要记得修改。后面的esim是虚拟sim卡,psim是物理sim卡,ids的值分别是对应的卡槽,比如在SIM 1卡槽接了ESIM,这里就配成0,不过实际测试,不过怎么配置ids,都能使用ESIM。

    在系统设置中,调起LPA服务下载ESIM卡号,并启用ESIM
    按照上面的方式集成之后,在系统设置-网络-移动网络选项,如果没有下载过ESIM,点击就会调起谷歌LPA服务,或者可以通过adb广播调起LPA配置界面,然后根据提示,扫描二维码,下载ESIM卡号即可。

    adb shell am start -n
    "com.google.android.euicc/com.android.euicc.ui.settings.CurrentProfileListActivity"
    
    • 1
    • 2

    其他问题

    之前在2290上面调试,出现下载完ESIM卡号之后,无法启用ESIM功能,需要在ESIM界面开、关一次飞行模式,ESIM启用按钮才可以点击。解决方案如下:

    --- a/QSSI.12/packages/apps/Settings/src/com/android/settings/network/telephony/MobileNetworkSettings.java
    +++ b/QSSI.12/packages/apps/Settings/src/com/android/settings/network/telephony/MobileNetworkSettings.java
    @@ -58,6 +58,7 @@ import com.android.settingslib.search.SearchIndexable;
     import com.android.settingslib.utils.ThreadUtils;
     
     import org.codeaurora.internal.IExtTelephony;
     
     import java.util.Arrays;
     import java.util.List;
    @@ -106,7 +107,8 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
     
         private void setScreenState() {
             int simState = mTelephonyManager.getSimState();
    -        boolean screenState = simState != TelephonyManager.SIM_STATE_ABSENT;
    +        // boolean screenState = simState != TelephonyManager.SIM_STATE_ABSENT;
    +        boolean screenState = true;
             if (screenState) {
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在MTK8766中同样出现不可点击的问题,而且还把白卡显示出来,造成了混淆,解决方案如下:

    --- a/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/network/MobileNetworkListController.java
    +++ b/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/network/MobileNetworkListController.java
    @@ -26,7 +26,9 @@ import android.content.Intent;
     import android.provider.Settings;
     import android.telephony.SubscriptionInfo;
     import android.telephony.SubscriptionManager;
    +import android.telephony.euicc.EuiccManager;
     import android.util.ArrayMap;
    +import android.util.Log;
     
     import androidx.lifecycle.Lifecycle;
     import androidx.lifecycle.LifecycleObserver;
    @@ -122,7 +124,7 @@ public class MobileNetworkListController extends AbstractPreferenceController im
                     } else {
                         pref.setSummary(R.string.mobile_network_inactive_esim);
                         /// M: Add for updating enabled state.
    -                    pref.setEnabled(false);
    +                    //pref.setEnabled(false);
                     }
                 } else {
                     if (mSubscriptionManager.isActiveSubscriptionId(subId)) {
    @@ -130,7 +132,7 @@ public class MobileNetworkListController extends AbstractPreferenceController im
                     } else if (SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager)) {
                         pref.setSummary(mContext.getString(R.string.mobile_network_inactive_sim));
                         /// M: Add for updating enabled state.
    -                    pref.setEnabled(false);
    +                    //pref.setEnabled(false);
                     } else {
                         pref.setSummary(mContext.getString(R.string.mobile_network_tap_to_activate,
                                 displayName));
    @@ -138,7 +140,14 @@ public class MobileNetworkListController extends AbstractPreferenceController im
                 }
     
                 pref.setOnPreferenceClickListener(clickedPref -> {
    -                if (!info.isEmbedded() && !mSubscriptionManager.isActiveSubscriptionId(subId)
    +                Log.d(TAG, "clickedPref isEmbedded: " + (info.isEmbedded()));
    +                               Log.d(TAG, "clickedPref isActiveSubscriptionId: " + (mSubscriptionManager.isActiveSubscriptionId(subId)));
    +                Log.d(TAG, "clickedPref showToggleForPhysicalSim: " + (SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager)));
    +                               /// M: Add for updating enabled state.
    +                               if(info.isEmbedded()){
    +                                       Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
    +                                       mContext.startActivity(intent);
    +                }else if (!info.isEmbedded() && !mSubscriptionManager.isActiveSubscriptionId(subId)
                             && !SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager)) {
                         SubscriptionUtil.startToggleSubscriptionDialogActivity(mContext, subId, true);
                     } else {
    --- a/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/network/MobileNetworkSummaryController.java
    +++ b/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/network/MobileNetworkSummaryController.java
    @@ -258,8 +258,17 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
                     mPreference.setEnabled(false);
                 }
                 /// @}
    -        } else {
    -            mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
    +        } else {                       
    +                       /// M: Add for updating enabled state.
    +                       mPreference.setOnPreferenceClickListener((Preference pref) -> {
    +                logPreferenceClick(pref);
    +
    +                Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
    +                               mContext.startActivity(intent);
    +                return true;
    +            });
    +                       
    +            //mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
             }
         }
    --- a/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/network/telephony/MobileNetworkSettings.java
    +++ b/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/network/telephony/MobileNetworkSettings.java
    @@ -27,6 +27,7 @@ import android.provider.Settings;
     import android.provider.SearchIndexableResource;
     import android.telephony.SubscriptionManager;
     import android.telephony.TelephonyManager;
    +import android.telephony.euicc.EuiccManager;
     import android.text.TextUtils;
     import android.util.Log;
     import android.view.Menu;
    @@ -100,8 +101,12 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
                 return true;
             }
             final String key = preference.getKey();
    +               
    +               Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
    +               startActivity(intent);
    +               return true;
     
    -        if (TextUtils.equals(key, BUTTON_CDMA_SYSTEM_SELECT_KEY)
    +        /*if (TextUtils.equals(key, BUTTON_CDMA_SYSTEM_SELECT_KEY)
                     || TextUtils.equals(key, BUTTON_CDMA_SUBSCRIPTION_KEY)) {
                 if (mTelephonyManager.getEmergencyCallbackMode()) {
                     startActivityForResult(
    @@ -112,7 +117,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
                 return true;
             }
     
    -        return false;
    +        return false;*/
         }
     
         @Override
    diff --git a/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/security/SimLockPreferenceController.java b/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/security/SimLockPreferenceController.java
    index 3b85888..98cbc9b 100644
    --- a/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/security/SimLockPreferenceController.java
    +++ b/vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/security/SimLockPreferenceController.java
    @@ -94,10 +94,10 @@ public class SimLockPreferenceController extends BasePreferenceController {
     
             for (SubscriptionInfo subInfo : subInfoList) {
                 final int simState = mTelephonyManager.getSimState(subInfo.getSimSlotIndex());
    -            if ((simState != TelephonyManager.SIM_STATE_ABSENT)
    -                    && (simState != TelephonyManager.SIM_STATE_UNKNOWN)) {
    +            // if ((simState != TelephonyManager.SIM_STATE_ABSENT)
    +            //         && (simState != TelephonyManager.SIM_STATE_UNKNOWN)) {
                     return true;
    -            }
    +            // }
             }
             return false;
         }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    MTK8766下载完ESIM卡号之后,有信号,能ping通百度,但是浏览器无法上网,最终定位是他们默认APN配置的问题

    --- a/device/mediatek/config/apns-conf.xml
    +++ b/device/mediatek/config/apns-conf.xml
    @@ -25782,12 +25782,12 @@
            mcc="454"
            mnc="00"
            apn="mobile"
    -       proxy="192.168.59.51"
    -       port="8080"
    -       mmsc="http://192.168.58.171:8002"
    -       mmsproxy="192.168.59.51"
    -       mmsport="8080"
    -       type="default,supl,mms"
    +       proxy=""
    +       port=""
    +       mmsc=""
    +       mmsproxy=""
    +       mmsport=""
    +       type="default,ia,supl"
            protocol="IPV4V6"
            roaming_protocol="IPV4V6"
       />
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    检查或复位状态[ feof()函数、ferror()函数和clearerr()函数 ]
    Oauth2系列6:隐式模式
    【升职加薪秘籍】我在服务监控方面的实践(6)-业务维度的mysql监控
    c++在线编辑器
    纺织ERP系统哪家的比较好?适用的纺织ERP软件有哪些
    微信小程序开发小程序下厨房|菜谱项目
    利用Flutter的特性最大程度提升iOS应用的用户体验
    第三方支付功能测试点【杭州多测师_王sir】【杭州多测师】
    Bio-Helix丨Bio-Helix艾美捷Ponceaus S染色液说明书
    Selenium基础
  • 原文地址:https://blog.csdn.net/Hebin320320/article/details/133779194