In front, we analyzed the initialization of dctracker, we have seen, in the Dctracker construction method, the call has the following method
private void Registerforallevents () {mPhone.mCi.registerForAvailable (this, dctconstants.event_radio_available, null
);
MPhone.mCi.registerForOffOrNotAvailable (this, dctconstants.event_radio_off_or_not_available, null);
MPhone.mCi.registerForDataNetworkStateChanged (this, dctconstants.event_data_state_changed, null); Note, this is fragile-the Phone are now presenting a merged picture//of PS (VoLTE) & CS and by diving into I TS Internals You ' re just seeing//the CS data. This works well for the purposes, this is currently used for/-but that may and not always being the case.
Should probably is redesigned to//accurately reflect what we ' re really interested in (registerforcsvoicecallended).
Mphone.getcalltracker (). registerforvoicecallended (this, dctconstants.event_voice_call_ended, null);
Mphone.getcalltracker (). registerforvoicecallstarted (this, dctconstants.event_voice_call_started, null); REgisterservicestatetrackerevents ();
Subscriptionmanager.registerforddsswitch (this,//dctconstants.event_clean_up_all_connections, NULL);
MPhone.mCi.registerForPcoData (this, dctconstants.event_pco_data_received, null); }
Where there are calls to the Registerservicestatetrackerevents method
public void Registerservicestatetrackerevents () {///Leo, registering dataconnectionattached message Mphone.getservicestatetracker ().
Registerfordataconnectionattached (this, dctconstants.event_data_connection_attached, null); Mphone.getservicestatetracker (). registerfordataconnectiondetached (This, dctconstants.event_data_connection_det
ached, NULL);
Mphone.getservicestatetracker (). Registerfordataroamingon (this, dctconstants.event_roaming_on, null);
Mphone.getservicestatetracker (). Registerfordataroamingoff (this, dctconstants.event_roaming_off, null); Mphone.getservicestatetracker (). registerforpsrestrictedenabled (This, dctconstants.event_ps_restrict_enabled, n
ULL); Mphone.getservicestatetracker (). registerforpsrestricteddisabled (This, dctconstants.event_ps_restrict_disabled,
NULL); Mphone.getservicestatetracker (). registerfordataregstateorratchanged (This, dctconstants.event_data_rat_changed, NULL);
}
In this way, the current dctracker and Servicestatetracker are bound together, we look at the first registration message event_data_connection_attached, then how does he activate receiving it?
I'm going to analyze the servicestatetracker. After the SIM card information is loaded, Servicestatetracker emits a event_sim_ready message, which is then processed
Case Event_sim_ready:
//Reset The mprevioussubid so we treat a SIM power bounce
//As a first boot. See b/19194287
MOnSubscriptionsChangedListener.mPreviousSubId.set ( -1);
Pollstate ();
Signal strength polling stops when radio is off
queuenextsignalstrengthpoll ();
Break
Well, the Pollstate method was called
public void Pollstate () {
pollstate (false);
}
public void Pollstate (Boolean modemtriggered) {mpollingcontext = new int[1];
Mpollingcontext[0] = 0; Switch (mci.getradiostate ()) {... default://Issue all poll-related commands at once the
n count down the responses, which//is allowed to arrive out-of-order mpollingcontext[0]++;
Mci.getoperator (Obtainmessage (Event_poll_state_operator, Mpollingcontext));
mpollingcontext[0]++;
Mci.getdataregistrationstate (Obtainmessage (Event_poll_state_gprs, Mpollingcontext));
mpollingcontext[0]++;
Mci.getvoiceregistrationstate (Obtainmessage (event_poll_state_registration, Mpollingcontext));
if (mphone.isphonetypegsm ()) {mpollingcontext[0]++; Mci.getnetworkselectionmode (Obtainmessage (Event_poll_state_network_selection_mode, MPollingContex
t));
} break;
}}
As you can see, the Getoperator,getdataregistrationstate and Getvoiceregistrationstate methods of the Ril class are called, respectively, for these three methods, Let's focus on the Getdataregistrationstate method, notice that the parameter passed in is a message object, and what the Message object is, Event_poll_state_gprs, Obj is a Mpollingcontext object
Next look at the Getdataregistrationstate method of the Ril class
public void
getdataregistrationstate (Message result) {
rilrequest rr
= Rilrequest.obtain (ril_request_ Data_registration_state, result);
if (RILJ_LOGD) Riljlog (rr.serialstring () + ">" + requesttostring (rr.mrequest));
Send (RR);
}
Well, from the previous articles, we know that this method is actually interacting with the underlying RIL, and sending ril_request_data_registration_state messages, and processing the results of the modem layer feedback in the Ril class, The incoming message Message object is then sent, as to exactly how it is passed, and subsequent re-analysis, so
Case Event_poll_state_registration: Case
Event_poll_state_gprs: Case
event_poll_state_operator:
ar = ( AsyncResult) Msg.obj;
Handlepollstateresult (Msg.what, AR);
Break
Called the Handlepollstateresult method, where parameter one is the message what, parameter two is the data of the modem layer feedback
protected void Handlepollstateresult (int what, AsyncResult ar) {
...
mpollingcontext[0]--;
if (mpollingcontext[0] = = 0) {
if (mphone.isphonetypegsm ()) {
updateroamingstate ();
Mnewss.setemergencyonly (memergencyonly);
} else {
...
}
Pollstatedone ();
}
}
Set the status information for the SIM card network and call the Pollstatedone method
private void Pollstatedone () {
if (mphone.isphonetypegsm ()) {
pollstatedonegsm ();
} else if ( MPHONE.ISPHONETYPECDMA ()) {
POLLSTATEDONECDMA ();
} else {
pollstatedonecdmalte ();
}
}
Because the SIM card is in GSM format
private void pollstatedonegsm () {
...
Boolean hasgprsattached =
mss.getdataregstate ()! = Servicestate.state_in_service
&& Mnewss.getdataregstate () = = Servicestate.state_in_service;
......
if (hasgprsattached) {
mattachedregistrants.notifyregistrants ();
}
if (hasgprsdetached) {
mdetachedregistrants.notifyregistrants ();
}
......
}
Therefore, the DATA attached message is sent here, and because in Dctracker, the event_data_connection_attached message is added to the mattachedregistrants, The Dctracker receives the event_data_connection_attached message and processes
Case dctconstants.event_data_connection_attached:
ondataconnectionattached ();
Break
Calling the Ondataconnectionattached method
private void ondataconnectionattached () {
if (DBG) log ("ondataconnectionattached");
Leo, set to True
Mattached.set (true);
Leo, conditions are not established
if (getoverallstate () = = DctConstants.State.CONNECTED) {
if (DBG) log ("Ondataconnectionattached: Start polling notify attached ");
Startnetstatpoll ();
Startdatastallalarm (data_stall_not_suspected);
Notifydataconnection (phone.reason_data_attached);
} else {
//Leo, will go directly to else, set the reason for its application dataconnection to reason_data_attached
//update APN availability so APN can be enabled.
Notifyoffapnsofavailability (phone.reason_data_attached);
}
if (mautoattachoncreationconfig) {
//Leo, set to True
Mautoattachoncreation.set (true);
}
Leo, finally call this method
Setupdataonconnectableapns (phone.reason_data_attached);
}
As can be seen above, there are several places set to true, combined with the initialization of the previous dataconnection, we know that these two parameters formally affect the conditions established by DataConnection
Finally, the Setupdataonconnectableapns method is called
private void Setupdataonconnectableapns (String reason) {
Setupdataonconnectableapns (reason, retryfailures.always);
}
private void Setupdataonconnectableapns (String reason, Retryfailures retryfailures) {
...
if (apncontext.isconnectable ()) {
log ("isconnectable () call Trysetupdata");
Apncontext.setreason (reason);
Trysetupdata (Apncontext, Waitingapns);
}
}
Apncontext.isconnectable () return value is true, please analyze it yourself
OK, back to the Trysetupdata method.
Private Boolean Trysetupdata (Apncontext apncontext, arraylist<apnsetting> Waitingapns) {...//all
ow setup_data request for E-APN to being completed during emergency call//and MOBILE DATA on/off cases as well.
Boolean ISEMERGENCYAPN = Apncontext.getapntype (). Equals (phoneconstants.apn_type_emergency);
Final Servicestatetracker SST = Mphone.getservicestatetracker ();
Set to False if APN type was non-metered or if we have a restricted (priveleged)/Request for the network. Todo-may want restricted requests to only apply to carrier-limited data access//rather than applying to
User limited as well. Exclude DUN for the purposes of the override until we get finer grained//intention in Networkrequests Boolean
checkuserdataenabled = Apnsetting.ismeteredapntype (Apncontext.getapntype (), Mphone.getcontext (),
Mphone.getsubid (), Mphone.getservicestate (). getdataroaming ()) && Apncontext.hasnorestrictedrequests (True/*exclude DUN */);
Dataallowfailreason Failurereason = new Dataallowfailreason (); Allow data if currently in roaming service, roaming setting disabled//and requested APN type was non-metered for R
Oaming.
Boolean isdataallowed = isdataallowed (Failurereason) | | (Failurereason.isfailforsinglereason (dataallowfailreasontype.roaming_disabled) &&! (Apnsetting.ismeteredapntype (Apncontext.getapntype (), Mphone.getcontext (), Mphone.getsubid (), MPhone.getServic
EState (). getdataroaming ()));
if (Apncontext.isconnectable () && (ISEMERGENCYAPN | | (isdataallowed && isdataallowedforapn (apncontext) && mdataenabledsettings.isdataenable
D (checkuserdataenabled) &&!isemergency ())) {if (apncontext.getstate () = = DctConstants.State.FAILED) { String str = "Trysetupdata:make a FAILED apncontext IDLE so its reUsable ";
if (DBG) log (str);
Apncontext.requestlog (str);
Apncontext.setstate (DctConstants.State.IDLE);
} int radiotech = Mphone.getservicestate (). Getrildataradiotechnology ();
Apncontext.setconcurrentvoiceanddataallowed (sst.isconcurrentvoiceanddataallowed ()); if (apncontext.getstate () = = DctConstants.State.IDLE) {if (Waitingapns = = null) {Waitingapns
= Buildwaitingapns (Apncontext.getapntype (), Radiotech);
} if (Waitingapns.isempty ()) {Notifynodata (DCFAILCAUSE.MISSING_UNKNOWN_APN, Apncontext);
Notifyoffapnsofavailability (Apncontext.getreason ());
String str = "trysetupdata:x No APN found Retvalue=false";
if (DBG) log (str);
Apncontext.requestlog (str);
return false;
} else {Apncontext.setwaitingapns (Waitingapns);
if (DBG) { Log ("Trysetupdata:create from mallapnsettings:" + apnlisttostring (MALLAPN
Settings));
}}} Boolean retvalue = SetupData (Apncontext, Radiotech);
Notifyoffapnsofavailability (Apncontext.getreason ());
if (DBG) log ("Trysetupdata:x retvalue=" + retvalue);
return retvalue; } else {...}}
Because the previous in the Ondataconnectionattached method, the two value is set to True, the isdataallowed return value here is true, so the code will go as above
The SetupData method is eventually called to build the DataConnection
Private Boolean SetupData (Apncontext apncontext, int radiotech) {if (DBG) log ("setupdata:apncontext=" + apncontext);
Apncontext.requestlog ("SetupData");
Apnsetting apnsetting;
Dcasyncchannel DCAC = null;
apnsetting = Apncontext.getnextapnsetting ();
if (apnsetting = = null) {if (DBG) log ("Setupdata:return for no APN found!");
return false;
} int profileid = Apnsetting.profileid;
if (profileID = = 0) {profileID = Getapnprofileid (Apncontext.getapntype ()); }//On CDMA, if we ' re explicitly asking for DUN, we need has//a dun-profiled connection so we can ' t share an
Existing one//on Gsm/lte we can share existing APN connections provided they support//this type.
if (Apncontext.getapntype ()! = Phoneconstants.apn_type_dun | |
Teardownfordun () = = False) {DCAC = Checkforcompatibleconnectedapncontext (Apncontext); if (DCAC! = null) {//Get the dcacapnsetting for The connection we want to share.
Apnsetting dcacapnsetting = Dcac.getapnsettingsync ();
if (dcacapnsetting! = null) {//Setting is good, so use it.
apnsetting = dcacapnsetting; }}} if (DCAC = = null) {if (isonlysingledcallowed (Radiotech)) {if (ishigherpriority Apncontextactive (Apncontext)) {if (DBG) {log ("Setupdata:higher priority Apncontext Active.
Ignoring call ");
} return false; }//Only lower-calls left. Disconnect them all on this a PDP case//So, we can bring up the requested higher priority call (ONC E we receive//response for deactivate request for the calls we is about-disconnect if (clean Upallconnections (True, phone.reason_single_pdn_arbitration)) {//If any call actually requested to be dis ConnectEd, means we can ' t//Bring up this connection yet as we need to wait for those data calls
To is disconnected. if (DBG) log ("Setupdata:some calls is disconnecting first.
Wait and retry ");
return false; }//No Other calls is active, so proceed if (DBG) log ("Setupdata:single PDP.
Continue setting up data call. ");
DCAC = Findfreedataconnection ();
if (DCAC = = null) {DCAC = Createdataconnection (); if (DCAC = = null) {if (DBG) log ("Setupdata:no free dataconnection and couldn ' t create one, WEIRD"
);
return false;
}} final int generation = Apncontext.incandgetconnectiongeneration ();
if (DBG) {log ("setupdata:dcac=" + DCAC + "apnsetting=" + apnsetting + "gen#=" + Generation);
} Apncontext.setdataconnectionac (DCAC);
Apncontext.setapnsetting (apnsetting); ApnContext.setstate (DctConstants.State.CONNECTING);
Mphone.notifydataconnection (Apncontext.getreason (), Apncontext.getapntype ());
Message msg = Obtainmessage ();
Msg.what = Dctconstants.event_data_setup_complete;
Msg.obj = new Pair<apncontext, integer> (Apncontext, Generation);
Dcac.bringup (Apncontext, profileID, Radiotech, MSG, Generation);
if (DBG) log ("setupdata:initing!");
return true; }
The analysis concludes that, finally, by calling the Createdataconnection method, the new Dcasyncchannel object
Private Dcasyncchannel createdataconnection () {
if (DBG) log ("Createdataconnection E");
int id = muniqueidgenerator.getandincrement ();
DataConnection conn = Dataconnection.makedataconnection (Mphone, id, this
, Mdctesterfailbringupall, MDCC);
Mdataconnections.put (ID, conn);
Dcasyncchannel DCAC = new Dcasyncchannel (conn, log_tag);
int status = Dcac.fullyconnectsync (Mphone.getcontext (), this, Conn.gethandler ());
if (status = = asyncchannel.status_successful) {
mdataconnectionachashmap.put (Dcac.getdataconnectionidsync (), DCAC);
} else {
Loge ("Createdataconnection:could not connect to dcac=" + DCAC + "status=" + status);
}
if (DBG) log ("Createdataconnection () X id=" + ID + "dc=" + conn);
return DCAC;
}
Create a new DataConnection by DataConnection's Makedataconnection method.
To this point, DataConnection has been established