移动数据流程

来源:互联网 发布:数据挖掘从应用心得 编辑:程序博客网 时间:2024/05/16 05:05
移动数据流程 该文摘自网友,留作以便查阅
切入点,setting 中 ”启用移动数据“
1: Settings.java (packages\apps\phone\src\com\android\phone)
    开始点击启用移动数据的按钮   
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        addPreferencesFromResource(R.xml.network_setting);
        ....
        mButtonDataEnabled = (CheckBoxPreference) prefSet.findPreference(BUTTON_DATA_ENABLED_KEY); // 启动移动数据的按钮
2:  Settings.java (packages\apps\phone\src\com\android\phone)
       点击启用移动数据  执行代码:  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 (frameworks\base\core\java\android\net)       
       调用 setMobileDataEnabled 函数
        public void setMobileDataEnabled(boolean enabled) {   // setMobileDataEnabled 函数
        try {
            mService.setMobileDataEnabled(enabled);  // 调用 ConnectivityService.java 中的 setMobileDateEnabled 函数
        } catch (RemoteException e) {
        }
        }        
4:  ConnectivityService.java (frameworks\base\services\java\com\android\server) 
       调用 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 (frameworks\base\services\java\com\android\server)
    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 (frameworks\base\services\java\com\android\server)
     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 (frameworks\base\core\java\android\net) 
     调用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 (frameworks\base\telephony\java\com\android\internal\telephony)
    接收消息并处理 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 (frameworks\base\telephony\java\com\android\internal\telephony)
     调用 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 (frameworks\base\telephony\java\com\android\internal\telephony\gsm)       
       调用onTrySetupData 函数 
    protected boolean onTrySetupData(String reason) {  //onTrySetupData 函数
        if (DBG) log("onTrySetupData: reason=" + reason);
        setupDataOnReadyApns(reason); // 调用setupDataOnReadyApns 函数  检查APN 列表
        return true;
    }   
11:GsmDataConnectionTracker.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)
      调用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 (frameworks\base\telephony\java\com\android\internal\telephony\gsm)   
       调用 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 (frameworks\base\telephony\java\com\android\internal\telephony)  (与流程无关)
    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 (frameworks\base\telephony\java\com\android\internal\telephony\gsm)
     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 (frameworks\base\telephony\java\com\android\internal\telephony)
       bringUp 函数
       
        public void bringUp(Message onCompletedMsg, ApnSetting apn) {
        sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg))); // 发送EVENT_CONNECT 事件
    }    
16  DataConnection.java (frameworks\base\telephony\java\com\android\internal\telephony)
         收到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 (frameworks\base\telephony\java\com\android\internal\telephony\gsm)
        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 (frameworks\base\telephony\java\com\android\internal\telephony) 

         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 (frameworks\base\telephony\java\com\android\internal\telephony) 
      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\ril\marvell-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\ril\marvell-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\ril\marvell-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\ril\mock-ril\src\cpp) 中RIL_DATA_PROFILE_DEFAULT=0
}
if(profile < RIL_DATA_PROFILE_DEFAULT || profile >= MAX_DATA_CALLS)
{
  LOGW("RIL_REQUEST_SETUP_DATA_CALL: Profile %d unsupportted! \n", 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); // 进入数据模式(结束)
.....
}
0 0
原创粉丝点击