zoukankan      html  css  js  c++  java
  • 移动数据 流程分析


    切入点,setting 中 ”启用移动数据“


    1: Settings.java (packagesappsphonesrccomandroidphone)
        开始点击启用移动数据的按钮   
        protected void onCreate(Bundle icicle) {
            super.onCreate(icicle);
            addPreferencesFromResource(R.xml.network_setting);
            ....
            mButtonDataEnabled = (CheckBoxPreference) prefSet.findPreference(BUTTON_DATA_ENABLED_KEY); // 启动移动数据的按钮
    2:  Settings.java (packagesappsphonesrccomandroidphone)
           点击启用移动数据  执行代码:  cm.setMobileDataEnabled(mButtonDataEnabled.isChecked());// 网络数据开关 打开后执行的语句      
          public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
            /** TODO: Refactor and get rid of the if's using subclasses */
            ....
            } else if (preference == mButtonDataEnabled) {
                if (DBG) log("onPreferenceTreeClick: preference == mButtonDataEnabled.");
                ConnectivityManager cm =
                        (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
                cm.setMobileDataEnabled(mButtonDataEnabled.isChecked());// lhj enable 网络数据开关     调用 setMobileDateEnabled 函数
                return true;
            } ....
        }   
    3:   ConnectivityManager.java (frameworksasecorejavaandroid et)      
           调用 setMobileDataEnabled 函数
            public void setMobileDataEnabled(boolean enabled) {   // setMobileDataEnabled 函数
            try {
                mService.setMobileDataEnabled(enabled);  // 调用 ConnectivityService.java 中的 setMobileDateEnabled 函数
            } catch (RemoteException e) {
            }
            }        
    4:  ConnectivityService.java (frameworksaseservicesjavacomandroidserver)
           调用 setMobileDateEnabled 函数   
          public void setMobileDataEnabled(boolean enabled) {
            enforceChangePermission();// 获取权限
            if (DBG) log("setMobileDataEnabled(" + enabled + ")");
            mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
                    (enabled ? ENABLED : DISABLED), 0));// 发送消息 EVENT_SET_MOBILE_DATA               
        }   
    5:ConnectivityService.java (frameworksaseservicesjavacomandroidserver)
        public void handleMessage(Message msg) {
                NetworkInfo info;
                switch (msg.what) {
                      .......
                    case EVENT_SET_MOBILE_DATA:   // 收到消息后 执行case EVENT_SET_MOBILE_DATA
                    {
                        boolean enabled = (msg.arg1 == ENABLED);
                        handleSetMobileData(enabled);//事件触发后设置移动数据 执行handleSetMobileData 函数
                        break;
                    }
                     .......               
    6:  ConnectivityService.java (frameworksaseservicesjavacomandroidserver)
         handleSetMobileData 函数
         private void handleSetMobileData(boolean enabled) {
            if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
                if (VDBG) {
                    log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
                }
                mNetTrackers[ConnectivityManager.TYPE_MOBILE].setUserDataEnable(enabled);// 调用setUserDataEnable 函数
            }
        }   
    7:MobileDataStateTracker.java (frameworksasecorejavaandroid et)
         调用setUserDataEnable 函数
       public void setUserDataEnable(boolean enabled) {  // setUserDataEnable 被调用
            if (DBG) log("setUserDataEnable: E enabled=" + enabled);
            final AsyncChannel channel = mDataConnectionTrackerAc;
            if (channel != null) {
                channel.sendMessage(CMD_SET_USER_DATA_ENABLE, enabled ? ENABLED : DISABLED);// 发送消息  CMD_SET_USER_DATA_ENABLE
                mUserDataEnabled = enabled;
            }
            if (VDBG) log("setUserDataEnable: X enabled=" + enabled);
        }   
    8:DataConnectionTracker.java (frameworksase elephonyjavacomandroidinternal elephony)
        接收消息并处理 CMD_SET_USER_DATA_ENABLE   
         public void handleMessage(Message msg) {
            switch (msg.what) {
           .......
                case CMD_SET_USER_DATA_ENABLE: {  // 接受 CMD_SET_USER_DATA_ENABLE 并执行case CMD_SET_USER_DATA_ENABLE
                    final boolean enabled = (msg.arg1 == ENABLED) ? true : false;
                    if (DBG) log("CMD_SET_USER_DATA_ENABLE enabled=" + enabled);
                    onSetUserDataEnabled(enabled);  //调用 OnSetUserDataEnable 函数
                    break;
                }
           .......     
    9:DataConnectionTracker.java (frameworksase elephonyjavacomandroidinternal elephony)
         调用 OnSetUserDataEnable 函数
         
            protected void onSetUserDataEnabled(boolean enabled) { // OnSetUserDataEnable 函数
            synchronized (mDataEnabledLock) {
                final boolean prevEnabled = getAnyDataEnabled();
                if (mUserDataEnabled != enabled) {
                    mUserDataEnabled = enabled;
                    Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
                            Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
                    if (prevEnabled != getAnyDataEnabled()) {
                        if (!prevEnabled) {
                            resetAllRetryCounts();
                            onTrySetupData(Phone.REASON_DATA_ENABLED);  // 调用onTrySetupData 函数
                        } else {
                            onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
                        }
                    }
                }
            }
        }
    10: GsmDataConnectionTracker.java (frameworksase elephonyjavacomandroidinternal elephonygsm)      
           调用onTrySetupData 函数
        protected boolean onTrySetupData(String reason) {  //onTrySetupData 函数
            if (DBG) log("onTrySetupData: reason=" + reason);
            setupDataOnReadyApns(reason); // 调用setupDataOnReadyApns 函数  检查APN 列表
            return true;
        }   
    11:GsmDataConnectionTracker.java (frameworksase elephonyjavacomandroidinternal elephonygsm)
          调用setupDataOnReadyApns 函数
          
          private void setupDataOnReadyApns(String reason) { // setupDataOnReadyApns 函数
               ....
            // Only check for default APN state
    for (ApnContext apnContext : mApnContexts.values()) {
                if (apnContext.getState() == State.FAILED) {
                    // By this time, alarms for all failed Apns
                    // should be stopped if any.
                    // Make sure to set the state back to IDLE
                    // so that setup data can happen.
                    apnContext.setState(State.IDLE);
                }
                if (apnContext.isReady()) {
                    if (apnContext.getState() == State.IDLE) {
                        apnContext.setReason(reason);
                        trySetupData(apnContext); // apn ready 调用 trySetupData 函数
                    }
                }
            }
        }   
    12:GsmDataConnectionTracker.java (frameworksase elephonyjavacomandroidinternal elephonygsm)   
           调用 trySetupData 函数      
          private boolean trySetupData(ApnContext apnContext) {// trySetupData 函数  (关键函数)
            if (mPhone.getSimulatedRadioControl() != null) {
                // Assume data is connected on the simulator
                // FIXME  this can be improved
                apnContext.setState(State.CONNECTED);   // 调用setState 方法
                mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
                log("trySetupData: (fix?) We're on the simulator; assuming data is connected");
                return true;
            }
            boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
            if ((apnContext.getState() == State.IDLE || apnContext.getState() == State.SCANNING) &&
                    isDataAllowed(apnContext) && getAnyDataEnabled() && !isEmergency()) {
                if (apnContext.getState() == State.IDLE) {
                    ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
                    if (waitingApns.isEmpty()) {
                        if (DBG) log("trySetupData: No APN found");
                        notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
                        notifyOffApnsOfAvailability(apnContext.getReason());
                        return false;
                    } else {
                        apnContext.setWaitingApns(waitingApns);
                        if (DBG) {
                            log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns));
                        }
                    }
                }
                boolean retValue = setupData(apnContext);//  得到retValue  调用函数setupData  继续流程 14 步
                notifyOffApnsOfAvailability(apnContext.getReason());
                return retValue;
            } else {
                // TODO: check the condition.
                if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)
                    && (apnContext.getState() == State.IDLE
                        || apnContext.getState() == State.SCANNING))
                    mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
                notifyOffApnsOfAvailability(apnContext.getReason());
                return false;
            }
        }  
    13:ApnContext.java (frameworksase elephonyjavacomandroidinternal elephony)  (与流程无关)
        setState 方法
        public synchronized void setState(DataConnectionTracker.State s) {  // synchronized 关键字作用为锁定调用这个方法的对象  其他对象不能调用
            if (DBG) {
                log("setState: " + s + " for type " + mApnType + ", previous state:" + mState);
            }
            mState = s;    // 只是对于网络状态的改变  
            if (mState == DataConnectionTracker.State.FAILED) {
                if (mWaitingApns != null) {
                    mWaitingApns.clear(); // when teardown the connection and set to IDLE
                }
            }
        }   
    14: GsmDataConnectionTracker.java (frameworksase elephonyjavacomandroidinternal elephonygsm)
         setupData 函数
            private boolean setupData(ApnContext apnContext) {
            ....
            Message msg = obtainMessage();
            msg.what = EVENT_DATA_SETUP_COMPLETE;
            msg.obj = apnContext;
            dc.bringUp(msg, apn);  // 发送消息 调用bringup 继续往下
            if (DBG) log("setupData: initing!");
            return true;
        }   
    15:DataConnection.java (frameworksase elephonyjavacomandroidinternal elephony)
           bringUp 函数
          
            public void bringUp(Message onCompletedMsg, ApnSetting apn) {
            sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg))); // 发送EVENT_CONNECT 事件
        }   
    16  DataConnection.java (frameworksase elephonyjavacomandroidinternal elephony)
             收到EVENT_CONNECT 后执行的代码         
                 public boolean processMessage(Message msg) {
                boolean retVal;
                switch (msg.what) {
                 ......
                    case EVENT_CONNECT:
                        ConnectionParams cp = (ConnectionParams) msg.obj;
                        cp.tag = mTag;
                        if (DBG) {
                            log("DcInactiveState msg.what=EVENT_CONNECT." + "RefCount = "
                                    + mRefCount);
                        }
                        mRefCount = 1;
                        onConnect(cp);  // 调用onConnect 方法
                        transitionTo(mActivatingState);
                        retVal = HANDLED;
                        break;
                 ......            
    17: GsmDataConnection.java (frameworksase elephonyjavacomandroidinternal elephonygsm)
            onConnect 方法
            
             void onConnect(ConnectionParams cp) {
             mApn = cp.apn;
           ....
            String protocol;
            if (phone.getServiceState().getRoaming()) {
                protocol = mApn.roamingProtocol;
            } else {
                protocol = mApn.protocol;
            }
            phone.mCM.setupDataCall(   //  调用 setupDataCall 方法
                    Integer.toString(getRadioTechnology(RILConstants.SETUP_DATA_TECH_GSM)),
                    Integer.toString(mProfileId),
                    mApn.apn, mApn.user, mApn.password,
                    Integer.toString(authType),
                    protocol, msg);
        }
    18:
    CommandsInterface.java (frameworksase elephonyjavacomandroidinternal elephony)

             setupDataCall 函数的接口  函数原型在ril.java 中 (19步)
             
              public void setupDataCall(String radioTechnology, String profile,
                String apn, String user, String password, String authType,
                String protocol, Message result);
                
    19 : RIL.java (frameworksase elephonyjavacomandroidinternal elephony)
          setupDataCall 函数  
          
         public void
         setupDataCall(String radioTechnology, String profile, String apn,
                String user, String password, String authType, String protocol,
                Message result) {
            RILRequest rr
                    = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);  //RIL_REQUEST_SETUP_DATA_CALL
            rr.mp.writeInt(7);
            rr.mp.writeString(radioTechnology);
            rr.mp.writeString(profile);
            rr.mp.writeString(apn);
            rr.mp.writeString(user);
            rr.mp.writeString(password);
            rr.mp.writeString(authType);
            rr.mp.writeString(protocol);
            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
                    + requestToString(rr.mRequest) + " " + radioTechnology + " "
                    + profile + " " + apn + " " + user + " "
                    + password + " " + authType + " " + protocol);
            send(rr);  // 发送RIL_REQUEST_SETUP_DATA_CALL 请求 ( 到达RIL )
            
    20: Marvell-ril.c (hardware ilmarvell-ril)
      
            RIL_REQUEST_SETUP_DATA_CALL  对应的响应
            
            static const struct request_info s_requests [] =
             {
              .....
              {RIL_REQUEST_SETUP_DATA_CALL,  SERVICE_PS,ril_request_setup_data_call},//ril_request_setup_data_call 方法
               .....
              }
             
    21 : Ril-ps.c (hardware ilmarvell-ril)
            ril_request_setup_data_call 方法
            
            void ril_request_setup_data_call(int request, void *data, size_t datalen, RIL_Token token)
              {
              UNUSED(request);
              UNUSED(datalen);
                 const char* radio_technology = ((const char **)data)[0];
                 const char* profile_type = ((const char **)data)[1];
                 const char* apn = ((const char **)data)[2];
                 const char* user = ((const char **)data)[3];
                 const char* passwd = ((const char **)data)[4];
                 const char* auth_type_str = ((const char **)data)[5];
                 const char* protocol = ((const char **)data)[6];
                 int profile = atoi(profile_type);
                 int auth_type = atoi(auth_type_str);

              LOGD("%s: profile_type=%d, apn=%s, user=%s,passwd=%s,auth_type=%d, protocol=%s",
               __FUNCTION__, profile, apn, user ? user : "NULL", passwd ? passwd : "NULL", auth_type, protocol);
            syncSetupDefaultPDPConnection(token, profile, apn, auth_type, user, passwd, protocol); //继续syncSetupDefaultPDPConnection函数
    }
    22:Ril-ps.c (hardware ilmarvell-ril)
           syncSetupDefaultPDPConnection函数
          
             /* Prossess RIL_REQUEST_SETUP_DATA_CALL in sync way*/
    static void syncSetupDefaultPDPConnection(RIL_Token token, int profile, const char* apn, int auth_type, const char* user, const char* passwd, const char* protocol)
    {
    ATResponse *p_response = NULL;
    int err = -1;
    int cid;
    RIL_Data_Call_Response result;
    char cmdString[MAX_AT_LENGTH];
    char ipaddress[64];
    char cid_str[8];
    char ifname[32];
    int is_ppp = is_ppp_enabled();
    int af = strcasecmp(protocol, "IPv6") ? AF_INET: AF_INET6;
    if (is_ppp)// For PPP connection, alway use default one
    {
      profile = RIL_DATA_PROFILE_DEFAULT; //Ril.h (hardware ilmock-rilsrccpp) 中RIL_DATA_PROFILE_DEFAULT=0
    }
    if(profile < RIL_DATA_PROFILE_DEFAULT || profile >= MAX_DATA_CALLS)
    {
      LOGW("RIL_REQUEST_SETUP_DATA_CALL: Profile %d unsupportted! ", profile);
      goto error;
    }
    cid = profile + 1;   //  cid=1
    snprintf(cid_str, sizeof(cid_str), "%d", cid);
    snprintf(ifname, sizeof(ifname), modemType == WUKONG ? "ccinetwk%d" : "ccinet%d", profile);
    result.status = PDP_FAIL_NONE;
    result.cid = cid;
    result.ifname = is_ppp ? "ppp0" : ifname;
    result.type = (char*)protocol;
    err = getInterfaceAddr(af, result.ifname, ipaddress);
    //if same data profile is active and APN is same, return SUCCESS
    if (err == 0 && g_datacalls[profile].apn[0] && strcmp(apn, g_datacalls[profile].apn) == 0)
    {
      LOGD("The PDP CID %s is already active: IP address %s for Inteface %s", cid_str, ipaddress, result.ifname);
      result.addresses = ipaddress;
      result.dnses= getDNSList(result.ifname);
      result.gateways= getGateway(result.ifname);
      if(strlen(result.addresses) > 0)
       result.active = 2;
      RIL_onRequestComplete(token, RIL_E_SUCCESS, &result, sizeof(result));
      return;
    }
    else if(err == 0)// if the same data profile is active and APN is changed, deactive it
    {
      LOGD("Data profile %d change APN from %s to %s, deactive cid %s firstly", profile, g_datacalls[profile].apn, apn, cid_str);
      sprintf(cmdString, "AT+CGACT=0,%s", cid_str);
      at_send_command_timeout(cmdString, NULL, TIMEOUT_CGACT_DEACT);
      sleep(3); //Workaround: it seems CP need sometime to clear the previous PDP context before reactiving it
    }
    /* Step1: Define the CID */
    sprintf(cmdString, "AT+CGDCONT=%s,"%s","%s"", cid_str, protocol, apn );  
    err = at_send_command(cmdString, &p_response);
    if (err < 0 || p_response->success == 0)
    {
      LOGW("Fail to define the PDP context: %s", cid_str);
      sprintf(cmdString, "AT+CGACT=0,%s", cid_str);
      at_send_command_timeout(cmdString, NULL, TIMEOUT_CGACT_DEACT);
      goto error;
    }
    at_response_free(p_response);
    p_response = NULL;
    /* Step2: set PPP auth parameters for direct IP type*/
    if (!is_ppp)
    {
      if(auth_type == 3) //PAP /CHAP may be performed - baseband dependent.
       auth_type = 1; //use PAP as default
      sprintf(cmdString, "AT*AUTHReq=%s,%d,%s,%s", cid_str, auth_type, user ? user : "", passwd ? passwd : "");
      at_send_command(cmdString, NULL);
    }
    /* Step3: Active the PDP Context */
    sprintf(cmdString, "AT+CGDATA="%s",%s", is_ppp ? "PPP" : "", cid_str); // 进入数据模式(结束)
    .....
    }




  • 相关阅读:
    注册页面
    JDBC操作MySQL数据
    音乐播放页面控制
    mysql知识点
    国内第一篇详细讲解hadoop2的automatic HA+Federation+Yarn配置的教程
    让自己变得更有钱
    看视频也能拿到月薪1万
    超人学院二期学员分享hadoop工作经验
    2013年吴超的个人总结
    国内最全最详细的hadoop2.2.0集群的MapReduce的最简单配置
  • 原文地址:https://www.cnblogs.com/liulaolaiu/p/11744500.html
Copyright © 2011-2022 走看看