Android 5.0 Lollipop 短彩信接收流程

短彩信接收流程和来电流程有点类似,最开始也是RIL层上报短信事件,然后上层来处理接收短信的流程。android的ril位于应用程序框架与内核之间,分成了两个部分,一个部分是rild,它负责socket与应用程序框架进行通信。另外一个部分是Vendor RIL,这个部分负责向下是通过两种方式与radio进行通信,它们是直接与radio通信的AT指令通道和用于传输包数据的通道,数据通道用于手机的上网功能,其中RIL.java主要用于hardware层和framework通信。在RIL.java中通过socket通信,接收来自hardware层上报的事件,在RIL.java的内部类RILReceiver中通过LocalSocket通信,获取上报事件,在processResponse处理接收或发送短信

class RILReceiver implements Runnable {
        byte[] buffer;

        RILReceiver() {
            buffer = new byte[RIL_MAX_COMMAND_BYTES];
        }

        @Override
        public void
        run() {
            int retryCount = 0;
            String rilSocket = "rild";

            try {for (;;) {
                LocalSocket s = null;
                LocalSocketAddress l;
                ...
                try {
                    s = new LocalSocket();
                    l = new LocalSocketAddress(rilSocket,
                            LocalSocketAddress.Namespace.RESERVED);
                    s.connect(l);
                } catch (IOException ex){
                    ...
                }

                int length = 0;
                try {
                    InputStream is = mSocket.getInputStream();

                    for (;;) {
                        Parcel p;

                        length = readRilMessage(is, buffer);

                        if (length < 0) {
                            // End-of-stream reached
                            break;
                        }

                        p = Parcel.obtain();
                        p.unmarshall(buffer, 0, length);
                        p.setDataPosition(0);

                        //Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes");

                       processResponse(p);
                        p.recycle();
                    }
                } catch (java.io.IOException ex) {
                    Rlog.i(RILJ_LOG_TAG, "'" + rilSocket + "' socket closed",
                          ex);
                }
                ...
        }
    }

在processResponse中会根据type的类型来判断是接受短彩信还是发送短彩信,processUnsolicited处理接受流程,processSolicited处理发送流程

    processResponse (Parcel p) {
        int type;

        type = p.readInt();

        if (type == RESPONSE_UNSOLICITED) {
            processUnsolicited (p);
        } else if (type == RESPONSE_SOLICITED) {
            RILRequest rr = processSolicited (p);
            if (rr != null) {
                rr.release();
                decrementWakeLock();
            }
        }
    }

processUnsolicited会处理上报的RIL_UNSOL_RESPONSE_NEW_SMS事件,在GsmInboundSmsHandler.java中,注册了RIL_UNSOL_RESPONSE_NEW_SMS事件的监听,当调用mGsmSmsRegistrant.notifyRegistrant时,系统会通知GsmInboundSmsHandler处理EVENT_NEW_SMS事件

    processUnsolicited (Parcel p) {
        int response;
        Object ret;

        response = p.readInt();

        try {switch(response) {
           ...
            case RIL_UNSOL_RESPONSE_NEW_SMS: ret =  responseString(p); break;
           ...
        }} catch (Throwable tr) {
            Rlog.e(RILJ_LOG_TAG, "Exception processing unsol response: " + response +
                "Exception:" + tr.toString());
            return;
        }

        switch(response) {
            ...
            case RIL_UNSOL_RESPONSE_NEW_SMS: {
                if (RILJ_LOGD) unsljLog(response);

                // FIXME this should move up a layer
                String a[] = new String[2];

                a[1] = (String)ret;

                SmsMessage sms;

                sms = SmsMessage.newFromCMT(a);
                if (mGsmSmsRegistrant != null) {
                    mGsmSmsRegistrant
                        .notifyRegistrant(new AsyncResult(null, sms, null));
                }
            break;
            }
            ...
        }
    }

GsmInboundSmsHandler在构造方法中注册了EVENT_NEW_SMS事件的监听,在其父类InboundSmsHandler.java中处理EVENT_NEW_SMS事件

        @Override
        public boolean processMessage(Message msg) {
            log("DeliveringState.processMessage:" + msg.what);
            switch (msg.what) {
                case EVENT_NEW_SMS
                    // handle new SMS from RIL
                    handleNewSms((AsyncResult) msg.obj);
                    sendMessage(EVENT_RETURN_TO_IDLE);
                    return HANDLED;

                case EVENT_INJECT_SMS:
                    // handle new injected SMS
                    handleInjectSms((AsyncResult) msg.obj);
                    sendMessage(EVENT_RETURN_TO_IDLE);
                    return HANDLED;

                case EVENT_BROADCAST_SMS:
                    // if any broadcasts were sent, transition to waiting state
                    if (processMessagePart((InboundSmsTracker) msg.obj)) {
                        transitionTo(mWaitingState);
                    }
                    return HANDLED;

                case EVENT_RETURN_TO_IDLE:
                    // return to idle after processing all other messages
                    transitionTo(mIdleState);
                    return HANDLED;

                case EVENT_RELEASE_WAKELOCK:
                    mWakeLock.release();    // decrement wakelock from previous entry to Idle
                    if (!mWakeLock.isHeld()) {
                        // wakelock should still be held until 3 seconds after we enter Idle
                        loge("mWakeLock released while delivering/broadcasting!");
                    }
                    return HANDLED;

                // we shouldn't get this message type in this state, log error and halt.
                case EVENT_BROADCAST_COMPLETE:
                case EVENT_START_ACCEPTING_SMS:
                default:
                    // let DefaultState handle these unexpected message types
                    return NOT_HANDLED;
            }
        }
    }

当接收到RIL层的EVENT_NEW_SMS事件,会调用handleNewSms,在handleNewSms中会调用dispatchMessage


 void handleNewSms(AsyncResult ar) {
        if (ar.exception != null) {
            loge("Exception processing incoming SMS: " + ar.exception);
            return;
        }

        int result;
        try {
            SmsMessage sms = (SmsMessage) ar.result;
            result = dispatchMessage(sms.mWrappedSmsMessage);
        } catch (RuntimeException ex) {
            loge("Exception dispatching message", ex);
            result = Intents.RESULT_SMS_GENERIC_ERROR;
        }

        // RESULT_OK means that the SMS will be acknowledged by special handling,
        // e.g. for SMS-PP data download. Any other result, we should ack here.
        if (result != Activity.RESULT_OK) {
            boolean handled = (result == Intents.RESULT_SMS_HANDLED);
            notifyAndAcknowledgeLastIncomingSms(handled, result, null);
        }
    }

在dispatchMessage调用子类的 dispatchMessageRadioSpecific


frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
   @Override
    protected int dispatchMessageRadioSpecific(SmsMessageBase smsb) {
        SmsMessage sms = (SmsMessage) smsb;

        if (sms.isTypeZero()) {
            // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be
            // Displayed/Stored/Notified. They should only be acknowledged.
            log("Received short message type 0, Don't display or store it. Send Ack");
            return Intents.RESULT_SMS_HANDLED;
        }

        // Send SMS-PP data download messages to UICC. See 3GPP TS 31.111 section 7.1.1.
        if (sms.isUsimDataDownload()) {
            UsimServiceTable ust = mPhone.getUsimServiceTable();
            return mDataDownloadHandler.handleUsimDataDownload(ust, sms);
        }

        boolean handled = false;
        if (sms.isMWISetMessage()) {
            updateMessageWaitingIndicator(sms.getNumOfVoicemails());
            handled = sms.isMwiDontStore();
            if (DBG) log("Received voice mail indicator set SMS shouldStore=" + !handled);
        } else if (sms.isMWIClearMessage()) {
            updateMessageWaitingIndicator(0);
            handled = sms.isMwiDontStore();
            if (DBG) log("Received voice mail indicator clear SMS shouldStore=" + !handled);
        }
        if (handled) {
            return Intents.RESULT_SMS_HANDLED;
        }

        if (!mStorageMonitor.isStorageAvailable() &&
                sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) {
            // It's a storable message and there's no storage available.  Bail.
            // (See TS 23.038 for a description of class 0 messages.)
            return Intents.RESULT_SMS_OUT_OF_MEMORY;
        }

        return dispatchNormalMessage(smsb);
    }

然后在GsmInboundSmsHandler.java调用父类的dispatchNormalMessage

    protected int dispatchNormalMessage(SmsMessageBase sms) {
        SmsHeader smsHeader = sms.getUserDataHeader();
        InboundSmsTracker tracker;

        if ((smsHeader == null) || (smsHeader.concatRef == null)) {
            // Message is not concatenated.
            int destPort = -1;
            if (smsHeader != null && smsHeader.portAddrs != null) {
                // The message was sent to a port.
                destPort = smsHeader.portAddrs.destPort;
                if (DBG) log("destination port: " + destPort);
            }

            tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
                    is3gpp2(), false);
        } else {
            // Create a tracker for this message segment.
            SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
            SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs;
            int destPort = (portAddrs != null ? portAddrs.destPort : -1);

            tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
                    is3gpp2(), sms.getOriginatingAddress(), concatRef.refNumber,
                    concatRef.seqNumber, concatRef.msgCount, false);
        }

        if (VDBG) log("created tracker: " + tracker);
        return addTrackerToRawTableAndSendMessage(tracker);
    }

在addTrackerToRawTableAndSendMessage中发送EVENT_BROADCAST_SMS,processMessag会响应到这个事件调用processMessagePart分开处理短信或彩信

 boolean processMessagePart(InboundSmsTracker tracker) {
        int messageCount = tracker.getMessageCount();
        byte[][] pdus;
        int destPort = tracker.getDestPort();
        ...
        SmsBroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker);

        if (destPort == SmsHeader.PORT_WAP_PUSH) {
            // Build up the data stream
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            for (byte[] pdu : pdus) {
                // 3GPP needs to extract the User Data from the PDU; 3GPP2 has already done this
                if (!tracker.is3gpp2()) {
                    SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
                    pdu = msg.getUserData();
                }
                output.write(pdu, 0, pdu.length);
            }
            int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver, this);
            if (DBG) log("dispatchWapPdu() returned " + result);
            // result is Activity.RESULT_OK if an ordered broadcast was sent
            return (result == Activity.RESULT_OK);
        }

        List<String> carrierPackages = null;
        UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
        if (card != null) {
            carrierPackages = card.getCarrierPackageNamesForIntent(
                    mContext.getPackageManager(),
                    new Intent(CarrierMessagingService.SERVICE_INTERFACE));
        } else {
            loge("UiccCard not initialized.");
        }

        List<String> systemPackages =
                getSystemAppForIntent(new Intent(CarrierMessagingService.SERVICE_INTERFACE));

        if (carrierPackages != null && carrierPackages.size() == 1) {
            log("Found carrier package.");
            CarrierSmsFilter smsFilter = new CarrierSmsFilter(pdus, destPort,
                    tracker.getFormat(), resultReceiver);
            CarrierSmsFilterCallback smsFilterCallback = new CarrierSmsFilterCallback(smsFilter);
            smsFilter.filterSms(carrierPackages.get(0), smsFilterCallback);
        } else if (systemPackages != null && systemPackages.size() == 1) {
            log("Found system package.");
            CarrierSmsFilter smsFilter = new CarrierSmsFilter(pdus, destPort,
                    tracker.getFormat(), resultReceiver);
            CarrierSmsFilterCallback smsFilterCallback = new CarrierSmsFilterCallback(smsFilter);
            smsFilter.filterSms(systemPackages.get(0), smsFilterCallback);
        } else {
            logv("Unable to find carrier package: " + carrierPackages
                    + ", nor systemPackages: " + systemPackages);
            dispatchSmsDeliveryIntent(pdus, tracker.getFormat(), destPort, resultReceiver);
        }

        return true;
    }

在上面这个方法中调用WapPushOverSms.java的dispatchWapPdu处理彩信,继续调用InboundSmsHandler.java中的dispatchSmsDeliveryIntent处理短信

  frameworks/opt/telephony/src/java/com/android/internal/telephony/WapPushOverSms.java
  public int dispatchWapPdu(byte[] pdu, BroadcastReceiver receiver, InboundSmsHandler handler) {

        if (DBG) Rlog.d(TAG, "Rx: " + IccUtils.bytesToHexString(pdu));
            ...
            // Direct the intent to only the default MMS app. If we can't find a default MMS app
            // then sent it to all broadcast receivers.
            ComponentName componentName = SmsApplication.getDefaultMmsApplication(mContext, true);
            if (componentName != null) {
                // Deliver MMS message only to this receiver
                intent.setComponent(componentName);
                if (DBG) Rlog.v(TAG, "Delivering MMS to: " + componentName.getPackageName() +
                        " " + componentName.getClassName());
            }

            handler.dispatchIntent(intent, permission, appOp, receiver, UserHandle.OWNER);
            return Activity.RESULT_OK;
        } catch (ArrayIndexOutOfBoundsException aie) {
            // 0-byte WAP PDU or other unexpected WAP PDU contents can easily throw this;
            // log exception string without stack trace and return false.
            Rlog.e(TAG, "ignoring dispatchWapPdu() array index exception: " + aie);
            return Intents.RESULT_SMS_GENERIC_ERROR;
        }
    }

WapPushOverSms的dispatchWapPdu会获取默认的MMS app,把彩信交给应用层里的PushReceiver.java处理解析pdu和下载彩信的逻辑。如果是短信,会在dispatchSmsDeliveryIntent中处理,同样也是先获取默认的MMs app,然后通过intent传递到上层短信应用里的PrivilegedSmsReceiver.java处理短信的显示和插入数据库等操作

frameworks/opt/telephony/src/java/com/android/internal/telephony/InboundSmsHandler.java
   void dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort,
            BroadcastReceiver resultReceiver) {
        Intent intent = new Intent();
        intent.putExtra("pdus", pdus);
        intent.putExtra("format", format);

        if (destPort == -1) {
            intent.setAction(Intents.SMS_DELIVER_ACTION);
            // Direct the intent to only the default SMS app. If we can't find a default SMS app
            // then sent it to all broadcast receivers.
            // We are deliberately delivering to the primary user's default SMS App.
            ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true);
            if (componentName != null) {
                // Deliver SMS message only to this receiver.
                intent.setComponent(componentName);
                log("Delivering SMS to: " + componentName.getPackageName() +
                    " " + componentName.getClassName());
            } else {
                intent.setComponent(null);
            }

            // TODO: Validate that this is the right place to store the SMS.
            if (SmsManager.getDefault().getAutoPersisting()) {
                final Uri uri = writeInboxMessage(intent);
                if (uri != null) {
                    // Pass this to SMS apps so that they know where it is stored
                    intent.putExtra("uri", uri.toString());
                }
            }
        } else {
            intent.setAction(Intents.DATA_SMS_RECEIVED_ACTION);
            Uri uri = Uri.parse("sms://localhost:" + destPort);
            intent.setData(uri);
            intent.setComponent(null);
        }

        dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
                AppOpsManager.OP_RECEIVE_SMS, resultReceiver, UserHandle.OWNER);
    }

简单的记录了下短彩信接受framework层的处理,下面是自己分析时画的时序图:

时间: 2024-08-28 17:47:10

Android 5.0 Lollipop 短彩信接收流程的相关文章

Android 5.0(Lollipop)中的SurfaceTexture,TextureView, SurfaceView和GLSurfaceView

SurfaceView, GLSurfaceView, SurfaceTexture以及TextureView是Android当中名字比较绕,关系又比较密切的几个类.本文基于Android 5.0(Lollipop)的代码理一下它们的基本原理,联系与区别. SurfaceView从Android 1.0(API level 1)时就有 .它继承自类View,因此它本质上是一个View.但与普通View不同的是,它有自己的Surface.我们知道,一般的Activity包含的多个View会组成Vi

Android 2.3发短信详细流程

在android中,APP通过SmsManager.java一系列方法实现发送短信的功能,而发送的内容有很很多种,比如sendTextMessage.sendMultipartTextMessage.sendDataMessage等等,在这篇文章里我们就以其中一个为例阐述发送短信的完整流程,如果有不对的地方,请大家指正,一起学习. 1. 起点:SmsManager.java (frameworks/base/telephony/java/android/telephony/SmsManager.

Android 5.0 Lollipop SDK下载地址(PASS)

Android 5.0 ARM EABI v7a System Image https://dl-ssl.google.com/android/repository/sys-img/google_apis/sysimg_arm-21_r01.zip Android 5.0 Android TV ARM EABI v7a System Imagehttps://dl-ssl.google.com/android/repository/sys-img/android-tv/sysimg_atv_ar

Android 5.0 Lollipop介绍

Android Lollipop介绍 Android 5.0 Lollipop,此版本为用户提供了丰富的新功能,并为开发者新增了数以千计的 API,它进一步扩展了 Android 的应用范围,从手机.平板电脑和可穿戴式设备,扩展到电视和汽车. 1.Android 5.0新增功能与特性 Material Design: 简介:Material Design语言的一些重要功能包括 系统字体Roboto的升级版本 ,同时颜色更鲜艳,动画效果更突出.杜拉特还简要谈到了新框架的一些变化--这个新框架也于今

Getting started with &#39;User Accounts&#39; on Android 5.0 Lollipop (android的多用户支持)

With Android 5.0 Lollipop, Google is adding true multi-user support for tablets and smartphones alike. When Google released Android 4.2 it included multiple user accounts for tablets; however, smartphone users were left in the cold. (In Google's defe

Android 5.0 Lollipop SDK下载地址

https://dl-ssl.google.com/android/repository/android-21_r01.zip https://dl-ssl.google.com/android/repository/platform-tools_r21-windows.zip https://dl-ssl.google.com/android/repository/platform-tools_r21-linux.zip https://dl-ssl.google.com/android/re

Android 5.0 Lollipop初上手体验

在等了好几天还没有等到OTA升级提示,前天笔者给Nexus4线刷入了官方提供的Lollipop的镜像,在试用了这两天之后,现在总结下自己感觉很惊艳的地方和一些地方的吐槽.(点击图片可以查看大图) 1.Material Design: 不得不说,这次的UI风格与用户交互改变很大,主要的就是谷歌推行的Material Design,刚开始看着和用着都觉得挺别扭,但是一旦接受了这个设定,还是挺带感的括弧笑. 典型的用户界面与交互设计可以参考Gmail,不得不说,Gmail一直是谷歌给开发者设计应用的规

android 5.0 (lollipop)源码编译环境搭建(Mac OS X)

硬件环境:MacBook Pro Retina, 13-inch, Late 2013 处理器  2.4 GHz Intel Core i5 内存  8 GB 1600 MHz DDR3 硬盘60G以上 软件环境:OS X 10.9.2 GNU Make 3.81 Python 2.7.5 XCode 5.0.2 java version "1.7.0_55" repo VERSION = (1, 21) 某收费VPN(代理FAN墙是下载不了的,请使用VPN) (软件版本问题非常可能导

Android 4.0及以上版本接收开机广播BOOT_COMPLETED、开机自启动服务

情景概要:自己做的一个项目的时候,或得不到开启启动的通知,这样更别说开机启动通知里面实现开机服务功能了,查找了N多资料,说法不一,太多的人说4.0之后无法获得开机通知,通过各种渠道,各种大牛的方式仍然是那些N多人说不可行的方法,即使大牛给的是英文文档也是说这样可以的. 最后发现,开启启动通知已经实现了,但是自己的疏忽没有发现,我通过在通知里面弹出一个Toast,但是真机或者模拟器在开机的时候都需要很多启动项,导致最后的Toast弹出很晚,而自己却没看见.你可以在通知里面弹出10个以上的Toast