安卓4.4加密卡验证流程

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 笔记

CatService详解


相关类路径frameworks/opt/telephony/src/java/com/android/internal/telephony/cat/

下面有如下多个类

AppInterface.java
BerTlv.java
CallControlResult.java
CatCmdMessage.java
CatException.java
CatLanguageDecoder.java
CatLog.java
CatResponseMessage.java
CatService.java
ChannelData.java
CommandDetails.java
//1、解析SIM卡上报的STK数据;2、将解析后的数据发送给RilMessageDecoder
CommandParamsFactory.java
CommandParams.java
ComprehensionTlv.java
//COMPREHENSION-TLV对象的枚举类型
ComprehensionTlvTag.java
DtmfMessage.java
Duration.java
FontSize.java
IATUtils.java
IconLoader.java
IconLoaderProxy.java
ImageDescriptor.java
Input.java
Item.java
LanguageMessage.java
LaunchBrowserMode.java
Menu.java
OpenChannelData.java
package.html
PresentationType.java
ReceiveChannelData.java
ResponseData.java
ResultCode.java
ResultException.java
RilMessageDecoder.java
SendChannelData.java
StkServiceProxy.java
TextAlignment.java
TextAttribute.java
TextColor.java
TextMessage.java
Tone.java
ToneSettings.java
ValueParser.java

什么是TLV


TLV格式及其编码

TLV一种可变格式,TLV的意思就是:Type类型, Lenght长度,Value值。

在CAT相关源码中的体现

ComprehensionTlvTag.java

这是TLV中的T,即TAG

//枚举,用于表示COMPREHENSION-TLV对象的标记值。 如果要获取实际值,请调用value()方法
 public enum ComprehensionTlvTag {
     COMMAND_DETAILS(0x01), //命令详情
     DEVICE_IDENTITIES(0x02), //设备ID标识 
     RESULT(0x03),  //结果
     DURATION(0x04),  //时长
     ALPHA_ID(0x05), 
     ADDRESS(0x06), //地址
     USSD_STRING(0x0a),
     SMS_TPDU(0x0b),
     TEXT_STRING(0x0d),
     TONE(0x0e),
     ITEM(0x0f),
     ITEM_ID(0x10),
     RESPONSE_LENGTH(0x11),
     FILE_LIST(0x12),
     HELP_REQUEST(0x15),
     DEFAULT_TEXT(0x17),
     NEXT_ACTION_INDICATOR(0x18),
     EVENT_LIST(0x19),
     ICON_ID(0x1e),
     ITEM_ICON_ID_LIST(0x1f),
     DATE_TIME_TIMEZONE(0x26),
     IMMEDIATE_RESPONSE(0x2b),
   //Deal With DTMF Message Start
     DTMF(0x2c),
   //Deal With DTMF Message End
     LANGUAGE(0x2d),
     URL(0x31),
     BROWSER_TERMINATION_CAUSE(0x34),
     BEARER_DESCRIPTION(0x35),
     CHANNEL_DATA(0x36),
     CHANNEL_DATA_LENGTH(0x37),
     CHANNEL_STATUS(0x38),
     BUFFER_SIZE(0x39),
     TRANSPORT_LEVEL(0x3c),
     OTHER_ADDRESS(0x3e),
     NETWORK_ACCESS_NAME(0x47),
     TEXT_ATTRIBUTE(0x50);
     private int mValue;
     ComprehensionTlvTag(int value) {
         mValue = value;
     } 
     //返回此COMPREHENSION-TLV对象的实际值
     public int value() {
         return mValue;
     }
     //value转为枚举类型
     public static ComprehensionTlvTag fromInt(int value) {
         for (ComprehensionTlvTag e : ComprehensionTlvTag.values()) {
             if (e.mValue == value) {
                 return e;
             }
         }
         return null;
     }
 }

ComprehensionTlv.java

表示COMPREHENSION-TLV对象的类,里面包含了T,L,V

class ComprehensionTlv {
    private static final String LOG_TAG = "ComprehensionTlv";
    private int mTag;  //TLV中的T
    private boolean mCr;
    private int mLength;  //TLV中的L
    private int mValueIndex;
    private byte[] mRawValue;  //存储数据的字节数组,TLV中的V
/**
 * 私有构造函数,请使用decodeMany或decode方法来获取对象实例
 */
protected ComprehensionTlv(int tag, boolean cr, int length, byte[] data,
        int valueIndex) {
    mTag = tag;  
    mCr = cr;
    mLength = length;
    mValueIndex = valueIndex;
    mRawValue = data;
}
 /**
  * 解析字节数组中的COMPREHENSION-TLV对象列表.
  */
 public static List<ComprehensionTlv> decodeMany(byte[] data, int startIndex)
         throws ResultException {
     ArrayList<ComprehensionTlv> items = new ArrayList<ComprehensionTlv>();
     int endIndex = data.length;
     while (startIndex < endIndex) {
         ComprehensionTlv ctlv = ComprehensionTlv.decode(data, startIndex);
         if (ctlv != null) {
             items.add(ctlv);
             startIndex = ctlv.mValueIndex + ctlv.mLength;
         } else {
             CatLog.d(LOG_TAG, "decodeMany: ctlv is null, stop decoding");
             items.clear();
             break;
         }
     }
     return items;
 }
/**
 * 从字节数组解析COMPREHENSION-TLV对象。
 */
public static ComprehensionTlv decode(byte[] data, int startIndex)
        throws ResultException {
    int curIndex = startIndex;
    int endIndex = data.length;
    try {
        /* tag */
        int tag;
        boolean cr; // Comprehension required flag
        int temp = data[curIndex++] & 0xff;
        switch (temp) {
        case 0:
            tag = 0;
            cr = false;
            break;
        case 0xff:
        ...
        ...
    return new ComprehensionTlv(tag, cr, length, data, curIndex);
}

CommandParamsFactory.java

/**
 * 从tlv列表中找到指定TAG的TLV对象
 */
private ComprehensionTlv searchForTag(ComprehensionTlvTag tag,
        List<ComprehensionTlv> ctlvs) {
    Iterator<ComprehensionTlv> iter = ctlvs.iterator();
    return searchForNextTag(tag, iter);
}

/**
 *SIM卡中proactive commands 的详细对象类
 */
public class CommandDetails extends ValueObject implements Parcelable {
    public boolean compRequired;
    public int commandNumber;
    public int typeOfCommand;
    public int commandQualifier;
    @Override
    public ComprehensionTlvTag getTag() {
        return ComprehensionTlvTag.COMMAND_DETAILS;
    }
    ...
    ...
}

AppInterface

/**
 * STK APP与CAT Telephony通信的接口
 */
public interface AppInterface {
     /*
      *用于表示proactive commands的命令类型枚举。这些是Telephony支持的唯一命令
      */
     public static enum CommandType {
         DISPLAY_TEXT(0x21),
         GET_INKEY(0x22),
         GET_INPUT(0x23),
         LAUNCH_BROWSER(0x15),
         PLAY_TONE(0x20),
         REFRESH(0x01),
         SELECT_ITEM(0x24),
         SEND_SS(0x11),
         SEND_USSD(0x12),
         SEND_SMS(0x13),
         SEND_DTMF(0x14),
         SET_UP_EVENT_LIST(0x05),
         SET_UP_IDLE_MODE_TEXT(0x28),
         SET_UP_MENU(0x25),
         SET_UP_CALL(0x10),
         PROVIDE_LOCAL_INFORMATION(0x26),
         /* SPRD: add for USAT 27.22.4.25 LANGUAGE NOTIFICATION  @{ */
         LANGUAGE_NOTIFACTION(0x35),
         /* @}*/
         OPEN_CHANNEL(0x40),
         CLOSE_CHANNEL(0x41),
         RECEIVE_DATA(0x42),
         SEND_DATA(0x43),
         GET_CHANNEL_STATUS(0x44);
         private int mValue;
         CommandType(int value) {
             mValue = value;
         }
         public int value() {
             return mValue;
         }
         public static CommandType fromInt(int value) {
             for (CommandType e : CommandType.values()) {
                 if (e.mValue == value) {
                     return e;
                 }
             }
             return null;
         }
     }
}

RilMessageDecoder.java

用于解析RilMessage的类

//用于对原始 ril 消息进行排队的类,将它们解码为 CommanParams
对象并将结果发送回 CAT 服务。
class RilMessageDecoder extends StateMachine {
private class StateStart extends State {
    @Override
    public boolean processMessage(Message msg) {
        if (msg.what == CMD_START) {
            if (decodeMessageParams((RilMessage)msg.obj)) {
                transitionTo(mStateCmdParamsReady);
            }
        } else {
            CatLog.d(this, "StateStart unexpected expecting START=" +
                     CMD_START + " got " + msg.what);
        }
        return true;
    }
}
 /**
  在decodeMessageParams()中先通过hexStringToBytes()方法将得到的Modem数据
转换为byte类型的数组数据rawData,然后将此数据交给CommandParamsFactory类
的make()方法去解析,经过make的解析就可以得到每项STK菜单的图标、菜单文本以
及需要的控件等信息
*/
 private boolean decodeMessageParams(RilMessage rilMsg) {
     boolean decodingStarted;
     mCurrentRilMessage = rilMsg;
     switch(rilMsg.mId) {
   ...
     case CatService.MSG_ID_PROACTIVE_COMMAND:
     case CatService.MSG_ID_EVENT_NOTIFY:
     case CatService.MSG_ID_REFRESH:
         byte[] rawData = null;
         try {
              //转为字节数组
             rawData = IccUtils.hexStringToBytes((String) rilMsg.mData);
             CatLog.d(this, "[stk]rawData length"+rawData.length);
             if (rawData.length == 0) {
                 CatLog.d(this, "[stk]rawData is empty");
                 decodingStarted = false;
                 break;
             }
         } catch (Exception e) {
             // zombie messages are dropped
             CatLog.d(this, "[stk] decodemessage Exception e:" + e);
             decodingStarted = false;
             break;
         }
         try {
            //开始异步解析命令参数
             mCmdParamsFactory.make(BerTlv.decode(rawData));
             decodingStarted = true;
         } catch (ResultException e) {
             // send to Service for proper RIL communication.
             CatLog.d(this, "[stk]mCmdParamsFactory.make Exception = " + e);
             mCurrentRilMessage.mId = CatService.MSG_ID_SESSION_END;
             mCurrentRilMessage.mResCode = e.result();
             sendCmdForExecution(mCurrentRilMessage);
             decodingStarted = false;
         }
         break;
     default:
         decodingStarted = false;
         break;
     }
     return decodingStarted;
 }

packages\apps\stk\src\com\android\stk\StkCmdReceiver.java

Uicc之CatService

广播接收类,主要接收来自framework层的CatService发送的针对RIL层上报上来的处理结果的响应信息

1、目前Stk 只使用packages/apps/Stk/src/com/android/stk/下面的代码处理Stk 相关的逻辑

不需要关注Stk1,Stk2;

2、modem 上报Get input command,通过RIL_UNSOL_STK_PROACTIVE_COMMAND上报给上层


目录
相关文章
|
24天前
|
Android开发
我的Android进阶修炼:安卓启动流程之init(1)
本文深入分析了Android系统中的init进程,包括其源码结构、主要功能以及启动流程的详细注解,旨在帮助读者理解init作为用户空间的1号进程在Android启动过程中的关键作用。
25 1
|
1月前
|
存储 算法 Java
在Java中使用MD5对用户输入密码进行加密存储、同时登录验证。
这篇文章详细介绍了在Java项目中如何使用MD5算法对用户密码进行加密存储和登录验证,包括加入依赖、编写MD5工具类、注册时的密码加密和登录时的密码验证等步骤,并通过示例代码和数据库存储信息展示了测试效果。
在Java中使用MD5对用户输入密码进行加密存储、同时登录验证。
|
1月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
View的绘制和事件处理是两个重要的主题,上一篇《图解 Android事件分发机制》已经把事件的分发机制讲得比较详细了,这一篇是针对View的绘制,View的绘制如果你有所了解,基本分为measure、layout、draw 过程,其中比较难理解就是measure过程,所以本篇文章大幅笔地分析measure过程,相对讲得比较详细,文章也比较长,如果你对View的绘制还不是很懂,对measure过程掌握得不是很深刻,那么耐心点,看完这篇文章,相信你会有所收获的。
69 2
|
27天前
|
JSON 算法 API
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token
|
2月前
|
Java Android开发
android 设置系统时间的流程
android 设置系统时间的方法
227 2
|
3月前
|
ARouter IDE 开发工具
Android面试题之App的启动流程和启动速度优化
App启动流程概括: 当用户点击App图标,Launcher通过Binder IPC请求system_server启动Activity。system_server指示Zygote fork新进程,接着App进程向system_server申请启动Activity。经过Binder通信,Activity创建并回调生命周期方法。启动状态分为冷启动、温启动和热启动,其中冷启动耗时最长。优化技巧包括异步初始化、避免主线程I/O、类加载优化和简化布局。
58 3
Android面试题之App的启动流程和启动速度优化
|
3月前
|
安全 网络协议 算法
Android网络基础面试题之HTTPS的工作流程和原理
HTTPS简述 HTTPS基于TCP 443端口,通过CA证书确保服务器身份,使用DH算法协商对称密钥进行加密通信。流程包括TCP握手、证书验证(公钥解密,哈希对比)和数据加密传输(随机数加密,预主密钥,对称加密)。特点是安全但慢,易受特定攻击,且依赖可信的CA。每次请求可能复用Session ID以减少握手。
48 2
|
2月前
|
消息中间件 前端开发 Android开发
Android面试题自定义View之Window、ViewRootImpl和View的三大流程
Android开发中,View的三大核心流程包括measure(测量)、layout(布局)和draw(绘制)。MeasureSpec类在测量过程中起到关键作用,它结合尺寸大小和模式(EXACTLY、AT_MOST、UNSPECIFIED)来指定View应如何测量。onMeasure方法用于自定义View的测量,布局阶段,ViewGroup调用onLayout确定子元素位置,而draw阶段按照特定顺序绘制背景、内容、子元素和装饰。整个流程始于ViewRootImpl的performTraversals,该方法触发测量、布局和绘制。
36 0
|
3月前
|
Android开发
Android面试题之activity启动流程
该文探讨了Android应用启动和Activity管理服务(AMS)的工作原理。从Launcher启动应用开始,涉及Binder机制、AMS回调、进程创建、Application和Activity的生命周期。文中详细阐述了AMS处理流程,包括创建ClassLoader、加载APK、启动Activity的步骤,以及权限校验和启动模式判断。此外,还补充了activity启动流程中AMS的部分细节。欲了解更多内容,可关注公众号“AntDream”。
36 1
|
3月前
|
Java Linux Android开发
Android面试题之说说系统的启动流程(总结)
这篇文章概述了Android系统的启动流程,从Boot Rom到Zygote进程和SystemServer的启动。init进程作为用户级别的第一个进程,负责创建文件目录、初始化服务并启动Zygote。Zygote通过预加载资源和创建Socket服务,使用fork函数生成SystemServer进程。fork过程中,子进程继承父进程大部分信息但具有独立的进程ID。Zygote预加载资源以减少后续进程的启动时间,而SystemServer启动众多服务并最终开启Launcher应用。文中还讨论了为何从Zygote而非init或SystemServer fork新进程的原因。
66 2