Android N 来电流程(MT)

本流程图基于MTK平台 Android 7.0,普通来电,本流程只作为沟通学习使用

本篇文章写作顺序是从modem上报消息,一层一层上报到incallUI,读者可以根据需求选择阅读顺序。

frameworks/opt/telephony/

这里写图片描述

当对方拨打电话后,运营商就会通过基站向含有特定SIM卡手机的modem发送指令,当手机modem收到这个指令后就会发生变化,并将变化信息通过AT指令集的方式传送给RILC,RILC又会通过socket的方式将变化信息传递到RILJ,此时RILJ的RILReceiver就会处理这些消息,从而进入我们上图的流程当中。

第一次其实是RIL_UNSOL_INCOMING_CALL_INDICATION这个事件,mIncomingCallIndicationRegistrant这个观察者list是在BaseCommands中定义并实现了添加观察者的方法,在GsmCdmaCallTracker初始化的时候往里面加入了观察者,观察EVENT_INCOMING_CALL_INDICATION事件,所以,当RILC向RILJ传送UNSOL_INCOMING_CALL_INDICATION事件时,通过
mIncomingCallIndicationRegistrant.notifyRegistrant(new AsyncResult(null, ret, null));这个方法,让GsmCdmaCallTracker的 handleMessage 的 EVENT_INCOMING_CALL_INDICATION,这样就把消息通过观察者模式传递到了GsmCdmaCallTracker里面去了,在这里面做一些判断,比如提高PhoneAPP的优先级、多个来电拒绝最新的来电等.

相关log信息

12-30 14:57:45.564 D/RILJ    ( 1452): [UNSL]< UNSOL_RESPONSE_CALL_STATE_CHANGED [SUB0]
12-30 14:57:45.565 D/GsmCallTrackerHelper( 1452): handle EVENT_CALL_STATE_CHANGE (slot 0)
12-30 14:57:45.565 D/RILJ    ( 1452): [4481]> GET_CURRENT_CALLS [SUB0]
12-30 14:57:45.584 D/RILJ    ( 1452): [4481]< GET_CURRENT_CALLS {[id=1,INCOMING,toa=129,norm,mt,0,voc,nonvid,noevp,,cli=1,,1] } [SUB0]
12-30 14:57:45.586 D/GsmCallTrackerHelper( 1452): handle EVENT_POLL_CALLS_RESULT (slot 0)
12-30 14:57:45.586 D/GsmCdmaCallTracker( 1452): Event EVENT_POLL_CALLS_RESULT Received 

这部分流程主要是做一些状态的上报,还有一些connection的初始化.

RIL和modem简单交互图

这里写图片描述 这里写图片描述

详细的介绍可以参考满哥的 http://blog.csdn.net/yihongyuelan/article/details/22044787 这篇文章,看完后应该会有个大致的了解,这里就不再细说了。

packages/services/Telecomm

这里写图片描述

这个流程图主要介绍了Telecom这层对下面Telephony传上来的数据处理,大概是一下几步:

  1. 将telephony上传的数据封装成一个intent
  2. 创建一个call
  3. 创建一个链接,并建立起一个链接

重要的方法:

构造intent的额外信息

    /**
     * Sends the incoming call intent to telecom.
     */
    private void sendIncomingCallIntent(Connection connection) {
        /// M: ALPS02136977. Prints debug messages for telephony. @{
        if (connection != null) {
            FormattedLog formattedLog = new FormattedLog.Builder()
                    .setCategory("CC")
                    .setServiceName("Telephony")
                    .setOpType(FormattedLog.OpType.NOTIFY)
                    .setActionName("MT")
                    .setCallNumber(connection.getAddress())
                    .setCallId("")
                    .buildDebugMsg();
            if (formattedLog != null) {
                Log.d(this, formattedLog.toString());
            }
        }
        /// @}

        Bundle extras = new Bundle();
        if (connection.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED &&
                !TextUtils.isEmpty(connection.getAddress())) {
            Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
            extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri);
            /// M: For one-key conference MT displayed as incoming conference call. @{
            boolean isIncomingMpty = connection.isIncomingCallMultiparty();
            Log.d(this, "isIncomingMpty: " + isIncomingMpty);
            extras.putBoolean(TelecomManagerEx.EXTRA_VOLTE_CONF_CALL_INCOMING, isIncomingMpty);
            /// @}
        }

        // Specifies the time the call was added. This is used by the dialer for analytics.
        extras.putLong(TelecomManager.EXTRA_CALL_CREATED_TIME_MILLIS,
                SystemClock.elapsedRealtime());

        PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
        if (handle == null) {
            try {
                connection.hangup();
            } catch (CallStateException e) {
                // connection already disconnected. Do nothing
            }
        } else {
            TelecomManager.from(mPhone.getContext()).addNewIncomingCall(handle, extras);
        }
    }

创建一个call

    /**
     * Starts the process to attach the call to a connection service.
     *
     * @param phoneAccountHandle The phone account which contains the component name of the
     *        connection service to use for this call.
     * @param extras The optional extras Bundle passed with the intent used for the incoming call.
     */
    void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
        Log.d(this, "processIncomingCallIntent");
        Uri handle = extras.getParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS);
        if (handle == null) {
            // Required for backwards compatibility
            handle = extras.getParcelable(TelephonyManager.EXTRA_INCOMING_NUMBER);
        }
        Call call = new Call(
                getNextCallId(),
                mContext,
                this,
                mLock,
                mConnectionServiceRepository,
                mContactsAsyncHelper,
                mCallerInfoAsyncQueryFactory,
                handle,
                null /* gatewayInfo */,
                null /* connectionManagerPhoneAccount */,
                phoneAccountHandle,
                Call.CALL_DIRECTION_INCOMING /* callDirection */,
                false /* forceAttachToExistingConnection */,
                false /* isConference */
        ); //创建一个call

        call.initAnalytics();
        if (getForegroundCall() != null) {
            getForegroundCall().getAnalytics().setCallIsInterrupted(true);
            call.getAnalytics().setCallIsAdditional(true);
        }

        setIntentExtrasAndStartTime(call, extras);
        /// M: For VoLTE @{
        if (TelecomVolteUtils.isConferenceInvite(extras)) {
            call.setIsIncomingFromConfServer(true);
        }
        /// @}

        // TODO: Move this to be a part of addCall()
        call.addListener(this);
        call.startCreateConnection(mPhoneAccountRegistrar);
    }

创建链接

    /**
     * This can be used by telecom to either create a new outgoing call or attach to an existing
     * incoming call. In either case, telecom will cycle through a set of services and call
     * createConnection util a connection service cancels the process or completes it successfully.
     */
    private void createConnection(
            final PhoneAccountHandle callManagerAccount,
            final String callId,
            final ConnectionRequest request,
            boolean isIncoming,
            boolean isUnknown) {
        Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
                        "isIncoming: %b, isUnknown: %b", callManagerAccount, callId, request,
                isIncoming,
                isUnknown);

        /// M: ALPS02136977. Prints debug messages for MO. @{
        if (!isIncoming) {
            String callNumber = null;
            if (request != null && request.getAddress() != null) {
                callNumber = request.getAddress().getSchemeSpecificPart();
            }
            FormattedLog formattedLog = new FormattedLog.Builder()
                    .setCategory("CC")
                    .setServiceName(getConnectionServiceName())
                    .setOpType(FormattedLog.OpType.OPERATION)
                    .setActionName("Dial")
                    .setCallNumber(callNumber)
                    .setCallId("")
                    .buildDebugMsg();
            if (formattedLog != null) {
                Log.d(this, formattedLog.toString());
            }
        }
        /// @}

        Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
                : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
                : onCreateOutgoingConnection(callManagerAccount, request);//根据不同的状态创建不同类型的链接
        Log.d(this, "createConnection, connection: %s", connection);
        if (connection == null) {
            connection = Connection.createFailedConnection(
                    new DisconnectCause(DisconnectCause.ERROR));
        }

        connection.setTelecomCallId(callId);
        if (connection.getState() != Connection.STATE_DISCONNECTED) {
            addConnection(callId, connection);
        }

        Uri address = connection.getAddress();
        String number = address == null ? "null" : address.getSchemeSpecificPart();
        Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s, properties: %s",
                Connection.toLogSafePhoneNumber(number),
                Connection.stateToString(connection.getState()),
                Connection.capabilitiesToString(connection.getConnectionCapabilities()),
                Connection.propertiesToString(connection.getConnectionProperties()));

        Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
        /// M: CC: Set PhoneAccountHandle for ECC @{
        //[ALPS01794357]
        PhoneAccountHandle handle = connection.getAccountHandle();
        if (handle == null) {
            handle = request.getAccountHandle();
        } else {
            Log.d(this, "createConnection, set back phone account:%s", handle);
        }
         @}
        mAdapter.handleCreateConnectionComplete(
                callId,
                request,
                new ParcelableConnection(
                        handle,  /* M: CC: Set PhoneAccountHandle for ECC [ALPS01794357] */
                        connection.getState(),
                        connection.getConnectionCapabilities(),
                        connection.getConnectionProperties(),
                        connection.getAddress(),
                        connection.getAddressPresentation(),
                        connection.getCallerDisplayName(),
                        connection.getCallerDisplayNamePresentation(),
                        connection.getVideoProvider() == null ?
                                null : connection.getVideoProvider().getInterface(),
                        connection.getVideoState(),
                        connection.isRingbackRequested(),
                        connection.getAudioModeIsVoip(),
                        connection.getConnectTimeMillis(),
                        connection.getStatusHints(),
                        connection.getDisconnectCause(),
                        createIdList(connection.getConferenceables()),
                        connection.getExtras()));
        if (isUnknown) {
            triggerConferenceRecalculate();
        }

        /// M: CC: Proprietary CRSS handling @{
        // [ALPS01956888] For FailureSignalingConnection, CastException JE will happen.
        if (connection.getState() != Connection.STATE_DISCONNECTED) {
            forceSuppMessageUpdate(connection);
        }
        /// @}
    }

相关的log和步骤介绍

12-30 14:57:45.603 D/Telephony( 1452): PstnIncomingCallNotifier: handleNewRingingConnection
12-30 14:57:45.603 D/Telephony( 1452): PstnIncomingCallNotifier: [Debug][CC][Telephony][Notify][MT][13880118404][]
12-30 14:57:45.604 D/Telephony( 1452): PstnIncomingCallNotifier: isIncomingMpty: false   
//判断来电是不是会议电话  这里会构造intent的extras放入号码、当前呼入时间、是否是会议通话,并且传给telecom  PstnIncomingCallNotifier.sendIncomingCallIntent

12-30 14:57:45.608 V/Telecom (  936): Logging: START_SESSION: TSI.aNIC@ApY
12-30 14:57:45.608 I/Telecom (  936): : Adding new incoming call with phoneAccountHandle PhoneAccountHandle{TelephonyConnectionService, 89860115881029413909, UserHandle{0}}: TSI.aNIC@ApY
//这个方法里面会检查包名、检查phoneaccount、然后构造完整的intent:ACTION_INCOMING_CALL、KEY_IS_INCOMING_CALL等等   TelecomServiceImpl.addNewIncomingCall

12-30 14:57:45.618 D/Telecom (  936): Telecom-LogUtils: [Debug][CC][Telecom][Notify][MT][][], Intent = Intent { act=android.telecom.action.INCOMING_CALL (has extras) }: TSI.aNIC@ApY 
12-30 14:57:45.619 D/Telecom (  936): Class: Processing incoming call from connection service [ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}]: TSI.aNIC@ApY 
//这里会判断intent的EXTRA_PHONE_ACCOUNT_HANDLE 和EXTRA_INCOMING_CALL_EXTRAS是否为null    CallIntentProcessor.processIncomingCallIntent

12-30 14:57:45.619 D/Telecom (  936): CallsManager: processIncomingCallIntent: TSI.aNIC@ApY
//这里会构造一个call ,并打断前台电话,设置当前时间为telecom处理时间,CallsManager.processIncomingCallIntent

12-30 14:57:45.640 V/Telecom (  936): CreateConnectionProcessor: CreateConnectionProcessor created for Call = [TC@5, NEW, null, tel:13880118404, A, childs(0), has_parent(false), [Capabilities:], [Properties:]]: TSI.aNIC@ApY
//创建链接处理器   CreateConnectionProcessor.process

12-30 14:57:45.643 V/Telecom (  936): CreateConnectionProcessor: process: TSI.aNIC@ApY 
12-30 14:57:45.658 V/Telecom (  936): CreateConnectionProcessor: attemptNextPhoneAccount: TSI.aNIC@ApY
12-30 14:57:45.659 I/Telecom (  936): CreateConnectionProcessor: Trying attempt CallAttemptRecord(PhoneAccountHandle{TelephonyConnectionService, 89860115881029413909, UserHandle{0}},PhoneAccountHandle{TelephonyConnectionService, 89860115881029413909, UserHandle{0}}): TSI.aNIC@ApY
//设置call的connectionmanager、connectionservice、Timeout、phoneaccount、等信息    CreateConnectionProcessor.attemptNextPhoneAccount

12-30 14:57:45.660 D/Telecom (  936): ConnectionServiceWrapper: createConnection([TC@5, NEW, com.android.phone/com.android.services.telephony.TelephonyConnectionService, tel:13880118404, A, childs(0), has_parent(false), [Capabilities:], [Properties:]]) via ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}.: TSI.aNIC@ApY
12-30 14:57:45.681 D/TelecomFramework( 1452): : Enqueueing pre-init request TC@5 
12-30 14:57:45.697 D/TelecomFramework( 1452): TelephonyConnectionService: createConnection, callManagerAccount: PhoneAccountHandle{TelephonyConnectionService, 89860115881029413909, UserHandle{0}}, callId: TC@5, request: ConnectionRequest tel:13880118404 Bundle[mParcelledData.dataSize=584], isIncoming: true, isUnknown:
12-30 14:57:45.698 I/Telephony( 1452): TelephonyConnectionService: onCreateIncomingConnection, request: ConnectionRequest tel:13880118404 Bundle[mParcelledData.dataSize=584]
//真正的创建一个链接,根据类型的不同 有onCreateUnknownConnection、onCreateIncomingConnection、onCreateOutgoingConnection这些  ConnectionService.createConnection

12-30 14:57:45.712 V/TelecomFramework( 1452): TelephonyConnectionService: createConnection, number: 13880118404, state: RINGING, capabilities: [Capabilities: CAPABILITY_SUPPORT_HOLD CAPABILITY_MUTE CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO CAPABILITY_SPEED_UP_MT_AUDIO CAPABILITY_SEPARATE_FROM_CONFERENCE CAPABILITY_DISCONNECT_FROM_CONFERENCE], properties: [Properties:]
12-30 14:57:45.712 D/TelecomFramework( 1452): TelephonyConnectionService: createConnection, calling handleCreateConnectionSuccessful TC@5
12-30 14:57:45.715 D/Telecom (  936): Telecom-LogUtils: [Debug][CC][Telecom][Notify][CreateMtSuccess][13880118404][TC@5]ParcelableConnection [act:PhoneAccountHandle{TelephonyConnectionService, 89860115881029413909, UserHandle{0}}], state:2, capabilities:[Capabilities: CAPABILITY_SUPPORT_HOLD CAPABILITY_MUTE CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO CAPABILITY_SPEED_UP_MT_AUDIO CAPABILITY_SEPARATE_FROM_CONFERENCE CAPABILITY_DISCONNECT_FROM_CONFERENCE], properties:[Properties:], extras:Bundle[mParcelledData.dataSize=104]: CSW.hCCC@Apo
12-30 14:57:45.715 D/Telecom (  936): ConnectionServiceWrapper: ConnectionService -> Telecom: handleCreateConnectionComplete TC@5: CSW.hCCC@Apo 
//MT成功  ConnectionServiceWrapper.ParcelableConnection

12-30 14:57:45.719 V/Telecom (  936): Call: handleCreateConnectionSuccessful ParcelableConnection [act:PhoneAccountHandle{TelephonyConnectionService, 89860115881029413909, UserHandle{0}}], state:2, capabilities:[Capabilities: CAPABILITY_SUPPORT_HOLD CAPABILITY_MUTE CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO CAPABILITY_SPEED_UP_MT_AUDIO CAPABILITY_SEPARATE_FROM_CONFERENCE CAPABILITY_DISCONNECT_FROM_CONFERENCE], properties:[Properties:], extras:Bundle[mParcelledData.dataSize=104]: CSW.hCCC@Apo
//这里会设置比较多的call的状态和信息,Call.handleCreateConnectionSuccess

12-30 14:57:45.745 D/Telecom (  936): CallsManager: onSuccessfulIncomingCall: CSW.hCCC@Apo
//这里会设置很多的过滤器,并执行过滤 CallsManager.onSuccessfulIncomingCall

12-30 14:57:45.746 D/Telecom (  936): IncomingCallFilter: [performFiltering], timeout = 5000: CSW.hCCC@Apo 
12-30 14:57:45.811 V/Telecom (  936): CallsManager: addCall([TC@5, RINGING, com.android.phone/com.android.services.telephony.TelephonyConnectionService, tel:13880118404, A, childs(0), has_parent(false), [Capabilities: CAPABILITY_SUPPORT_HOLD CAPABILITY_MUTE CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO CAPABILITY_SPEED_UP_MT_AUDIO CAPABILITY_SEPARATE_FROM_CONFERENCE CAPABILITY_DISCONNECT_FROM_CONFERENCE], [Properties:]])
12-30 14:57:45.831 I/Telecom (  936): EmergencyInCallServiceConnection: Attempting to bind to InCall ComponentInfo{com.android.dialer/com.android.incallui.InCallServiceImpl}, with Intent { act=android.telecom.InCallService cmp=com.android.dialer/com.android.incallui.InCallServiceImpl }
//EmergencyInCallServiceConnection继承自InCallServiceBindingConnection 所以最终会回调到onServiceConnected

12-30 14:57:45.885 D/Telecom (  936): : onServiceConnected: ComponentInfo{com.android.dialer/com.android.incallui.InCallServiceImpl} false true: ICSBC.oSC@Ap4  //YT
12-30 14:57:45.885 I/Telecom (  936): InCallController: onConnected to ComponentInfo{com.android.dialer/com.android.incallui.InCallServiceImpl}: ICSBC.oSC@Ap4
12-30 14:57:45.886 I/Telecom (  936): InCallController: Adding 1 calls to InCallService after onConnected: ComponentInfo{com.android.dialer/com.android.incallui.InCallServiceImpl}: ICSBC.oSC@Ap4
//后面会通过InCallServiceImpl 的onCallAdded方法调用到上层界面incallUI里面去

packages/apps/Dialer

这里写图片描述

这里主要是把来电的消息转发到incallUI:

  1. 收到来电信息,改变关心此消息的变量的状态
  2. 判断当前手机状态决定以全屏显示来电界面还是以headsup的形式提示用户

重要的方法:

确定是来电后的一些处理逻辑

    /**
     * Called when there is a new incoming call.
     *
     * @param call
     */
    @Override
    public void onIncomingCall(Call call) {
        /// M: for ALPS01945830. Force set theme colors. @{
        setThemeColors();
        /// @}
        InCallState newState = startOrFinishUi(InCallState.INCOMING);
        InCallState oldState = mInCallState;

        Log.i(this, "Phone switching state: " + oldState + " -> " + newState);
        mInCallState = newState;

        for (IncomingCallListener listener : mIncomingCallListeners) {
            listener.onIncomingCall(oldState, mInCallState, call);
        }
    }

决定显示HeadsUp还是AnswerFragment

    @Override
    public void addNotification(StatusBarNotification notification, RankingMap ranking,
            Entry oldEntry) {
        if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());

        mNotificationData.updateRanking(ranking);
        Entry shadeEntry = createNotificationViews(notification);
        if (shadeEntry == null) {
            return;
        }
        boolean isHeadsUped = shouldPeek(shadeEntry);
        Log.d("michael", "isHeadsUped: " +isHeadsUped);
        if (isHeadsUped) { //根据这个值确定是否显示HeadsUp true显示
            mHeadsUpManager.showNotification(shadeEntry);
            // Mark as seen immediately
            setNotificationShown(notification);
        }

        if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
            if (shouldSuppressFullScreenIntent(notification.getKey())) {
                if (DEBUG) {
                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
                }
            } else if (mNotificationData.getImportance(notification.getKey())
                    < NotificationListenerService.Ranking.IMPORTANCE_MAX) {
                if (DEBUG) {
                    Log.d(TAG, "No Fullscreen intent: not important enough: "
                            + notification.getKey());
                }
            } else {
                // Stop screensaver if the notification has a full-screen intent.
                // (like an incoming phone call)
                awakenDreams();

                // not immersive & a full-screen alert should be shown
                if (DEBUG)
                    Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
                try {
                    EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
                            notification.getKey());
                    notification.getNotification().fullScreenIntent.send();//显示AnswerFragment
                    shadeEntry.notifyFullScreenIntentLaunched();
                    MetricsLogger.count(mContext, "note_fullscreen", 1);
                } catch (PendingIntent.CanceledException e) {
                }
            }
        }
        addNotificationViews(shadeEntry, ranking);
        // Recalculate the position of the sliding windows and the titles.
        setAreThereNotifications();
    }

相关的log信息

12-30 14:57:45.992 D/InCall  ( 3633): CallList - onCallAdded: callState=4, incallui call id=Call_1, telcom call id=TC@5
12-30 14:57:45.992 I/InCall  ( 3633): CallList - onIncoming - [Call_1, INCOMING, [Capabilities: CAPABILITY_SUPPORT_HOLD CAPABILITY_RESPOND_VIA_TEXT CAPABILITY_MUTE CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO CAPABILITY_SEPARATE_FROM_CONFERENCE CAPABILITY_DISCONNECT_FROM_CONFERENCE], children:[], parent:null, conferenceable:[], videoState:Audio Only, mSessionModificationState:0, VideoSettings:(CameraDir:-1)] 
//Called when a single call has changed. call已经发生改变,更新一些值的状态 CallList.onIncoming
12-30 14:57:46.001 I/InCall  ( 3633): InCallPresenter - Start Full Screen in call UI  
12-30 14:57:46.105 I/InCall  ( 3633): StatusBarNotifier - Displaying notification for 2
12-30 14:57:46.110 V/NotificationService(  936): enqueueNotificationInternal: pkg=com.android.dialer id=2 notification=Notification(pri=1 contentView=null vibrate=null sound=null defaults=0x0 flags=0x82 color=0xff00796b category=call actions=2 vis=PRIVATE publicVersion=Notification(pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x0 color=0xff0288d1 vis=PRIVATE))
12-30 14:57:46.112 D/NotificationService(  936): EnqueueNotificationRunnable.run for: 0|com.android.dialer|2|null|10006
12-30 14:57:46.112 I/InCall  ( 3633): InCallPresenter - Phone switching state: NO_CALLS -> INCOMING
12-30 14:57:46.126 D/InCall  ( 3633): AnswerPresenter - onIncomingCall: com.android.incallui.AnswerPresenter@f23e1cd
12-30 14:57:46.136 D/StatusBar( 1190): onNotificationPosted: StatusBarNotification(pkg=com.android.dialer user=UserHandle{0} id=2 tag=null key=0|com.android.dialer|2|null|10006: Notification(pri=2 contentView=null vibrate=null sound=null defaults=0x0 flags=0x82 color=0xff00796b category=call actions=2 vis=PRIVATE publicVersion=Notification(pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x0 color=0xff0288d1 vis=PRIVATE)))
12-30 14:57:46.136 D/PhoneStatusBar( 1190): addNotification key=0|com.android.dialer|2|null|10006

完整流程图

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: MT7628是一款高度集成的无线路由器芯片,支持双频段802.11n WiFi和Fast Ethernet。它具有高效的处理能力,能够实现多种网络场景,比如AP+STA模式。 AP(Access Point)模式是指MT7628作为无线接入点,通过无线信号向其他设备提供网络服务。STA(Station)模式是指MT7628作为无线客户端,通过无线信号连接到其他的无线接入点上。 当MT7628同时支持AP和STA模式时,就可以实现AP+STA模式。这种模式可以使MT7628既能够连接到无线网络中,又能够提供无线网络服务,适用于多种应用场景。 比如,在家庭网络中,可以通过MT7628将有线网络转换为无线网络,实现整个家庭的WiFi覆盖。同时,如果家中还有其他的无线接入点,MT7628也可以以STA模式连接到这些接入点,扩展WiFi覆盖面。 另外,在办公场所中,可以通过MT7628提供一个无线接入点,让员工连接到公司网络中,这样可以方便员工的移动工作和无线上网需求。同时,MT7628也可以以STA模式连接到办公室中的其他无线设备,方便数据共享和设备控制。 总之,MT7628 ap sta模式具有灵活性和多功能性,在无线网络应用中有着广泛的用途和应用前景。 ### 回答2: MT7628是一款集成了CPU、无线、以太网、USB和多种外设接口的芯片。它可以用于各种路由器和物联网设备中,特别在AP和STA模式下有广泛应用。 AP模式(接入点模式)是将路由器变成无线接入点,用于创建局域网(LAN),允许多个设备连接到它并共享资源。MT7628的AP模式可支持2.4GHz无线频段,提供最高300Mbps无线传输速率,可在家庭、办公室、学校等场合使用。 STA模式(站点模式)允许MT7628芯片作为无线客户端连接到其他AP或路由器,实现无线接口的通信。在STA模式下,MT7628可以通过物理接口转发网络数据,实现无线与有线的互通,例如将其他设备的网络接口转成无线接口实现无线连接,或者将无线接口连接到其他设备的物理接口上。 总的来说,MT7628芯片在AP和STA模式下有广泛的应用场景和展示空间,可以应对不同的物联网需求,满足用户多样的网络连接需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值