针对本系列前面几篇有提到安全硬件,但是这块接触的比较少,唯一接触到的场景有SecureElement,本篇主要就是围绕SecureElement的使用和相关案例进行解说。
一、SecureElement框架
Secure Element(安全元件)本质上是一个"高安全级别的执行与存储环境",专门用来存放敏感数据(比如密钥、证书、银行卡数据)并在受硬件保护的环境里执行安全逻辑(比如加解密、支付、认证),对外通过严格受控的接口提供服务。
Secure Element(简称SE)是一种以芯片形式存在的专用硬件组件。它通过物理隔离与防篡改设计来保护敏感数据,免受未经授权的访问,内部集成了加密/解密逻辑电路,并且与主处理器隔离运行,确保数据的安全性。
主要功能如下:
- 物理隔离与安全保护:SecureElement具有独立的执行环境和安全存储,软件和硬件上都具备防篡改能力。其内部组件包含CPU、RAM、ROM、加密引擎等。
- 安全存储与加密运算:它能够安全地存储密钥、证书、个人隐私数据等敏感信息,并提供数据加密运算功能。主要功能包括密钥的安全存储、数据加密运算和信息的安全存放。
- 多种实现形式:SecureElement可以封装成不同的形式,包括智能卡、嵌入式安全模块(eSE)、UICC(通用集成电路卡)以及Micro SD卡等。其中,eSE是嵌入在手机内部的芯片,UICC是SIM卡,Micro SD则是通过SD卡槽集成的芯片。
Secure Element 主要用于需要高安全级别的应用场景,常见形态如下:
- **eSE:**全称embedded Secure Element(嵌入式安全单元),一般是焊在主板上的一块安全芯片,不是"SIM 卡槽"那种可插拔形式。在手机里,这块eSE很常见的用途是和NFC绑在一起做安全支付(比如公交卡、门禁、银行卡等),因为NFC控制器可以通过硬件连线(SWP/I2C/SPI 等)访问这块 eSE。
- UICC:SIM 卡上的 SE,运营商的 SIM/USIM/eSIM 卡本身就带有 SE 功能,Android SIM1/SIM2 就是把 SIM 卡当作一个 SE。
- SD:带 SE功能的SD卡,这种比较少。
Secure Element 作为安全存储芯片,和普通存储/CPU 的区别:
- 有独立的安全认证与访问控制逻辑(像你看到的 AccessControlEnforcer、AID 权限规则)。
- 针对物理攻击、防篡改、防侧信道攻击做过专门设计与认证(例如符合某些安全等级标准)。
- 即便系统被 Root / 内核被攻破,要从 SE 里直接把密钥"拽"出来也非常困难。
Secure Element 和前文介绍的TEE这些又有什么样的关系呢?
- TEE(TrustZone 内的安全世界)也是一种安全执行环境,但通常和 AP 同一颗 SoC,不一定是"独立芯片",抽象层次略不同。
- TPM(传统 PC 上的可信模块)在"安全存储+安全操作"这个职责上和 SE 很像,只是接口与生态不同。
- 你可以粗略地把 SE 理解为"手机里的类似 TPM 的安全元件",只是形态可以是 eSE 芯片、SIM 卡等。
一句话总结Secure Element 就是手机里专门负责"高安全等级存储和执行(如支付、认证、加密)"的安全硬件/安全环境,在 Android 中通过 OMAPI 以 Reader / Session / Channel 的形式对外提供受控访问。
1、SecureElement应用端
在AOSP原生系统中,是存在一个叫做SecureElement的应用,应用源码路径在packages/apps/SecureElement:

在AOSP原生目录build/make/target/product/handheld_system.mk中进行预装,注意低配置的设备不支持此应用:

那么这个应用的关键信息有哪些呢?根据如下代码可以了解到:
- 包名:com.android.se
- 核心服务:SecureElementService
- 引用hardware库

1)SecureElementService服务注册
此应用没有界面,但是有一个核心服务SecureElementService,在应用创建的时候启动:
java
//packages/apps/SecureElement/src/com/android/se/SEApplication.java
//Starts the SecureElementService.
public class SEApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Intent serviceIntent = new Intent(getApplicationContext(), SecureElementService.class);
startService(serviceIntent);
}
}
SecureElementService作为APP层的核心服务,实现服务的生命周期:
java
//packages/apps/SecureElement/src/com/android/se/SecureElementService.java
public final class SecureElementService extends Service {
private final String mTag = "SecureElementService";
//此服务支持两个终端:SIM和eSE
public static final String UICC_TERMINAL = "SIM";
public static final String ESE_TERMINAL = "eSE";
public static final String VSTABLE_SECURE_ELEMENT_SERVICE = "android.se.omapi.ISecureElementService/default";
@Override
public IBinder onBind(Intent intent) {
Log.i(mTag, Thread.currentThread().getName() + " onBind");
if (ISecureElementService.class.getName().equals(intent.getAction())) {
return mSecureElementServiceBinder;
}
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(mTag, Thread.currentThread().getName() + " onCreate");
initialize();
//创建两个终端:SIM和eSE
createTerminals();
// Add vendor stable service only if it is configured
//向servicemanager注册android.se.omapi.ISecureElementService/default服务
if (getResources().getBoolean(R.bool.secure_element_vintf_enabled)) {
ServiceManager.addService(VSTABLE_SECURE_ELEMENT_SERVICE, mSecureElementServiceBinderVntf);
}
// Since ISecureElementService is marked with VINTF stability
// to use this same interface within the system partition, will use
// forceDowngradeToSystemStability and register it.
mSecureElementServiceBinder.forceDowngradeToSystemStability();
//向servicemanager注册secure_element服务
ServiceManager.addService(Context.SECURE_ELEMENT_SERVICE, mSecureElementServiceBinder);
}
//secure_element服务的具体实现
private final ISecureElementService.Stub mSecureElementServiceBinder = new SecureElementServiceBinder();
//android.se.omapi.ISecureElementService/default服务的具体实现
private final ISecureElementService.Stub mSecureElementServiceBinderVntf = new SecureElementServiceBinder();
}
如上向系统注册了secure_element服务,但是服务的具体实现如下:

如上代码如下:
- com.android.se应用维护了名叫做SecureElementService的服务
- com.android.se应用把SecureElementService注册成为了系统级服务
- com.android.se应用作为服务端应用进程,提供了如下功能:
- getReaders():拿到所有 SE 读卡器名字。
- getReader(name):拿到指定 Reader(背后是 Terminal.SecureElementReader)。
- isNfcEventAllowed():检查 NFC 事件是否允许发给某些 App。
因此可以看出SecureElementService服务管理了系统所有的安全芯片,并对外提供了OMAPI接口,主要暴露了如上三个接口。
2)SIM & eSE 终端管理
SecureElementService服务是如何管理系统所有支持的安全芯片呢?
仔细阅读此服务的代码,可以了解到一个叫做Terminal的概念,具体实现是在Terminal.java里面。
这里先说一下我的理解:Terminal翻译过来就是终端,可以看到一个SE芯片对应一个终端,例如SIM安全卡槽和eSE安全卡槽。

SecureElementService服务启动初始化的时候,注册了卡槽插拔事件,用于创建管理维护安全芯片列表mTerminals,如下经典代码:
java
//packages/apps/SecureElement/src/com/android/se/SecureElementService.java
public final class SecureElementService extends Service {
//主要两大类终端:SIM和eSE
public static final String UICC_TERMINAL = "SIM";
public static final String ESE_TERMINAL = "eSE";
// LinkedHashMap will maintain the order of insertion
private LinkedHashMap<String, Terminal> mTerminals = new LinkedHashMap<String, Terminal>();
private int mActiveSimCount = 0;
//核心流程一:添加UICC_TERMINAL终端
private void initialize() {
// 注册监听当前系统SIM卡槽获取数量
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED);
this.registerReceiver(mMultiSimConfigChangedReceiver, intentFilter);
}
private final BroadcastReceiver mMultiSimConfigChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED)) {
int activeSimCount = intent.getIntExtra(TelephonyManager.EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 1);
Log.i(mTag, "received action MultiSimConfigChanged. Refresh UICC terminals");
Log.i(mTag, "Current ActiveSimCount:" + activeSimCount + ". Previous ActiveSimCount:" + mActiveSimCount);
// 刷新SIM终端数量
refreshUiccTerminals(activeSimCount);
}
}
};
// 最后通过addTerminals去添加UICC_TERMINAL终端
private void refreshUiccTerminals(int activeSimCount) {
String name = null;
synchronized (this) {
if (activeSimCount < mActiveSimCount) {
// Remove non-supported UICC terminals
for (int i = activeSimCount + 1; i <= mActiveSimCount; i++) {
name = UICC_TERMINAL + Integer.toString(i);
Terminal terminal = mTerminals.get(name);
if (terminal != null) {
terminal.closeChannels();
terminal.close();
}
mTerminals.remove(name);
Log.i(mTag, name + " is removed from available Terminals");
}
mActiveSimCount = activeSimCount;
} else if (activeSimCount > mActiveSimCount) {
// Try to initialize new UICC terminals
addTerminals(UICC_TERMINAL);
}
}
}
//核心流程二:添加ESE_TERMINAL终端
@Override
public void onCreate() {
super.onCreate();
Log.i(mTag, Thread.currentThread().getName() + " onCreate");
initialize();
createTerminals();
//.......服务注册
}
//不需要判断,直接添加ESE_TERMINAL,因为是内置的
private void createTerminals() {
// Check for all SE HAL implementations
addTerminals(ESE_TERMINAL);
if (!SystemProperties.getBoolean("ro.radio.noril", false)) {
addTerminals(UICC_TERMINAL);
}
}
//核心流程三:addTerminals添加总段,其实
private void addTerminals(String terminalName) {
int index = 1;
int uicc_count = 0;
String name = null;
TelephonyManager mTelephonyManager;
mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
uicc_count = mTelephonyManager.getPhoneCount();
if (terminalName.startsWith(SecureElementService.UICC_TERMINAL)) index = mActiveSimCount + 1;
try {
do {
if((terminalName.equals(UICC_TERMINAL)) && (index > uicc_count)) break;
name = terminalName + Integer.toString(index);
//核心代码:实例化对象Terminal
Terminal terminal = new Terminal(name, this);
Log.i(mTag, "Check if terminal " + name + " is available.");
// Only retry on fail for the first terminal of each type.
terminal.initialize(index == 1);
//核心代码:添加到SE列表mTerminals中
mTerminals.put(name, terminal);
if (terminalName.equals(UICC_TERMINAL)) mActiveSimCount = index;
} while (++index > 0);
} catch (NoSuchElementException e) {
Log.i(mTag, "No HAL implementation for " + name);
} catch (RemoteException | RuntimeException e) {
Log.e(mTag, "Error in getService() for " + name);
}
}
}
总结如上代码:
- 先监听ACTION_MULTI_SIM_CONFIG_CHANGED广播,进行添加或者移除SIM
- 然后直接添加eSE
- 最后判断系统如果支持蜂窝功能添加SIM
- 添加SE终端设备的方式就是直接new Terminal(),然后添加到mTerminals列表中
3)Terminal如何与HAL层通信?
Terminal 表示"一块具体的 Secure Element(比如某个 eSE1 或 SIM1)",负责这块 SE 的生命周期管理、和 HAL 的通信、通道(Channel)管理,以及访问控制(ACL)。
A Terminal连接hardware层

内部逻辑:
- 先尝试 android.hardware.secure_element.ISecureElement(AIDL)。
- 再尝试 android.hardware.secure_element.V1_2.ISecureElement。
- 再尝试 V1_1 / V1_0。
- 成功后调用 init(...) 注册回调,并 linkToDeath(...) 监听进程死亡。
- 实际业务调用 HAL:
- mAidlHal.getAtr() / mSEHal.getAtr() → 获取 ATR。
- mAidlHal.openBasicChannel() / mSEHal.openBasicChannel() → 开 basic channel。
- mAidlHal.openLogicalChannel() / mSEHal.openLogicalChannel() → 开 logical channel。
- mAidlHal.transmit() / mSEHal.transmit() → 发送 APDU。
- mAidlHal.closeChannel() / mSEHal.closeChannel() → 关闭通道。
- mAidlHal.isCardPresent() / mSEHal.isCardPresent() → 判断卡是否在。
- mAidlHal.reset() / mSEHal12.reset() → 触发 SE reset。
可以把 Terminal 看成 "framework(OMAPI) ↔ HAL 之间的适配器"。
B Terminal暴露接口
与 HAL/状态相关
- initialize(boolean retryOnFail):初始化与 HAL 的连接。
- getAtr():拿当前 SE 的 ATR。
- isSecureElementPresent():是否有卡/SE 在。
- reset():reset Secure Element。
- stateChange(boolean state, String reason)(内部):处理 HAL 状态回调,更新连接状态、重建 ACL。
通道管理
- openBasicChannel(SecureElementSession session, byte[] aid, byte p2, ISecureElementListener listener, String packageName, byte[] uuid, int pid)
- openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, ISecureElementListener listener, String packageName, byte[] uuid, int pid)
- openLogicalChannelWithoutChannelAccess(byte[] aid):内部使用,不做 ACL。
- closeChannel(Channel channel)
- closeChannels()
- close():解绑 death recipient
APDU 相关
- transmit(byte[] cmd):带 6C/61 处理的高层 transmit。
- transmitInternal(byte[] cmd):直接调 HAL 的低层 transmit。
- selectDefaultApplication() / 私有 select(byte[] aid):在 basic channel 上 select 应用。
访问控制 & NFC 事件
- isNfcEventAllowed(PackageManager pm, byte[] aid, String[] packageNames):NFC 事件是否允许给某些 App
- checkCarrierPrivilegeRules(PackageInfo pInfo):检查 carrier privilege
- getAccessControlEnforcer()、setUpChannelAccess(...)、initializeAccessControl():ACL 初始化和通道访问权限设置
- isAidSelectable(byte[] aid):检测某 AID 是否可以被 select(内部通过打开/关闭逻辑通道试探)。
最后一句话理解Terminal :一块具体 Secure Element(比如某张 SIM 卡或某个 eSE 芯片)的"驱动+管家":它一边直接和 HAL 打交道(开关通道、收发 APDU、reset),一边负责管理这块 SE 上所有的 channel/session,并通过访问控制组件决定哪些 App/UUID 能访问哪些 AID 和 NFC 事件。
2、secure_element硬件抽象层
SecureElement.apk虽然是一个apk的形态出现在我们的眼前,包名为com.android.se,但是在SecureElementService中给系统注册了secure_element服务,维护管理了UICC和eSM安全芯片设备,并以Terminal作为桥梁直接调用到了硬件抽象层,本节就针对secure_element硬件抽象层进行初步认识。

如上AOSP原生代码路径/hardware/st/目录下实现了nfc和secure_element两个模块的硬件抽象层。
同上面的介绍,nfc与secure_element其实是两个独立的模块:
- nfc:负责射频收发,是"天线 + 射频前端 + 协议栈",对外表现为"刷卡"的接口。
- secure_element:是一个高安全等级的"安全芯片/安全执行环境",用来存储密钥、证书、支付应用、交通卡应用等敏感数据,并在里面执行加解密、认证逻辑。
那么他们之间到底有什么联系呢?在很多设计里,NFC 控制器和 SE 之间有一条专用接口(如 SWP、DCLB、I²C/SPI 等),NFC 负责与读卡器或手机外部设备通信,再把 APDU 等命令透传给 SE,由 SE 完成安全处理。这是否可以理解se和tee之间到底有什么区别了吗?
本节跳过nfc,重点来看看secure_element,很明显在A16上面secure_element实现了两份,我们直接来看secure_element2吧:
bash
.
├── Android.bp
├── LICENSE
├── METADATA
├── MODULE_LICENSE_APACHE2
├── NOTICE -> LICENSE
├── OWNERS
└── secure_element
├── 1.0
│ ├── Android.bp
│ ├── android.hardware.secure_element@1.0-service-gto-ese2.rc
│ ├── android.hardware.secure_element@1.0-service-gto.rc
│ ├── GtoService.cpp
│ ├── GtoService_ese2.cpp
│ ├── SecureElement.cpp
│ ├── SecureElement.h
│ ├── SecureElementHalCallback.cpp
│ ├── SecureElementHalCallback.h
│ └── se-gto
│ └── libse-gto.h
├── 1.1
│ ├── Android.bp
│ ├── android.hardware.secure_element@1.1-service-gto-ese2.rc
│ ├── android.hardware.secure_element@1.1-service-gto.rc
│ ├── GtoService.cpp
│ ├── GtoService_ese2.cpp
│ ├── SecureElement.cpp
│ ├── SecureElement.h
│ └── se-gto
│ └── libse-gto.h
├── 1.2
│ ├── Android.bp
│ ├── android.hardware.secure_element@1.2-service-gto-ese2.rc
│ ├── android.hardware.secure_element@1.2-service-gto.rc
│ ├── GtoService.cpp
│ ├── GtoService_ese2.cpp
│ ├── SecureElement.cpp
│ ├── SecureElement.h
│ └── se-gto
│ └── libse-gto.h
├── aidl
│ ├── Android.bp
│ ├── android.hardware.secure_element_gto-ese2.rc
│ ├── android.hardware.secure_element_gto-ese2.xml
│ ├── android.hardware.secure_element_gto.rc
│ ├── android.hardware.secure_element_gto-st33.rc
│ ├── android.hardware.secure_element_gto-st33.xml
│ ├── android.hardware.secure_element_gto.xml
│ ├── GtoService.cpp
│ ├── GtoService-ese2.cpp
│ ├── GtoService-st33.cpp
│ ├── SecureElement.cpp
│ ├── SecureElement.h
│ └── se-gto
│ └── libse-gto.h
├── esehal
│ ├── Android.bp
│ └── src
│ ├── checksum.c
│ ├── checksum.h
│ ├── compiler.h
│ ├── iso7816_t1.c
│ ├── iso7816_t1.h
│ ├── libse-gto.c
│ ├── libse-gto-private.h
│ ├── linux
│ │ └── se_gemalto.h
│ ├── log.c
│ ├── log.h
│ ├── se-gto
│ │ └── libse-gto.h
│ ├── spi.c
│ ├── spi.h
│ ├── transport.c
│ └── transport.h
├── libse-gto-hal.conf
└── libse-gto-hal-ese2.conf
关于secure_element hardware没有什么好讲的,但是在XTS中会经常遇到,后文通过XTS来进行介绍吧。
二、MTK OMAPIXTS 分析指南
MTK有官方网站介绍:https://online.mediatek.com/apps/faq/detail?faqid=FAQ39642&list=SW。本节内容完全拷贝MTK的总结
摘要:本文档针对 OMAPI(Open Mobile API)相关的 xTS 测试失败问题提供排查思路和解决方案,涵盖 CtsOmapiTestCases、CtsSecureElementAccessControlTestCases 和 VtsHalSecureElement。问题通常由 OMAPI 配置、SecureElement HAL Service 状态异常或测试环境(测试白卡/eSIM Profile)不合规引起。
PS:本章完全摘抄MTK官方网站
1、常见问题
- 在 CTS 认证时遇到
CtsOmapiTestCases失败,报错OpenLogicalChannel() failed或AccessControlException,如何解决? - 如果项目不需要支持 NFC/OMAPI 功能,如何通过配置跳过 OMAPI 相关的 xTS 测试?
- 1 eSIM + 1 实体 SIM 架构下,eSIM 不需要支持 OMAPI,如何配置以满足 xTS 测试要求?
2、问题原因
OMAPI 相关 xTS 测试失败通常由以下原因引起:
原因1:测试使用的 SIM 卡不合规
该测试要求插入符合 Google CTS 要求的测试白卡。对于 eSIM 项目,需要 eSIM 提供方提供符合 Google CTS 要求的专用 Profile。否则 SecureElement 的访问控制(AccessControlEnforcer)无法在 SIM 卡或 eSIM 中找到对应的访问规则,导致测试失败。
Google 官网的相关说明:https://source.android.com/compatibility/cts/secure-element
典型日志示例1(Access Control 规则缺失):
SecureElement-PKCS15Handler: - Loading SIM2 rules...
TestRunner: java.lang.AssertionError: Unexpected Exception java.lang.SecurityException: Exception in setUpChannelAccess()
java.security.AccessControlException: SecureElement-AccessControlEnforcerno APDU access allowed!
典型日志示例2(OpenLogicalChannel 失败):
java.lang.AssertionError: Unexpected Exception java.io.IOException: OpenLogicalChannel() failed
典型日志示例3(APDU 传输失败):
MtkUiccSEHal: [se2]transmitInternalLocked:657: [121] > transmit [2] 02C27FFF00
MtkUiccSEHal: [se2]transmitInternalLocked:705: [121] < transmit [2] 0000 err=2
原因2:SecureElement APK 不存在
典型日志:
I/ModuleListener: [1/1] android.omapi.cts.OmapiTest#testOpenBasicChannelNullAid fail:
java.lang.AssertionError: Unexpected Exception java.util.concurrent.TimeoutException: Service could not be connected after 3000 ms
原因3:Feature声明,HAL 声明与 HAL Service 运行状态不匹配
系统声明了 android.hardware.se.omapi.uicc feature,device manifest 中声明了 ISecureElement,但 HAL Service (/vendor/bin/hw/android.hardware.secure_element@1.2-service-mediatek) 未运行。
典型日志:
ServiceManagerCppClient: Waited one second for android.hardware.secure_element.ISecureElement/SIM1 (is service started? Number of threads started in the threadpool: 16. Are binder threads started and available?)
3、排查方法
步骤0:确认 SIM 卡是否合规
如果看到上节所述 Access Control 规则缺失、OpenLogicalChannel 失败、APDU 传输失败的典型日志,检查是否使用的是 CTS 测试白卡或 CTS 专用 eSIM Profile。
注意:不同 eSIM 厂商的测试 profile 可能不通用,务必从对应的 eSIM 厂商获取 profile
步骤1:检查 SecureElement APK
adb shell ls /system/app/SecureElement
SecureElement APK 是 AOSP 原生就存在的 APK,如果不存在,检查是否客制化移除。
步骤2:检查 Feature 声明
adb shell cat /vendor/etc/permissions/android.hardware.se.omapi.prebuilt.xml
如果声明了 android.hardware.se.omapi.uicc, 结果为:
...
<permissions>
<feature name="android.hardware.se.omapi.uicc" />
</permissions>
步骤3:检查 manifest
adb shell "grep -A4 ISecureElement /vendor/etc/vintf/manifest.xml"
如果声明了 ISecureElement HAL,结果为(Android U 及之后):
<fqname>ISecureElement/SIM1</fqname>
<fqname>ISecureElement/SIM2</fqname>
...
或者 (Android T 及之前)
<name>ISecureElement</name>
<interface>SIM1</interface>
<interface>SIM2</interface>
...
步骤4:检查 HAL service
adb shell "ps -A | grep secure_element"
如下结果显示 HAL service 正常运行:
secure_element 1335 1 10940052 7492 binder_thread_read 0 S android.hardware.secure_element@1.2-service-mediatek
步骤5:检查配置一致性
MTK 在 /device/mediatek/vendor/common/device.mk 中通过 MTK_OMAPI_SUPPORT 宏保证了 feature、manifest、HAL service 的同开同关。
如果上述 feature/manifest/HAL service 存在状态不一致:
- 检查 device.mk 是否有客制化
- 检查是否在其他地方修改了 feature/manifest/HAL service 配置
/device/mediatek/vendor/common/device.mk
ifeq ($(strip $(MTK_OMAPI_SUPPORT)), yes)
ifeq ($(strip $(MTK_MULTI_SIM_SUPPORT)), ss)
DEVICE_MANIFEST_FILE += $(LOCAL_PATH)/project_manifest/manifest_secure_element_ss$(ESE_MANIFEST).xml
endif
ifeq ($(strip $(MTK_MULTI_SIM_SUPPORT)), dsds)
DEVICE_MANIFEST_FILE += $(LOCAL_PATH)/project_manifest/manifest_secure_element_dsds$(ESE_MANIFEST).xml
endif
...
...
PRODUCT_PACKAGES += android.hardware.se.omapi.prebuilt.xml
PRODUCT_PACKAGES += mailto:android.hardware.secure_element@1.2-service-mediatek
...
...
endif
4、解决方案
方案一:彻底关闭OMAPI支持
📌 适用场景:设备不需要UICC OMAPI能力(不支持NFC/OMAPI的项目)
操作步骤
-
关闭宏配置
MTK_OMAPI_SUPPORT = no -
确认Feature声明
确认
/vendor/etc/permissions/下没有 android.hardware.se.omapi.prebuilt.xml -
确认device Manifest
确认
/vendor/etc/vintf/manifest.xml中没有声明 ISecureElement -
确认服务状态
adb shell "ps -A | grep secure_element"确认没有相关服务在运行
方案二:单独对特定卡槽(如SIM2/eSIM)禁用OMAPI
📌 适用场景:1 eSIM + 1 实体SIM架构,且eSIM不需要支持OMAPI
操作步骤
-
修改Manifest文件
在以下文件中删除
<fqname>ISecureElement/SIM2</fqname>:/device/mediatek/vendor/common/project_manifest/manifest_secure_element_dsds.xml/device/mediatek/vendor/common/project_manifest/odm_manifest_secure_element_dsds.xml
-
修改HAL代码
文件路径:
/vendor/mediatek/proprietary/hardware/secure_element/MtkUiccSeService.cpp将
getNumberOfSim()函数的逻辑修改为固定返回1说明:此修改会使CTS只测试SIM1,从而避开对SIM2/eSIM的检测
方案三:必须支持OMAPI时的配置要求
📌 适用场景:业务要求必须支持OMAPI Feature
操作步骤
-
开启宏与服务
- 配置
MTK_OMAPI_SUPPORT = yes - 确认 HAL service
android.hardware.secure_element@1.2-service-mediatek正常运行
- 配置
-
使用合规测试卡
- 实体卡槽必须插入CTS测试白卡
-
eSIM Profile要求
- 联系eSIM供应商,下载符合Google CTS测试要求的专用Profile
**三、**SecureElement XTS案例分析
Google针对SecureElement模块的XTS测试项还是非常多,本章介绍一下我在实际项目中遇到的一系列相关XTS问题,大概测试项如下:

1、CtsSecureElementTestCases
2、