android手机信号强度

来源:互联网 发布:win10网络图标不能启用 编辑:程序博客网 时间:2024/04/30 00:43

在Android手机上,通过“设置”-“关于手机”-“状态”-“信号强度”可以查看到手机的信号强度,显示出如“-87 dBm 13 asu”这样的数据。ASU与dBm之间的关系是:dBm=-113+(2*ASU)。

  在你手机屏幕上方显示的信号条永远不会是最好的方法来确定你手机的信号,无论你用什么手机都一样。Android也是,用很粗的条来展示很强的信号,但这些条仅仅表示最高的信号。或许你并不熟悉,信号通常是以dBm度量的。dBm是每毫瓦特的电磁波产生的功率。-60dBm的信号接近完美,-112dBm就很容易掉线,如果你在 -87dBm以上,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值转换为几格信号的方法:


[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. 403  
  2.     public int getGsmLevel() {  
  3. 404  
  4.         int level;  
  5. 405  
  6.    
  7. 406  
  8.         // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5  
  9. 407  
  10.         // asu = 0 (-113dB or less) is very weak  
  11. 408  
  12.         // signal, its better to show 0 bars to the user in such cases.  
  13. 409  
  14.         // asu = 99 is a special case, where the signal strength is unknown.  
  15. 410  
  16.         int asu = getGsmSignalStrength();  
  17. 411  
  18.         if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;  
  19. 412  
  20.         else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;  
  21. 413  
  22.         else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;  
  23. 414  
  24.         else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;  
  25. 415  
  26.         else level = SIGNAL_STRENGTH_POOR;  
  27. 416  
  28.         if (DBG) log("getGsmLevel=" + level);  
  29. 417  
  30.         return level;  
  31. 418  
  32.     }  


-----------------------------------------------------------------------------------------

以下是从网上找到的相关资料。

  在RILConstants.java中找到:

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. int RIL_UNSOL_SIGNAL_STRENGTH = 1009;  



在RIL.java中找到与其相关的代码:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private void processUnsolicited (Parcel p) {  
  2. …….  
  3. case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;  
  4. …..  
  5. case RIL_UNSOL_SIGNAL_STRENGTH:  
  6. // Note this is set to “verbose” because it happens  
  7. // frequently  
  8. if (RILJ_LOGV) unsljLogvRet(response, ret);  
  9.   
  10. if (mSignalStrengthRegistrant != null) {  
  11. mSignalStrengthRegistrant.notifyRegistrant(  
  12. new AsyncResult (null, ret, null));  
  13. }  



在RIL的父类BaseCommands.java中找到:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public void setOnSignalStrengthUpdate(Handler h, int what, Object obj) {  
  2. <span style="white-space:pre">  </span>mSignalStrengthRegistrant = new Registrant (h, what, obj);  
  3. }  



再找其调用者(GsmServiceStateTracker.java):
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public GsmServiceStateTracker(GSMPhone phone) {  
  2. super();  
  3.   
  4. ……  
  5. cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);  
  6. ……  



GsmServiceStateTracker自己处理上报上来的信号强度信息:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. case EVENT_SIGNAL_STRENGTH_UPDATE:  
  2. // This is a notification from  
  3. // CommandsInterface.setOnSignalStrengthUpdate  
  4.   
  5. ar = (AsyncResult) msg.obj;  
  6.   
  7. // The radio is telling us about signal strength changes  
  8. // we don’t have to ask it  
  9. dontPollSignalStrength = true;  
  10.   
  11. onSignalStrengthResult(ar);  
  12. break;  



函数onSignalStrengthResult负责处理:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private void onSignalStrengthResult(AsyncResult ar) {  
  2.         SignalStrength oldSignalStrength = mSignalStrength;  
  3.         int rssi = 99;  
  4.   
  5.   
  6.         if (ar.exception != null) {  
  7.          // -1 = unknown  
  8.         // most likely radio is resetting/disconnected  
  9.             setSignalStrengthDefaultValues();  
  10.         } else {  
  11.             int[] ints = (int[]) ar.result;  
  12.   
  13.   
  14.         // bug 658816 seems to be a case where the result is 0-length  
  15.             if (ints.length != 0) {  
  16.                 rssi = ints[0];  
  17.             } else {  
  18.                 Log.e(LOG_TAG, “Bogus signal strength response”);  
  19.                 rssi = 99;  
  20.             }  
  21.         }  
  22.   
  23.   
  24.         mSignalStrength = new SignalStrength(rssi, -1, -1, -1,  
  25.                 -1, -1, -1true);  
  26.   
  27.   
  28.         if (!mSignalStrength.equals(oldSignalStrength)) {  
  29.             try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after  
  30.                   // POLL_PERIOD_MILLIS) during Radio Technology Change)  
  31.                 phone.notifySignalStrength();  
  32.             } catch (NullPointerException ex) {  
  33.                 log(“onSignalStrengthResult()Phone already destroyed:”+ex  
  34.                         +“SignalStrength not notified”);  
  35.             }  
  36.         }  
  37.     }  



若没发生异常,且值产生变化,则调用 phone.notifySignalStrength通知(见GSMPhone.java):
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. notifySignalStrength() {  
  2.         mNotifier.notifySignalStrength(this);  
  3.     }  
  4.   
  5.   
  6.     DefaultPhoneNotifier(DefaultPhoneNotifier.java)通知注册者:  
  7.   
  8.   
  9.     public void notifySignalStrength(Phone sender) {  
  10.         try {  
  11.             mRegistry.notifySignalStrength(sender.getSignalStrength());  
  12.         } catch (RemoteException ex) {  
  13. // system process is dead  
  14.         }  
  15.     }  


这个注册者来自:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. DefaultPhoneNotifier() {  
  2.         mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry));  
  3.     }  


TelephonyRegistry.java,TelephonyRegistry是ITelephonyRegistry.Stub的子类,作为service运行在system_server进程中,它会通知注册者。上面的DefaultPhoneNotifier运行在com.android.phone进程中,当信号强度值变化时,通过Service进行通知(service被感兴趣的注册者调用了listen,添加了回调函数。
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1.  public void notifySignalStrength(SignalStrength signalStrength) {  
  2.         if (!checkNotifyPermission(“notifySignalStrength()”)) {  
  3.             return;  
  4.         }  
  5.         synchronized (mRecords) {  
  6.             mSignalStrength = signalStrength;  
  7.             for (int i = mRecords.size()–1;  
  8.             i >= 0;  
  9.             i–){  
  10.                 Record r = mRecords.get(i);  
  11.                 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {  
  12.                     sendSignalStrength(r, signalStrength);  
  13.                 }  
  14.                 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {  
  15.                     try {  
  16.                         int gsmSignalStrength = signalStrength.getGsmSignalStrength();  
  17.                         r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1  
  18.                                 : gsmSignalStrength));  
  19.                     } catch (RemoteException ex) {  
  20.                         remove(r.binder);  
  21.                     }  
  22.                 }  
  23.             }  
  24.         }  
  25.         broadcastSignalStrengthChanged(signalStrength);  
  26.     }  



在TelephonyManager.java中提供了API,应用程序可以监听各种事件,实际上它将感兴趣的监听者作为一条记录添加到service一侧的列表(跨进程)中,当有变化时,调用它们提供的回调函数,通知(跨进程)这些注册者。
TelephonyManager.java中的listen函数如下:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public void listen(PhoneStateListener listener, int events) {  
  2.     String pkgForDebug = mContext != null ? mContext.getPackageName() : “<unknown>”;  
  3.     try {  
  4.         Boolean notifyNow = (getITelephony() != null);  
  5.         mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);  
  6.     } catch (RemoteException ex) {  
  7.         // system process dead  
  8.     } catch (NullPointerException ex) {  
  9.         // system process dead  
  10.     }  
  11. }  


其中回调对象实例listener.callback来自于PhoneStateListener.java嵌套定义及其实例,这样,当TelephonyRegistry.java调用回调函数时,就调用到listener.callback,进而发送消息给PhoneStateListener.java中的mHandler,由其处理,进而由其子类去处理。

在StatusBarPolicy.java中,注册了下面要监听处理的事件。第二个为信号强度:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE)). listen(mPhoneStateListener,  
  2.           PhoneStateListener.LISTEN_SERVICE_STATE  
  3.           |PhoneStateListener.LISTEN_SIGNAL_STRENGTHS  
  4.                   |PhoneStateListener.LISTEN_CALL_STATE  
  5.                   |PhoneStateListener.LISTEN_DATA_CONNECTION_STATE  
  6.                   |PhoneStateListener.LISTEN_DATA_ACTIVITY);  



处理者为:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {  
  2.         @Override  
  3.         public void onSignalStrengthsChanged(SignalStrength signalStrength) {  
  4.             mSignalStrength = signalStrength;  
  5.             updateSignalStrength();  
  6.         }  
  7.     }  



在StatusBarPolicy的updateSignalStrength函数中,将根据得到的信息,设置适当的图标id,显示合适的图标。

主动请求:

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. GsmServiceStateTracker.java  
  2. case EVENT_POLL_SIGNAL_STRENGTH:  
  3. // Just poll signal strength…not part of pollState()  
  4.   
  5. cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));  
  6. break;  


在RIL.java中,发送请求:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1.  public void  
  2.     getSignalStrength(Message result) {  
  3.         RILRequest rr  
  4.                 = RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result);  
  5.   
  6. /*if (RILJ_LOGD)*/  
  7.         riljLog(rr.serialString() + “ >”+requestToString(rr.mRequest));  
  8.   
  9.         send(rr);  
  10.     }  



请求号在RIL.java中,定义了请求号:
RIL_REQUEST_SIGNAL_STRENGTH

返回结果: processSolicited中得到结果后sendToTarget
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1.  private void processSolicited (Parcel p) {  
  2.        ...  
  3.   
  4.         case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;  
  5.   
  6.         在GsmServiceStateTracker.java中,msg的handler指定为this,所以GsmServiceStateTracker负责回送的消息的处理:  
  7.         case EVENT_GET_SIGNAL_STRENGTH:  
  8. // This callback is called when signal strength is polled  
  9. // all by itself  
  10.   
  11.         if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isCdma())) {  
  12. // Polling will continue when radio turns back on and not CDMA  
  13.             return;  
  14.         }  
  15.         ar = (AsyncResult) msg.obj;  
  16.         onSignalStrengthResult(ar);  
  17.         queueNextSignalStrengthPoll();  
  18.   
  19.         break;  
  20.   
  21.     private void onSignalStrengthResult(AsyncResult ar) {  
  22.         SignalStrength oldSignalStrength = mSignalStrength;  
  23.         int rssi = 99;  
  24.         Log.d("YCG""query done! onSignalStrengthResult");  
  25.         if (ar.exception != null) {  
  26. // -1 = unknown  
  27. // most likely radio is resetting/disconnected  
  28.             setSignalStrengthDefaultValues();  
  29.         } else {  
  30.             int[] ints = (int[])ar.result;  
  31.   
  32. // bug 658816 seems to be a case where the result is 0-length  
  33.             if (ints.length != 0) {  
  34.                 rssi = ints[0];  
  35.                 Log.d("YCG""query done! rssi="+rssi);  
  36.             } else {  
  37.                 Log.e(LOG_TAG, "Bogus signal strength response");  
  38.                 rssi = 99;  
  39.             }  
  40.         }  
  41.   
  42.         mSignalStrength = new SignalStrength(rssi, -1, -1, -1,  
  43.                 -1, -1, -1true);  
  44.   
  45.         if (!mSignalStrength.equals(oldSignalStrength)) {  
  46.             try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after  
  47. // POLL_PERIOD_MILLIS) during Radio Technology Change)  
  48.                 phone.notifySignalStrength();  
  49.             } catch (NullPointerException ex) {  
  50.                 log("onSignalStrengthResult() Phone already destroyed: " + ex  
  51.                         + "SignalStrength not notified");  
  52.             }  
  53.         }  
  54.     }  



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


转自 http://blog.csdn.NET/pierce0young/article/details/9294119
0 0
原创粉丝点击