深度解析 | Android 12系统级禁用SIM卡功能实现与Framework层定制

发布于:2025-03-25 ⋅ 阅读:(30) ⋅ 点赞:(0)
一、需求背景与实现原理

在Android系统定制开发中,彻底禁用SIM卡功能是某些行业设备(如安全终端、Kiosk模式设备)的常见需求。不同于常规的SIM卡状态管理,该功能需要实现:

  1. 硬件级禁用 - 即使插入SIM卡也无法识别

  2. 系统级管控 - 防止用户通过设置界面重新启用

  3. 持久化生效 - 设备重启后策略依然有效

本文基于Android 12源码,深入分析Framework层实现方案,提供两种核心实现路径:


二、实现方案一:关机流程劫持(ShutdownThread)
1. 核心原理分析

关机流程中的SIM卡关闭逻辑位于ShutdownThread,其调用链为:

复制

PowerManager.shutdown() 
→ ShutdownThread.shutdown() 
→ shutdownRadios() 
→ ITelephony.shutdownMobileRadios()

关键代码段:

java

复制

// frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
private void shutdownRadios(final int timeout) {
    final ITelephony phone = ITelephony.Stub.asInterface(
        ServiceManager.checkService("phone"));
    // 核心禁用逻辑
    phone.shutdownMobileRadios(); 
}
2. 改造实现

java

复制

public void disableSimPermanently(Context context) {
    final long identity = Binder.clearCallingIdentity();
    try {
        ITelephony telephony = ITelephony.Stub.asInterface(
            ServiceManager.getService(Context.TELEPHONY_SERVICE));
        if (telephony != null) {
            // 强制关闭所有基带模块
            telephony.shutdownMobileRadios();
            // 持久化状态防止重启恢复
            Settings.Global.putInt(context.getContentResolver(),
                "airplane_mode_on", 1); 
        }
    } catch (RemoteException e) {
        Log.e(TAG, "Telephony service unavailable", e);
    } finally {
        Binder.restoreCallingIdentity(identity);
    }
}
3. 方案特点
  • 即时生效:执行后立即禁用

  • 依赖关机流程:需触发关机/重启操作

  • 兼容性风险:不同厂商可能定制Telephony服务


三、实现方案二:系统服务初始化拦截(PhoneWindowManager)
1. 核心原理分析

系统服务初始化阶段调用PhoneWindowManager.systemReady(),通过Phone对象直接操作基带:

java

复制

// frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
private void shutdownRadioUsingPhoneId(int phoneId) {
    Phone phone = PhoneFactory.getPhone(phoneId);
    if (phone != null) {
        phone.shutdownRadio(); // 底层调用RIL请求
    }
}
2. 改造实现

java

复制

@Override
public void systemReady() {
    // 系统服务初始化完成时执行
    TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
    for (int i = 0; i < tm.getPhoneCount(); i++) {
        Phone phone = PhoneFactory.getPhone(i);
        if (phone != null && phone.isRadioAvailable()) {
            phone.shutdownRadio();
            // 持久化禁用状态
            phone.setRadioPower(false); 
        }
    }
    // 禁用SIM卡相关服务
    disableSimServices(true);
}

private void disableSimServices(boolean disable) {
    PackageManager pm = mContext.getPackageManager();
    ComponentName comp = new ComponentName("com.android.phone", 
        "com.android.phone.TelephonyDebugService");
    pm.setComponentEnabledSetting(comp,
        disable ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                : PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
        PackageManager.DONT_KILL_APP);
}
3. 方案特点
  • 启动阶段生效:系统初始化即禁用

  • 深度系统集成:修改Framework核心服务

  • 需处理多SIM卡:遍历PhoneCount


四、技术要点对比
维度 关机流程方案 系统初始化方案
生效时机 关机/重启后生效 系统启动时立即生效
修改风险 较低(流程劫持) 较高(核心服务修改)
多SIM卡支持 自动处理 需遍历Phone对象
OEM兼容性 依赖AOSP实现 需适配厂商RIL层
持久化存储 需额外处理 可集成到系统配置

五、实现效果验证
  1. 射频状态检查

shell

复制

adb shell dumpsys telephony.registry | grep "mRadioState"
# 预期输出:mRadioState=0 (RADIO_UNAVAILABLE)
  1. 基带日志监控

shell

复制

adb logcat -b radio | grep "RILJ"
# 预期出现:SET_RADIO_POWER: off
  1. API层验证

java

复制

TelephonyManager tm = getSystemService(TelephonyManager.class);
tm.getSimState(); // 应返回SIM_STATE_ABSENT
tm.isDataEnabled(); // 应返回false

六、注意事项
  1. 权限声明:需声明系统签名权限

xml

复制

<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
<uses-permission android:name="android.permission.CONTROL_DEVICE_POWER"/>

运行 HTML

  1. 厂商适配:部分设备需修改RIL层

c

复制

// hardware/ril/reference-ril/ril.cpp
static void onRequestShutdown(int request) {
    RIL_onRequestComplete(request, RIL_E_SUCCESS, NULL, 0);
}
  1. 状态持久化:建议结合DevicePolicyManager实现企业级管控


通过深度定制Android Framework层,开发者可以实现硬件级的SIM卡禁用功能。本文提供的两种方案可根据具体需求选择实现,建议在系统级定制项目中优先采用PhoneWindowManager方案,以确保持久生效与深度管控。

转载请注明出处深度解析 | Android 12系统级禁用SIM卡功能实现与Framework层定制-CSDN博客,谢谢!