1. 程式人生 > >Android中的訊號強度上報與顯示完整流程()

Android中的訊號強度上報與顯示完整流程()

分析:
在RILConstants.java中找到:
int RIL_UNSOL_SIGNAL_STRENGTH = 1009;

在RIL.java中找到與其相關的程式碼:
private void
processUnsolicited (Parcel p) {
…….
case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;
…..
case RIL_UNSOL_SIGNAL_STRENGTH:
// Note this is set to “verbose” because it happens
// frequently
if (RILJ_LOGV) unsljLogvRet(response, ret);

if (mSignalStrengthRegistrant != null) {
mSignalStrengthRegistrant.notifyRegistrant(
new AsyncResult (null, ret, null));
}

在RIL的父類BaseCommands.java中找到:
public void setOnSignalStrengthUpdate(Handler h, int what, Object obj) {
mSignalStrengthRegistrant = new Registrant (h, what, obj);
}

再找其呼叫者(GsmServiceStateTracker.java):
public GsmServiceStateTracker(GSMPhone phone) {


super();

……
cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
……

GsmServiceStateTracker自己處理上報上來的訊號強度資訊:
case EVENT_SIGNAL_STRENGTH_UPDATE:
// This is a notification from
// CommandsInterface.setOnSignalStrengthUpdate

ar = (AsyncResult) msg.obj;

// The radio is telling us about signal strength changes


// we don’t have to ask it
dontPollSignalStrength = true;

onSignalStrengthResult(ar);
break;

函式onSignalStrengthResult負責處理:
private void onSignalStrengthResult(AsyncResult ar) {
SignalStrength oldSignalStrength = mSignalStrength;
int rssi = 99;

if (ar.exception != null) {
// -1 = unknown
// most likely radio is resetting/disconnected
setSignalStrengthDefaultValues();
} else {
int[] ints = (int[])ar.result;

// bug 658816 seems to be a case where the result is 0-length
if (ints.length != 0) {
rssi = ints[0];
} else {
Log.e(LOG_TAG, “Bogus signal strength response”);
rssi = 99;
}
}

mSignalStrength = new SignalStrength(rssi, -1, -1, -1,
-1, -1, -1, true);

if (!mSignalStrength.equals(oldSignalStrength)) {
try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
// POLL_PERIOD_MILLIS) during Radio Technology Change)
phone.notifySignalStrength();
} catch (NullPointerException ex) {
log(“onSignalStrengthResult() Phone already destroyed: ” + ex
+ “SignalStrength not notified”);
}
}
}

若沒發生異常,且值產生變化,則呼叫 phone.notifySignalStrength通知(見GSMPhone.java):
notifySignalStrength() {
mNotifier.notifySignalStrength(this);
}

DefaultPhoneNotifier(DefaultPhoneNotifier.java)通知註冊者:
public void notifySignalStrength(Phone sender) {
try {
mRegistry.notifySignalStrength(sender.getSignalStrength());
} catch (RemoteException ex) {
// system process is dead
}
}

這個註冊者來自:
DefaultPhoneNotifier() {
mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
“telephony.registry”));
}

TelephonyRegistry.java,TelephonyRegistry是ITelephonyRegistry.Stub的子類,作為service執行在system_server程序中,它會通知註冊者。上面的DefaultPhoneNotifier執行在com.android.phone程序中,當訊號強度值變化時,通過Service進行通知(service被感興趣的註冊者呼叫了listen,添加了回撥函式。
public void notifySignalStrength(SignalStrength signalStrength) {
if (!checkNotifyPermission(“notifySignalStrength()”)) {
return;
}
synchronized (mRecords) {
mSignalStrength = signalStrength;
for (int i = mRecords.size() – 1; i >= 0; i–) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
sendSignalStrength(r, signalStrength);
}
if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
int gsmSignalStrength = signalStrength.getGsmSignalStrength();
r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
: gsmSignalStrength));
} catch (RemoteException ex) {
remove(r.binder);
}
}
}
}
broadcastSignalStrengthChanged(signalStrength);    //此處作用一,就是通知BatteryStats,mBatteryStats.notePhoneSignalStrength(signalStrength);訊號變化,開始計時,從而用來統計訊號處於這一狀態的時長。


}

在TelephonyManager.java中提供了API,應用程式可以監聽各種事件,實際上它將感興趣的監聽者作為一條記錄新增到service一側的列表(跨程序)中,當有變化時,呼叫它們提供的回撥函式,通知(跨程序)這些註冊者。
TelephonyManager.java中的listen函式如下:
public void listen(PhoneStateListener listener, int events) {
String pkgForDebug = mContext != null ? mContext.getPackageName() : “<unknown>”;
try {
Boolean notifyNow = (getITelephony() != null);
mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
} catch (RemoteException ex) {
// system process dead
} catch (NullPointerException ex) {
// system process dead
}
}
其中回撥物件例項listener.callback來自於PhoneStateListener.java巢狀定義及其例項,這樣,當TelephonyRegistry.java呼叫回撥函式時,就呼叫到listener.callback,進而傳送訊息給PhoneStateListener.java中的mHandler,由其處理,進而由其子類去處理。

在StatusBarPolicy.java中,註冊了下面要監聽處理的事件。第二個為訊號強度:
((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_CALL_STATE
| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
| PhoneStateListener.LISTEN_DATA_ACTIVITY);

處理者為:
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
mSignalStrength = signalStrength;
updateSignalStrength();
}

在StatusBarPolicy的updateSignalStrength函式中,將根據得到的資訊,設定適當的圖示id,顯示合適的圖示。

主動請求:

GsmServiceStateTracker.java
case EVENT_POLL_SIGNAL_STRENGTH:
// Just poll signal strength…not part of pollState()

cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
break;

在RIL.java中,傳送請求:
public void
getSignalStrength (Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result);

/*if (RILJ_LOGD)*/ riljLog(rr.serialString() + “> ” + requestToString(rr.mRequest));

send(rr);
}

請求號在RIL.java中,定義了請求號:
RIL_REQUEST_SIGNAL_STRENGTH

返回結果: processSolicited中得到結果後sendToTarget
private void
processSolicited (Parcel p) {
…..

case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;

在GsmServiceStateTracker.java中,msg的handler指定為this,所以GsmServiceStateTracker負責回送的訊息的處理:
case EVENT_GET_SIGNAL_STRENGTH:
// This callback is called when signal strength is polled
// all by itself

if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isCdma())) {
// Polling will continue when radio turns back on and not CDMA
return;
}
ar = (AsyncResult) msg.obj;
onSignalStrengthResult(ar);
queueNextSignalStrengthPoll();

break;

private void onSignalStrengthResult(AsyncResult ar) {
SignalStrength oldSignalStrength = mSignalStrength;
int rssi = 99;
Log.d(“YCG”, “query done! onSignalStrengthResult”);
if (ar.exception != null) {
// -1 = unknown
// most likely radio is resetting/disconnected
setSignalStrengthDefaultValues();
} else {
int[] ints = (int[])ar.result;

// bug 658816 seems to be a case where the result is 0-length
if (ints.length != 0) {
rssi = ints[0];
Log.d(“YCG”, “query done! rssi=”+rssi);
} else {
Log.e(LOG_TAG, “Bogus signal strength response”);
rssi = 99;
}
}

mSignalStrength = new SignalStrength(rssi, -1, -1, -1,
-1, -1, -1, true);

if (!mSignalStrength.equals(oldSignalStrength)) {
try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
// POLL_PERIOD_MILLIS) during Radio Technology Change)
phone.notifySignalStrength();
} catch (NullPointerException ex) {
log(“onSignalStrengthResult() Phone already destroyed: ” + ex
+ “SignalStrength not notified”);
}
}
}

phone.notifySignalStrength();通知上層,走上相同流程