Android携帯電話の信号強度


Android携帯電話では、「設定」-「携帯電話について」-「状態」-「信号強度」で携帯電話の信号強度が表示され、「-87 dBm 13 asu」のようなデータが表示されます.ASUとdBmの関係は、dBm=−113+(2*ASU)である.
あなたの携帯電話の画面に表示される信号バーは、どんな携帯電話を使っても同じように、あなたの携帯電話の信号を確定する最善の方法ではありません.Androidも、太いバーで強い信号を示していますが、これらのバーは最高の信号だけを表しています.よく知らないかもしれませんが、信号は通常dBmで測定されます.dBmはミリワット当たりの電磁波発生電力である.-60 dBmの信号が完璧に近づくと、-112 dBmはオフラインになりやすく、-87 dBm以上になるとAndroidは4グリッドのフル信号を表示します.
AndroidインタフェースUI信号表示は、RILが通信モジュールに対してATコマンドを送信ことによって実現する、例えばAT+CSQである、我々は一般的にlogcat-b radioによってRILのリアルタイム情報を取得することができ、キーワード「CSQ」によってradioを検索することができることを確認する.log、携帯電話の信号強度を確認します.logは、AT<+CSQ:14,99ここでの14がASU値である、4.0ソースコードにSignalStrengthがある.JAvaクラスでは、ASU値をいくつかのグリッド信号に変換する方法があります.
403
    public int getGsmLevel() {
404
        int level;
405
 
406
        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
407
        // asu = 0 (-113dB or less) is very weak
408
        // signal, its better to show 0 bars to the user in such cases.
409
        // asu = 99 is a special case, where the signal strength is unknown.
410
        int asu = getGsmSignalStrength();
411
        if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
412
        else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
413
        else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;
414
        else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;
415
        else level = SIGNAL_STRENGTH_POOR;
416
        if (DBG) log("getGsmLevel=" + level);
417
        return level;
418
    }

-----------------------------------------------------------------------------------------
以下はネットで見つけた関連資料です.
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のサブクラスは、サービスとしてsystem_で実行されますサーバプロセスでは、登録者に通知されます.上のDefaultPhoneNotifierはcomで実行されます.android.phoneプロセスでは,信号強度値が変化するとサービスにより通知(サービスは関心のある登録者によって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);
    }

TelephonyManagerでJAvaにはAPIが提供されており、アプリケーションは様々なイベントをリスニングすることができ、実際には興味のあるリスニング者をサービス側のリスト(プロセス間)にレコードとして追加し、変更がある場合は、提供されたコールバック関数を呼び出して登録者に通知します(プロセス間).
TelephonyManager.JAvaのlisten関数は次のとおりです.
    public void listen(PhoneStateListener listener, int events) {
        String pkgForDebug = mContext != null ? mContext.getPackageName() : “”;
        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では、次のリスニング処理するイベントが登録されています.2つ目は信号強度です.
 ((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();上層部に知らせ、同じ流れに進む
転入先http://blog.csdn.net/pierce0young/article/details/9294119