(M)SIM卡开机流程分析之RIL类分析

今天,来简单看一下SIM卡开机流程中的另一个重要的类,RIL.java

首先,进入RIL.java文件中

/**
 * RIL implementation of the CommandsInterface.
 *
 * {@hide}
 */
// Leo,需要注意这个地方,继承自BaseCommands,实现了CommandsInterface的接口
public final class RIL extends BaseCommands implements CommandsInterface {
    ......
}
注意,这个类是继承自BaseCommands,并实现了CommandsInterface接口

再来看看,PhoneFactory.java文件中的makeDefaultPhone方法中对于RIL类的创建

for (int i = 0; i < numPhones; i++) {
     // reads the system properties and makes commandsinterface
     // Get preferred network type.
     networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;

     Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i]));
     // Leo,为每一个卡槽新建一个RIL对象
     // RIL是实现了CommandsInterface的接口,因此这个地方的名称为sCommandsInterfaces
     sCommandsInterfaces[i] = new RIL(context, networkModes[i], cdmaSubscription, i);
}
// Leo,获取Settings.Global.CDMA_SUBSCRIPTION_MODE的值
int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
CdmaSubscriptionSourceManager.java

/**
     * Gets the default CDMA subscription source
     *
     * @return Default CDMA subscription source from Settings DB if present.
     */
    public static int getDefault(Context context) {
        // Get the default value from the Settings
        int subscriptionSource = Settings.Global.getInt(context.getContentResolver(),
                Settings.Global.CDMA_SUBSCRIPTION_MODE, PREFERRED_CDMA_SUBSCRIPTION);
        Rlog.d(LOG_TAG, "subscriptionSource from settings: " + subscriptionSource);
        return subscriptionSource;
    }
networkModes[i]参数,从上面可以看到,是直接赋值的,cdmaSubscription参数,从上文中看值为指定的值,暂不追究,i参数是之的第几张卡槽,接下来,看看RIL的构造函数

// Leo, RIL的构造方法
// 第四个参数是第instanceId个卡槽
// 第二个参数是第instanceId个卡槽的PreferredNetworkMode值
// 第三个参数cdmaSubscription,是Settings.Global.CDMA_SUBSCRIPTION_MODE的值
public RIL(Context context, int preferredNetworkType, int cdmaSubscription, Integer instanceId) {
    super(context);
    ......
    
    mContext = context;
    mCdmaSubscription  = cdmaSubscription;
    mPreferredNetworkType = preferredNetworkType;
    mPhoneType = RILConstants.NO_PHONE;
    mInstanceId = instanceId;

    PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    // Leo, 这个WakeLock是干嘛用的?
    mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, RILJ_LOG_TAG);
    mWakeLock.setReferenceCounted(false);
    mWakeLockTimeout = SystemProperties.getInt(TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT, DEFAULT_WAKE_LOCK_TIMEOUT);
    mWakeLockCount = 0;

    // Leo HandlerThread
    mSenderThread = new HandlerThread("RILSender" + mInstanceId);
    mSenderThread.start();

    Looper looper = mSenderThread.getLooper();
    // Leo, 这个RILSender继承Handler,并实现Runnable接口
    mSender = new RILSender(looper);

    ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {
        riljLog("Not starting RILReceiver: wifi-only");
    } else {
        riljLog("Starting RILReceiver" + mInstanceId);
        // Leo,实现Socket通信,Runnable对象
        mReceiver = new RILReceiver();
        mReceiverThread = new Thread(mReceiver, "RILReceiver" + mInstanceId);
        mReceiverThread.start();

        DisplayManager dm = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        mDefaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
        dm.registerDisplayListener(mDisplayListener, null);
        mDefaultDisplayState = mDefaultDisplay.getState();

        // Leo,监控电量变化,为啥?
        IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent batteryStatus = context.registerReceiver(mBatteryStateListener, filter);
        if (batteryStatus != null) {
            // 0 means it's on battery
            mIsDevicePlugged = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
        }
    }

    // Leo,刚刚在PhoneFactory调用了一次TelephonyDevController的create方法
    // 此处调用getInstance方法,可以得到其对象
    TelephonyDevController tdc = TelephonyDevController.getInstance();
    tdc.registerRIL(this);
}
从代码中可以看到,RIL的构造函数中,主要是做了

1)赋值操作

2)新建一些WakeLock,这个目前我还不知道其作用,待以后分析吧

3)启动了一个HandlerThread,然后新建一个RILSender对象,这个对象继承了Handler,并且实现了Runnable接口,但是其run方法中并未做任何操作

4)在判断手机支持移动数据流量的基础上,新建一个RILReceiver对象并直接启动,这个对象实现了Runnable的接口,在其run方法中,建立通信连接,实现RIL消息的传输和RIL消息的处理,这个一会儿再看

5)监听显示设置和电量变化

6)新建了TelephonyDevController对象,并注册RIL


接下来,我们就重点看看第4)条,进入RILReceiver类

class RILReceiver implements Runnable {
    byte[] buffer;
    RILReceiver() {
	buffer = new byte[RIL_MAX_COMMAND_BYTES];
    }
    @Override
    public void run() {
	int retryCount = 0;
	String rilSocket = "rild";
	// Leo,Socket通信
	try {
		for (;;) {
			LocalSocket s = null;
			LocalSocketAddress l;

			if (mInstanceId == null || mInstanceId == 0) {
				rilSocket = SOCKET_NAME_RIL[0];
			} else {
				rilSocket = SOCKET_NAME_RIL[mInstanceId];
			}

			try {
				s = new LocalSocket();
				l = new LocalSocketAddress(rilSocket, LocalSocketAddress.Namespace.RESERVED);
				s.connect(l);
			} catch (IOException ex) {
				try {
					if (s != null) {
						s.close();
					}
				} catch (IOException ex2) {
					// ignore failure 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) {
					Rlog.e(RILJ_LOG_TAG, "Couldn't find '" + rilSocket
									+ "' socket after " + retryCount
									+ " times, continuing to retry silently");
				} else if (retryCount >= 0 && retryCount < 8) {
					Rlog.i(RILJ_LOG_TAG, "Couldn't find '" + rilSocket
							+ "' socket; retrying after timeout");
				}

				try {
					Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
				} catch (InterruptedException er) {
				}
				retryCount++;
				continue;
			}

			retryCount = 0;
 			mSocket = s;
			......
			int length = 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);
					// Rlog.v(RILJ_LOG_TAG, "Read packet: " + length +
					// " bytes");
					processResponse(p);
					p.recycle();
				}
			} catch (java.io.IOException ex) {
				Rlog.i(RILJ_LOG_TAG, "'" + rilSocket
						+ "' socket closed", ex);
			} catch (Throwable tr) {
				Rlog.e(RILJ_LOG_TAG, "Uncaught exception read length="
						+ length + "Exception:" + tr.toString());
			}
			Rlog.i(RILJ_LOG_TAG, "(" + mInstanceId
					+ ") Disconnected from '" + rilSocket + "' socket");
			setRadioState(RadioState.RADIO_UNAVAILABLE);

			try {
				mSocket.close();
			} catch (IOException ex) {
			}
			mSocket = null;
			RILRequest.resetSerial();

					// Clear request list on close
					clearRequestList(RADIO_NOT_AVAILABLE, false);
				}
			} catch (Throwable tr) {
				Rlog.e(RILJ_LOG_TAG, "Uncaught exception", tr);
			}

			/* We're disconnected so we don't know the ril version */
			notifyRegistrantsRilConnectionChanged(-1);
		}
	}
RILReceiver类是实现了Runnable的接口,其run方法主要是新建一个死循环

1)在死循环中新建LocalSocket和LocalSocketAddress对象,并建立链接,之后将LocalSocket对象赋值给全局对象mSocket

2)再新建一个死循环,这个死循环不间断地读取底层RIL传递上来的消息,然后调用processResponse方法处理这个RIL消息,直到完全结束后,释放Socket,并通知RILCONNECTION状态变化

那么,在RIL中是如何处理底层ril传递上来的ril消息呢?

private void processResponse (Parcel p) {
    int type;

    type = p.readInt();

    if (type == RESPONSE_UNSOLICITED) {
        processUnsolicited (p);
    } else if (type == RESPONSE_SOLICITED) {
        RILRequest rr = processSolicited (p);
        if (rr != null) {
            rr.release();
            decrementWakeLock();
        }
    }
}
若回复请求,则调用processSolicited方法,反之,则调用processUnsoliciterd方法

private void processUnsolicited (Parcel p) {
    ......
}
private RILRequest processSolicited (Parcel p) {
    ......
}
针对不同的请求,处理

在看到这个RIL.java文件的时候,我们发现在其文件中有一个RILRequest类,这个类是有什么作用呢?先看看这个类中的方法

/**
 * Retrieves a new RILRequest instance from the pool.
 *
 * @param request RIL_REQUEST_*
 * @param result sent when operation completes
 * @return a RILRequest instance from the pool.
 */
static RILRequest obtain(int request, Message result) {
    RILRequest rr = null;

    synchronized(sPoolSync) {
        if (sPool != null) {
            rr = sPool;
            sPool = rr.mNext;
            rr.mNext = null;
            sPoolSize--;
        }
    }

    if (rr == null) {
        rr = new RILRequest();
    }

    rr.mSerial = sNextSerial.getAndIncrement();

    rr.mRequest = request;
    rr.mResult = result;
    rr.mParcel = Parcel.obtain();

    if (result != null && result.getTarget() == null) {
        throw new NullPointerException("Message target must not be null");
    }

    // first elements in any RIL Parcel
    rr.mParcel.writeInt(request);
    rr.mParcel.writeInt(rr.mSerial);

    return rr;
}
这个方法,从代码中看,首先是先创建了一个RILRequest对象,这个对象保存了传入的request对象和result对象,然后将request和自身的mSerial写入mParcel对象中

对于release方法等,在此不做其他分析,可以自己看

我们在其他地方,经常会看到,需要调用RIL对象的大量获取数据的方法,那么,我们就仅下述方法来确认,究竟是什么样的流程,如下:

@Override
public void getVoiceRadioTechnology(Message result) {
    RILRequest rr = RILRequest.obtain(RIL_REQUEST_VOICE_RADIO_TECH, result);

    if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

    send(rr);
}
我们看到,这个地方调用了RILRequest的obtain方法,创建一个RILRequest对象,从上述分析我们知道,这会将该对象的mRequest参数置为RIL_REQUEST_VOICE_RADIO_TECH,而mResult对象置为result消息对象没然后新建一个mParcel对象

接下来进入RIL类的send方法

private void send(RILRequest rr) {
    Message msg;

    if (mSocket == null) {
        rr.onError(RADIO_NOT_AVAILABLE, null);
        rr.release();
        return;
    }

    msg = mSender.obtainMessage(EVENT_SEND, rr);

    acquireWakeLock();

    msg.sendToTarget();
}
mSender从前文中,我们知道这个是RILSender对象,这个对象继承了Handler,并实现了Runnable,因此其本质为Handler,那么调用msg的sendToTarget方法,即调用了mSender对象的handleMessage方法,而且msg的what为EVENT_SEND,obj参数为刚刚新建的RILRequest对象

RILSender的handleMessage方法对于EVENT_SEND的处理为

@Override 
public void handleMessage(Message msg) {
    RILRequest rr = (RILRequest)(msg.obj);
    RILRequest req = null;

    switch (msg.what) {
        case EVENT_SEND:
            try {
                LocalSocket s;
                s = mSocket;
                ......

                synchronized (mRequestList) {
                    // Leo,写入
                    mRequestList.append(rr.mSerial, rr);
                }

                byte[] data;

                data = rr.mParcel.marshall();
                rr.mParcel.recycle();
                rr.mParcel = null;

                ......

                // parcel length in big endian
                dataLength[0] = dataLength[1] = 0;
                dataLength[2] = (byte)((data.length >> 8) & 0xff);
                dataLength[3] = (byte)((data.length) & 0xff);

                ......

                s.getOutputStream().write(dataLength);
                s.getOutputStream().write(data);
            } catch (IOException ex) {
                ......
            } catch (RuntimeException exc) {
                ......
            }

            break;
            ......
    }
}
新建LocalSocket对象,并且指向mSocket,mSocket我们在前面分析过,在RILRequest内部类中进行绑定了并发送,那么谁接收呢?自然是在RILReceiver的run方法中了,还记得它是有一个死循环,不断都去RIL命令么?其调用了processResponse方法,最终调用的是processSolicited方法

private RILRequest processSolicited(Parcel p) {
	int serial, error;
	boolean found = false;

	serial = p.readInt();
	error = p.readInt();

	RILRequest rr;

	rr = findAndRemoveRequestFromList(serial);

	if (rr == null) {
		......
		return null;
	}

	Object ret = null;

	if (error == 0 || p.dataAvail() > 0) {
		// either command succeeds or command fails but with data payload
		try {
			switch (rr.mRequest) {
			......
			case RIL_REQUEST_VOICE_RADIO_TECH:
				ret = responseInts(p);
				break;
			......
		} catch (Throwable tr) {
			......
		}
	}
	......
	return rr;
}
findAndRemoveRequestFromList方法从mRequestList取出rr.mSerial对应的RILRequest,是在RILSender对象的EVENT_SEND消息处添加的

然后获取其mRequest对象,我们知道为RIL_REQUEST_VOICE_RADIO_TECH,因此调用responseInts进行处理

private Object responseInts(Parcel p) {
    int numInts;
    int response[];

    numInts = p.readInt();

    response = new int[numInts];

    for (int i = 0 ; i < numInts ; i++) {
        response[i] = p.readInt();
    }

    return response;
}
至此,RIL类在SIM卡开机流程中,所作的大致用途,已经分析完成,待后续对开机流程中所遇到的具体问题,再在具体方法中进行分析

你可能感兴趣的:(SIM卡开机流程分析)