Android 飛行模式筆記(一)

首先,在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接口的實現者是BaseCommandsRIL.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();

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章