Android 7.0 UICC 分析(二)

本文讲解UiccCard类

/frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/UiccCard.java

UICCController 类的onGetIccCardStatusDone() 方法,根据获取的SIM状态信息IccCardStatus 创建或更新UiccCard 对象;

    private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) {
        .......
        IccCardStatus status = (IccCardStatus)ar.result;

        if (mUiccCards[index] == null) {
            //Create new card
            mUiccCards[index] = new UiccCard(mContext, mCis[index], status, index);
        } else {
            //Update already existing card
            mUiccCards[index].update(mContext, mCis[index] , status);
        }
        .......
    }

UiccCard 类的构造方法,同样会调用update() 方法更新SIM 卡状态信息;

    public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId) {
        mCardState = ics.mCardState;
        mPhoneId = phoneId;
        update(c, ci, ics);
    }

UiccCard 类的 update() 方法:

1、根据IccCardStatus 参数在mUiccApplication 列表中匹配UiccCardApplication 对象,通过UiccCardApplication 类的update() 方法更新,否则创建一个UiccCardApplication 对象;

2、调用createAndUpdateCatService() 方法创建或更新CatService 对象;

3、获取RadioState状态,更新CardState,发出SIM卡插拔消息;

    public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
             ........
            //update applications
            if (DBG) log(ics.mApplications.length + " applications");
            for ( int i = 0; i < mUiccApplications.length; i++) {
                if (mUiccApplications[i] == null) {
                    //Create newly added Applications
                    if (i < ics.mApplications.length) {
                        mUiccApplications[i] = new UiccCardApplication(this,
                                ics.mApplications[i], mContext, mCi);
                    }
                } else if (i >= ics.mApplications.length) {
                    //Delete removed applications
                    mUiccApplications[i].dispose();
                    mUiccApplications[i] = null;
                } else {
                    //Update the rest
                    mUiccApplications[i].update(ics.mApplications[i], mContext, mCi); //调用UiccCardApplication.java
                }
            }

            createAndUpdateCatService(); //CatService
            ..........
            RadioState radioState = mCi.getRadioState();
            if (DBG) log("update: radioState=" + radioState + " mLastRadioState="
                    + mLastRadioState);
            // No notifications while radio is off or we just powering up
            if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
                if (oldState != CardState.CARDSTATE_ABSENT &&
                        mCardState == CardState.CARDSTATE_ABSENT) {
                    if (DBG) log("update: notify card removed");
                    mAbsentRegistrants.notifyRegistrants();
                    mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
                } else if (oldState == CardState.CARDSTATE_ABSENT &&
                        mCardState != CardState.CARDSTATE_ABSENT) {
                    if (DBG) log("update: notify card added");
                    mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
                }
            }
            mLastRadioState = radioState;
        }
    }

createAndUpdateCatService() 方法,创建或更新CatService:

    protected void createAndUpdateCatService() {
        if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
            // Initialize or Reinitialize CatService
            if (mCatService == null) {
                mCatService = CatService.getInstance(mCi, mContext, this, mPhoneId);
            } else {
                ((CatService)mCatService).update(mCi, mContext, this);
            }
        } else {
            if (mCatService != null) {
                mCatService.dispose();
            }
            mCatService = null;
        }
    }

消息EVENT_CARD_REMOVED、 EVENT_CARD_ADDED 在UiccCard 类的handleMessage()方法中处理:

    protected Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg){
            switch (msg.what) {
                case EVENT_CARD_REMOVED:
                    onIccSwap(false);
                    break;
                case EVENT_CARD_ADDED:
                    onIccSwap(true);
                    break;
                .........
            }
        }
    };

onIccSwap() 方法,判断是否共卡座,如果是直接返回,否则调用promptForRestart():

    private void onIccSwap(boolean isAdded) {

        boolean isHotSwapSupported = mContext.getResources().getBoolean(
                R.bool.config_hotswapCapable);

        if (isHotSwapSupported) { //给国内双卡共卡座设计留下接口
            log("onIccSwap: isHotSwapSupported is true, don‘t prompt for rebooting");
            return;
        }
        log("onIccSwap: isHotSwapSupported is false, prompt for rebooting");

        promptForRestart(isAdded);
    }

promptForRestart() 方法,切换sim卡,弹出提示框:

    private void promptForRestart(boolean isAdded) {
        synchronized (mLock) {
            final Resources res = mContext.getResources();
            final String dialogComponent = res.getString(
                    R.string.config_iccHotswapPromptForRestartDialogComponent);
            if (dialogComponent != null) {
                Intent intent = new Intent().setComponent(ComponentName.unflattenFromString(
                        dialogComponent)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                        .putExtra(EXTRA_ICC_CARD_ADDED, isAdded);
                try {
                    mContext.startActivity(intent);
                    return;
                } catch (ActivityNotFoundException e) {
                    loge("Unable to find ICC hotswap prompt for restart activity: " + e);
                }
            }

            // TODO: Here we assume the device can‘t handle SIM hot-swap
            //      and has to reboot. We may want to add a property,
            //      e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support
            //      hot-swap.
            DialogInterface.OnClickListener listener = null;

            // TODO: SimRecords is not reset while SIM ABSENT (only reset while
            //       Radio_off_or_not_available). Have to reset in both both
            //       added or removed situation.
            listener = new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    synchronized (mLock) {
                        if (which == DialogInterface.BUTTON_POSITIVE) {
                            if (DBG) log("Reboot due to SIM swap");
                            PowerManager pm = (PowerManager) mContext
                                    .getSystemService(Context.POWER_SERVICE);
                            pm.reboot("SIM is added.");
                        }
                    }
                }

            };

            Resources r = Resources.getSystem();

            String title = (isAdded) ? r.getString(R.string.sim_added_title) :
                r.getString(R.string.sim_removed_title);
            String message = (isAdded) ? r.getString(R.string.sim_added_message) :
                r.getString(R.string.sim_removed_message);
            String buttonTxt = r.getString(R.string.sim_restart_button);

            AlertDialog dialog = new AlertDialog.Builder(mContext)
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(buttonTxt, listener)
            .create();
            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            dialog.show();
        }
    }
时间: 2024-07-28 22:20:25

Android 7.0 UICC 分析(二)的相关文章

kaifyou Android 7.0 UICC 分析(四)

本文讲解SIMRecords /frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/SIMRecords.java 构造方法: public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) { super(app, c, ci); mAdnCache = new AdnRecordCache(mFh); mVmConfi

[Android]Volley源码分析(二)Cache

Cache作为Volley最为核心的一部分,Volley花了重彩来实现它.本章我们顺着Volley的源码思路往下,来看下Volley对Cache的处理逻辑. 我们回想一下昨天的简单代码,我们的入口是从构造一个Request队列开始的,而我们并不直接调用new来构造,而是将控制权反转给Volley这个静态工厂来构造. com.android.volley.toolbox.Volley: public static RequestQueue newRequestQueue(Context conte

[Android]Fragment源码分析(二) 状态

我们上一讲,抛出来一个问题,就是当Activity的onCreateView的时候,是如何构造Fragment中的View参数.要回答这个问题我们先要了解Fragment的状态,这是Fragment管理中非常重要的一环.我们先来看一下FragmentActivity提供的一些核心回调: @Override protected void onCreate(Bundle savedInstanceState) { mFragments.attachActivity(this, mContainer,

android 休眠唤醒机制分析(二) — early_suspend

本文转自:http://blog.csdn.net/g_salamander/article/details/7982170 early_suspend是Android休眠流程的第一阶段即浅度休眠,不会受到wake_lock的阻止,一般用于关闭lcd.tp等设备为运行的应用节约电能.Android的PowerManagerService会根据用户的操作情况调整电源状态,如果需要休眠则会调用到HAL层的set_screen_state()接口,在set_screen_state()中会向/sys/

Android 6.0 IMS流程(二)——接口扩展(从RIL到APP)

平时工作中,经常有这样的需求,就是从RIL层一直到APP,添加一个新接口给APP调用,方便系统APP或者第三方APP通过这个接口获取或者改变modem中某些的值.状态等. 基于高通平台,有三种方式去实现这种接口: 扩展ImsSenderRxr,依赖ImsService来实现. 扩展RILJ,依赖Phone进程来实现. 结合1和2,依赖Phone进程来实现. 其中,第一种方式最简单,第二种次之,第三种最复杂:但是每种方式各自有各自的限制条件以及适用范围. 本文来自http://blog.csdn.

Android 6.0 应用权限(二) -- 与系统权限一起工作(Working with System Permissions) 使用MarkDown重新整理了排版

为了保护系统集成度和用户的隐私,Android在一个受限访问的沙箱中运行每个程序.如果这个应用想要使用它的沙箱外的其他资源或信息,就必须显性地请求权限.依赖于应用请求的权限类型,系统可能会自动地授权或者通过询问用户来授权 本节向你展示如何为你的应用声明和授予权限. Declare Permissions(声明权限) 每个Android应用都运行在一个受限访问的沙箱中..如果这个应用想要使用它的沙箱外的其他资源或信息,就需要请求正确的权限.你可以通过在App Manifest中列出这些权限来声明你

Android 5.0 Uicc框架分析

Uicc框架 UICC框架是Android在4.1引入的,使的对卡的管理控制更加清晰.要了解这个UICC框架,需要从UiccController开始,它是整个UICC框架的开始与控制者,该类被设计为单例,是消息处理类Handler的子类,所以其实现肯定是基于event触发的,其在Phone创建的早期被初始化: 1 2 3 // Instantiate UiccController so that all other classes can just // call getInstance() m

Android 5.0 怎样正确启用isLoggable(二)__原理分析

前置文章 <Android 5.0 怎样正确启用isLoggable(一)__使用具体解释> 概要 在上文<Android 5.0 怎样正确启用isLoggable(一)__使用具体解释>中分析了isLoggable的用法,本文主要分析isLoggable实现原理以及user版系统root后永久enable isLoggable的原理,并使用脚本自己主动设置isLoggable相关属性. 本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处

Android 5.0 如何正确启用isLoggable(二)__原理分析

前置文章 <Android 5.0 如何正确启用isLoggable(一)__使用详解> 概要 在上文<Android 5.0 如何正确启用isLoggable(一)__使用详解>中分析了isLoggable的使用方法,本文主要分析isLoggable实现原理以及user版系统root后永久enable isLoggable的原理,并使用脚本自动设置isLoggable相关属性. 本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处 isL