Android Phone 模块3

来源:互联网 发布:淘宝耳饰 知乎 编辑:程序博客网 时间:2024/05/16 08:42

RIL


[java] view plaincopy
  1. public RIL(Context context, int preferredNetworkType, int cdmaSubscription,int phoneId) {  
  2.     super(context);  
  3.     mCdmaSubscription = cdmaSubscription;  
  4.     mPreferredNetworkType = preferredNetworkType;  
  5.     mPhoneType = RILConstants.NO_PHONE;  
  6.   
  7.     mPhoneId = phoneId;  
  8.     if (mPhoneId != PhoneFactory.DEFAULT_PHONE_ID) {  
  9.         SOCKET_NAME_RIL = SOCKET_NAME_RIL + phoneId;  
  10.     }  
  11.     PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);  
  12.     mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);  
  13.     mWakeLock.setReferenceCounted(false);  
  14.     mWakeLockTimeout = SystemProperties.getInt(TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT,DEFAULT_WAKE_LOCK_TIMEOUT);  
  15.     mRequestMessagesPending = 0;  
  16.     mRequestMessagesWaiting = 0;  
  17.     //创建ril发送线程  
  18.     mSenderThread = new HandlerThread("RILSender");  
  19.     mSenderThread.start();  
  20.     Looper looper = mSenderThread.getLooper();  
  21.     mSender = new RILSender(looper);  
  22.   
  23.     ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);  
  24.     if (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {  
  25.         riljLog("Not starting RILReceiver: wifi-only");  
  26.     } else {  
  27.         riljLog("Starting RILReceiver");  
  28.         //创建接收线程  
  29.         mReceiver = new RILReceiver();  
  30.         mReceiverThread = new Thread(mReceiver, "RILReceiver");  
  31.         mReceiverThread.start();  
  32.         IntentFilter filter = new IntentFilter();  
  33.         filter.addAction(Intent.ACTION_SCREEN_ON);  
  34.         filter.addAction(Intent.ACTION_SCREEN_OFF);  
  35.         context.registerReceiver(mIntentReceiver, filter);  
  36.     }  
  37. }  
RIL线程模型:

RILSender

当上层需要向rild服务发送请求时,通过RIL的send函数来完成。
[java] view plaincopy
  1. public void handleMessage(Message msg) {  
  2.     RILRequest rr = (RILRequest) (msg.obj);  
  3.     RILRequest req = null;  
  4.     switch (msg.what) {  
  5.     case EVENT_SEND:  
  6.         boolean alreadySubtracted = false;  
  7.         try {  
  8.             LocalSocket s;  
  9.             s = mSocket;  
  10.             if (s == null) {  
  11.                 rr.onError(RADIO_NOT_AVAILABLE, null);  
  12.                 rr.release();  
  13.                 if (mRequestMessagesPending > 0)  
  14.                     mRequestMessagesPending--;  
  15.                 alreadySubtracted = true;  
  16.                 return;  
  17.             }  
  18.             synchronized (mRequestsList) {  
  19.                 mRequestsList.add(rr);  
  20.                 mRequestMessagesWaiting++;  
  21.             }  
  22.             if (mRequestMessagesPending > 0)  
  23.                 mRequestMessagesPending--;  
  24.             alreadySubtracted = true;  
  25.             byte[] data;  
  26.             data = rr.mp.marshall();  
  27.             rr.mp.recycle();  
  28.             rr.mp = null;  
  29.             if (data.length > RIL_MAX_COMMAND_BYTES) {  
  30.                 throw new RuntimeException("Parcel larger than max bytes allowed! "+ data.length);  
  31.             }  
  32.             // parcel length in big endian  
  33.             dataLength[0] = dataLength[1] = 0;  
  34.             dataLength[2] = (byte) ((data.length >> 8) & 0xff);  
  35.             dataLength[3] = (byte) ((data.length) & 0xff);  
  36.             s.getOutputStream().write(dataLength);  
  37.             s.getOutputStream().write(data);  
  38.         } catch (IOException ex) {  
  39.             Log.e(LOG_TAG, "IOException", ex);  
  40.             req = findAndRemoveRequestFromList(rr.mSerial);  
  41.             if (req != null || !alreadySubtracted) {  
  42.                 rr.onError(RADIO_NOT_AVAILABLE, null);  
  43.                 rr.release();  
  44.             }  
  45.         } catch (RuntimeException exc) {  
  46.             Log.e(LOG_TAG, "Uncaught exception ", exc);  
  47.             req = findAndRemoveRequestFromList(rr.mSerial);  
  48.             if (req != null || !alreadySubtracted) {  
  49.                 rr.onError(GENERIC_FAILURE, null);  
  50.                 rr.release();  
  51.             }  
  52.         } finally {  
  53.             releaseWakeLockIfDone();  
  54.         }  
  55.         if (!alreadySubtracted && mRequestMessagesPending > 0) {  
  56.             mRequestMessagesPending--;  
  57.         }  
  58.         break;  
  59.   
  60.     case EVENT_WAKE_LOCK_TIMEOUT:  
  61.         synchronized (mWakeLock) {  
  62.             if (mWakeLock.isHeld()) {  
  63.                 if (mRequestMessagesWaiting != 0) {  
  64.                     mRequestMessagesWaiting = 0;  
  65.                 }  
  66.                 if (mRequestMessagesPending != 0) {  
  67.                     mRequestMessagesPending = 0;  
  68.                 }  
  69.                 mWakeLock.release();  
  70.             }  
  71.         }  
  72.         break;  
  73.     }  
  74. }  

写入rild套接字的数据为:


发送步骤:

1.        生成RILRequest,此时将生成m_Serial(请求的Token)并将请求号,数据,及其Result Message 对象填入到RILRequest中

2.        使用send将RILRequest打包到EVENT_SEND消息中发送到到RIL Sender Handler

3.        RilSender 接收到EVENT_SEND消息,将RILRequest通过套接口发送到RILD,同时将RILRequest保存在mRequest中以便应答消息的返回。

RILReceiver


[java] view plaincopy
  1. public void run() {  
  2.     int retryCount = 0;  
  3.     try {  
  4.         for (;;) {  
  5.             LocalSocket s = null;  
  6.             LocalSocketAddress l;  
  7.             try {  
  8.                 //创建socket并连接到rild  
  9.                 s = new LocalSocket();  
  10.                 l = new LocalSocketAddress(SOCKET_NAME_RIL,LocalSocketAddress.Namespace.RESERVED);  
  11.                 s.connect(l);  
  12.             } catch (IOException ex) {  
  13.                 try {  
  14.                     if (s != null) {  
  15.                         s.close();  
  16.                     }  
  17.                 } catch (IOException ex2) {  
  18.                     // ignore failure to close after failure to connect  
  19.                 }  
  20.                 if (retryCount == 8) {  
  21.                     Log.e(LOG_TAG, "Couldn't find '" + SOCKET_NAME_RIL  
  22.                             + "' socket after " + retryCount  
  23.                             + " times, continuing to retry silently");  
  24.                 } else if (retryCount > 0 && retryCount < 8) {  
  25.                     Log.i(LOG_TAG, "Couldn't find '" + SOCKET_NAME_RIL  
  26.                             + "' socket; retrying after timeout");  
  27.                 }  
  28.                 try {  
  29.                     Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);  
  30.                 } catch (InterruptedException er) {  
  31.                 }  
  32.                 retryCount++;  
  33.                 continue;  
  34.             }  
  35.             retryCount = 0;  
  36.             mSocket = s;  
  37.             Log.i(LOG_TAG, "Connected to '" + SOCKET_NAME_RIL + "' socket");  
  38.             int length = 0;  
  39.             try {  
  40.                 InputStream is = mSocket.getInputStream();  
  41.                 //循环从socket中读取消息  
  42.                 for (;;) {  
  43.                     Parcel p;  
  44.                     length = readRilMessage(is, buffer);  
  45.                     if (length < 0) {  
  46.                         break;  
  47.                     }  
  48.                     p = Parcel.obtain();  
  49.                     p.unmarshall(buffer, 0, length);  
  50.                     p.setDataPosition(0);  
  51.                     processResponse(p);  
  52.                     p.recycle();  
  53.                 }  
  54.             } catch (java.io.IOException ex) {  
  55.                 Log.i(LOG_TAG, "'" + SOCKET_NAME_RIL + "' socket closed",ex);  
  56.             } catch (Throwable tr) {  
  57.                 Log.e(LOG_TAG, "Uncaught exception read length=" + length+ "Exception:" + tr.toString());  
  58.             }  
  59.             //socket连接断开,请求所有请求并重新连接  
  60.             Log.i(LOG_TAG, "Disconnected from '" + SOCKET_NAME_RIL+ "' socket");  
  61.             setRadioState(RadioState.RADIO_UNAVAILABLE);  
  62.             try {  
  63.                 mSocket.close();  
  64.             } catch (IOException ex) {  
  65.             }  
  66.             mSocket = null;  
  67.             RILRequest.resetSerial();  
  68.             clearRequestsList(RADIO_NOT_AVAILABLE, false);  
  69.         }  
  70.     } catch (Throwable tr) {  
  71.         Log.e(LOG_TAG, "Uncaught exception", tr);  
  72.     }  
  73.     notifyRegistrantsRilConnectionChanged(-1);  
  74. }  

接收步骤

1.        分析接收到的Parcel,根据类型不同进行处理。

2.        根据数据中的Token(mSerail),反查mRequest,找到对应的请求信息。

3.        将是接收到的数据转换成结果数据。

4.        将结果放在RequestMessage中发回到请求的发起者。