首先,在PhoneApp中,有个Receiver接受到来Intent
/**
*Receiver for misc intent broadcasts the Phone app caresabout.
*/
private class PhoneAppBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action =intent.getAction();
if(action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)){
boolean enabled = System.getInt(getContentResolver(),
System.AIRPLANE_MODE_ON,0) == 0;
phone.setRadioPower(enabled);
}
然后进入 PhoneProxy.java
private Phone mActivePhone;
public void setRadioPower(boolean power) {
mActivePhone.setRadioPower(power);
}
然后进入 GsmPhone.java中
GsmServiceStateTracker mSST;
public void setRadioPower(boolean power) {
mSST.setRadioPower(power);
}
然后进入GsmServiceStateTracker.java(ServiceStateTracker.java)
在ServiceStateTracker.java中,
protected abstract voidsetPowerStateToDesired();
public void setRadioPower(boolean power) {
mDesiredPowerState= power;
setPowerStateToDesired();
}
在gsmServiceStateTracker.java中
protected CommandsInterface cm;
protected boolean mDesiredPowerState;
protected void setPowerStateToDesired() {
//If we want it on and it's off, turn it on
if(mDesiredPowerState && cm.getRadioState()== CommandsInterface.RadioState.RADIO_OFF){
cm.setRadioPower(true,null);
} elseif(!mDesiredPowerState&& cm.getRadioState().isOn()){
DataConnectionTrackerdcTracker = phone.mDataConnection;
if(! dcTracker.isDataConnectionAsDesired()) {
EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
dcTracker.getStateInString(),dcTracker.getAnyDataEnabled() ? 1 : 0);
}
//If it's on and available and we want it off gracefully
powerOffRadioSafely();
} //Otherwise, we're in the desired state
}
对于cm.getRadioState(),其中cm接口的实现者是BaseCommands和 RIL.java
前者实现了部分接口,后者实现来其他接口,定义如下
publicabstractclassBaseCommands implementsCommandsInterface
publicfinalclassRIL extendsBaseCommands implementsCommandsInterface
而cm.getRadioState()则跳跃到BaseCommands中
然后执行
@Override
protected void powerOffRadioSafely() {
//clean data connection
DataConnectionTracker dcTracker= phone.mDataConnection;
Message msg =dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
msg.arg1= 1; // tearDown is true
msg.obj= GSMPhone.REASON_RADIO_TURNED_OFF;
dcTracker.sendMessage(msg);
//poll data state up to 15 times, with a 100ms delay
//totaling 1.5 sec.Normal data disable action will finish in 100ms.
for(int i = 0; i < MAX_NUM_DATA_STATE_READS;i++) {
if(dcTracker.getState() != DataConnectionTracker.State.CONNECTED
&&dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING){
Log.d(LOG_TAG,"Data shutdown complete.");
break;
}
SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
}
//hang up all active voice calls
if(phone.isInCall()){
phone.mCT.ringingCall.hangupIfAlive();
phone.mCT.backgroundCall.hangupIfAlive();
phone.mCT.foregroundCall.hangupIfAlive();
}
cm.setRadioPower(false,null);
}
最后在RIL.java中通过发送RILRequest来关闭Radio
public void setRadioPower(boolean on, Message result) {
//ifradio is OFF set preferred NW type and cmdasubscription
if(mInitialRadioStateChange){
synchronized(mStateMonitor){
if(!mState.isOn()){
RILRequest rrPnt =RILRequest.obtain(
RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,null);
rrPnt.mp.writeInt(1);
rrPnt.mp.writeInt(mNetworkMode);
if(RILJ_LOGD)riljLog(rrPnt.serialString() + ">"
+requestToString(rrPnt.mRequest)+ " : "+ mNetworkMode);
send(rrPnt);
RILRequest rrCs =RILRequest.obtain(
RIL_REQUEST_CDMA_SET_SUBSCRIPTION,null);
rrCs.mp.writeInt(1);
rrCs.mp.writeInt(mCdmaSubscription);
if(RILJ_LOGD)riljLog(rrCs.serialString() + ">"
+requestToString(rrCs.mRequest)+ " : "+ mCdmaSubscription);
send(rrCs);
}
}
}
RILRequest rr=RILRequest.obtain(RIL_REQUEST_RADIO_POWER,result);
rr.mp.writeInt(1);
rr.mp.writeInt(on? 1 : 0);
if(RILJ_LOGD)riljLog(rr.serialString() + "> "+ requestToString(rr.mRequest));
send(rr);
}
其中send(rr)为
private void send(RILRequest rr) {
Message msg;
msg =mSender.obtainMessage(EVENT_SEND,rr);
acquireWakeLock();
msg.sendToTarget();
}
最后通过RILReceiver来监听状态RIL.java中
class RILReceiver implements Runnable {
byte[]buffer;
RILReceiver() {
buffer= new byte[RIL_MAX_COMMAND_BYTES];
}
public void run() {
intretryCount = 0;
try{for(;;) {
LocalSocket s = null;
LocalSocketAddress l;
try{
s = newLocalSocket();
l = newLocalSocketAddress(SOCKET_NAME_RIL,
LocalSocketAddress.Namespace.RESERVED);
s.connect(l);
} catch(IOException ex){
try{
if(s != null){
s.close();
}
} catch(IOException ex2) {
//ignorefailure to close after failure to connect
}
//don't print an error message after the the first time
//or after the 8th time
if(retryCount == 8) {
Log.e(LOG_TAG,
"Couldn'tfind '" + SOCKET_NAME_RIL
+ "'socket after " + retryCount
+ "times, continuing to retry silently");
} else if(retryCount > 0 && retryCount < 8) {
Log.i(LOG_TAG,
"Couldn'tfind '" + SOCKET_NAME_RIL
+ "'socket; retrying after timeout");
}
try{
Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
} catch(InterruptedException er) {
}
retryCount++;
continue;
}
retryCount = 0;
mSocket= s;
Log.i(LOG_TAG,"Connected to '"+ SOCKET_NAME_RIL+ "' socket");
intlength = 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);
//Log.v(LOG_TAG,"Read packet: " + length + " bytes");
processResponse(p);
p.recycle();
}
} catch(java.io.IOException ex) {
Log.i(LOG_TAG,"'"+ SOCKET_NAME_RIL+ "' socket closed",
ex);
} catch(Throwable tr) {
Log.e(LOG_TAG,"Uncaught exception read length="+ length +
"Exception:"+ tr.toString());
}
Log.i(LOG_TAG,"Disconnected from '"+ SOCKET_NAME_RIL
+ "'socket");
setRadioState(RadioState.RADIO_UNAVAILABLE);
try{
mSocket.close();
} catch(IOException ex) {
}
mSocket= null;
RILRequest.resetSerial();
//Clear request list on close
synchronized(mRequestsList){
for(int i = 0, sz = mRequestsList.size(); i < sz ; i++) {
RILRequest rr =mRequestsList.get(i);
rr.onError(RADIO_NOT_AVAILABLE,null);
rr.release();
}
mRequestsList.clear();
}
}} catch(Throwable tr) {
Log.e(LOG_TAG,"Uncaughtexception", tr);
}
}
}
其中RIL.java中
private void processResponse (Parcel p) {
int type;
type = p.readInt();
if(type == RESPONSE_UNSOLICITED){
processUnsolicited (p);
} else if(type == RESPONSE_SOLICITED){
processSolicited (p);
}
releaseWakeLockIfDone();
}