首先, 在ril.cpp 中 。 把短信pdu 写到uim卡上的函数为:
static void dispatchRilCdmaSmsWriteArgs(Parcel &p, RequestInfo *pRI) {
RIL_CDMA_SMS_WriteArgs rcsw;
int32_t t;
uint32_t ut;
uint8_t uct;
status_t status;
int32_t digitCount;
memset(&rcsw, 0, sizeof(rcsw));
status = p.readInt32(&t);
rcsw.status = t;
status = p.readInt32(&t);
rcsw.message.uTeleserviceID = (int) t;
status = p.read(&uct,sizeof(uct));
rcsw.message.bIsServicePresent = (uint8_t) uct;
status = p.readInt32(&t);
rcsw.message.uServicecategory = (int) t;
status = p.readInt32(&t);
rcsw.message.sAddress.digit_mode = (RIL_CDMA_SMS_DigitMode) t;
status = p.readInt32(&t);
rcsw.message.sAddress.number_mode = (RIL_CDMA_SMS_NumberMode) t;
status = p.readInt32(&t);
rcsw.message.sAddress.number_type = (RIL_CDMA_SMS_NumberType) t;
status = p.readInt32(&t);
rcsw.message.sAddress.number_plan = (RIL_CDMA_SMS_NumberPlan) t;
status = p.read(&uct,sizeof(uct));
rcsw.message.sAddress.number_of_digits = (uint8_t) uct;
for(digitCount = 0 ; digitCount < rcsw.message.sAddress.number_of_digits; digitCount ++) {
status = p.read(&uct,sizeof(uct));
rcsw.message.sAddress.digits[digitCount] = (uint8_t) uct;
}
status = p.readInt32(&t);
rcsw.message.sSubAddress.subaddressType = (RIL_CDMA_SMS_SubaddressType) t;
status = p.read(&uct,sizeof(uct));
rcsw.message.sSubAddress.odd = (uint8_t) uct;
status = p.read(&uct,sizeof(uct));
rcsw.message.sSubAddress.number_of_digits = (uint8_t) uct;
for(digitCount = 0 ; digitCount < rcsw.message.sSubAddress.number_of_digits; digitCount ++) {
status = p.read(&uct,sizeof(uct));
rcsw.message.sSubAddress.digits[digitCount] = (uint8_t) uct;
}
status = p.readInt32(&t);
rcsw.message.uBearerDataLen = (int) t;
for(digitCount = 0 ; digitCount < rcsw.message.uBearerDataLen; digitCount ++) {
status = p.read(&uct, sizeof(uct));
rcsw.message.aBearerData[digitCount] = (uint8_t) uct;
}
if (status != NO_ERROR) {
goto invalid;
}
startRequest;
appendPrintBuf("%sstatus=%d, message.uTeleserviceID=%d, message.bIsServicePresent=%d, \
message.uServicecategory=%d, message.sAddress.digit_mode=%d, \
message.sAddress.number_mode=%d, \
message.sAddress.number_type=%d, ",
printBuf, rcsw.status, rcsw.message.uTeleserviceID, rcsw.message.bIsServicePresent,
rcsw.message.uServicecategory, rcsw.message.sAddress.digit_mode,
rcsw.message.sAddress.number_mode,
rcsw.message.sAddress.number_type);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
s_callbacks[pRI->client_id].onRequest(pRI->pCI->requestNumber, &rcsw, sizeof(rcsw),pRI);
#ifdef MEMSET_FREED
memset(&rcsw, 0, sizeof(rcsw));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
对应的 ril.java 中的函数为 :
public void writeSmsToRuim(int status, String pdu, Message response) {
status = translateStatus(status);
RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM,
response);
rr.mp.writeInt(status);
//rr.mp.writeString(pdu);
constructCdmaWriteSmsRilRequest(rr,IccUtils.hexStringToBytes(pdu));
if (Config.LOGD) {
riljLog(pdu);
if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+ requestToString(rr.mRequest)
+ " " + status);
}
send(rr);
}
调用了 constructCdmaWriteSmsRilRequest 这个函数,具体实现为:
private void
constructCdmaWriteSmsRilRequest(RILRequest rr, byte[] pdu) {
int address_nbr_of_digits;
int subaddr_nbr_of_digits;
int bearerDataLength;
ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
DataInputStream dis = new DataInputStream(bais);
try {
// int status = dis.readInt();
// rr.mp.writeInt(status); //status
int teleServiceId = dis.readInt();
rr.mp.writeInt(teleServiceId); //teleServiceId ,int
byte servicePresent = (byte)dis.readByte();
rr.mp.writeByte(servicePresent); //servicePresent, byte
int serviceCategory = dis.readInt();
rr.mp.writeInt(serviceCategory); //serviceCategory, int
int address_digit_mode = dis.readInt();
rr.mp.writeInt(address_digit_mode); //address_digit_mode, int
int address_nbr_mode = dis.readInt();
rr.mp.writeInt(address_nbr_mode); //address_nbr_mode,int
int address_ton = dis.readInt();
rr.mp.writeInt(address_ton); //address_ton,int
int address_nbr_plan = dis.readInt();
rr.mp.writeInt(address_nbr_plan); //address_nbr_plan,int
address_nbr_of_digits = (byte) dis.readByte();//byte
rr.mp.writeByte((byte) address_nbr_of_digits);
for(int i=0; i < address_nbr_of_digits; i++){
rr.mp.writeByte(dis.readByte()); // address_orig_bytes[i]
}
int subaddressType = dis.readInt();//int
rr.mp.writeInt(subaddressType); //subaddressType
byte subaddr_odd = (byte) dis.readByte();
rr.mp.writeByte(subaddr_odd); //subaddr_odd
subaddr_nbr_of_digits = (byte) dis.readByte();
rr.mp.writeByte((byte) subaddr_nbr_of_digits);
for(int i=0; i < subaddr_nbr_of_digits; i++){
rr.mp.writeByte(dis.readByte()); //subaddr_orig_bytes[i]
}
bearerDataLength = dis.readInt();
rr.mp.writeInt(bearerDataLength);
for(int i=0; i < bearerDataLength; i++){
rr.mp.writeByte(dis.readByte()); //bearerData[i]
}
riljLog(" teleServiceId="+ teleServiceId + " servicePresent=" + servicePresent
+ " serviceCategory=" + serviceCategory +" address_digit_mode=" + address_digit_mode+ " address_nbr_mode="
+ address_nbr_mode + " address_ton=" + address_ton + " address_nbr_plan=" + address_nbr_plan + " address_nbr_of_digits="
+ address_nbr_of_digits + " subaddressType=" + subaddressType + " subaddr_odd= " + subaddr_odd + " subaddr_nbr_of_digits="
+ subaddr_nbr_of_digits + " bearerDataLength=" + bearerDataLength);
}catch (IOException ex){
if (RILJ_LOGD) riljLog("sendSmsCdma: conversion from input stream to object failed: "
+ ex);
}finally{
try{
if(null != bais){
bais.close();
}
if(null != dis){
dis.close();
}
}catch(IOException e){
}
}
}
所以在我们对短信pdu打包的过程中,需要对应相应的数据和类型。
在SmsMessage.java (frameworks\base\telephony\java\com\android\internal\telephony\cdma)这个类中。 有对短信pdu打包的函数:
public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message,
boolean statusReportRequested, SmsHeader smsHeader) {
/**
* TODO(cleanup): Do we really want silent failure like this?
* Would it not be much more reasonable to make sure we don't
* call this function if we really want nothing done?
*/
if (message == null || destAddr == null) {
return null;
}
UserData uData = new UserData();
uData.payloadStr = message;
uData.userDataHeader = smsHeader;
return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
}
其中privateGetSubmitPdu 函数的具体实现为:
/**
* Creates BearerData and Envelope from parameters for a Submit SMS.
* @return byte stream for SubmitPdu.
*/
private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested,
UserData userData) {
// 此处省略部分代码
//…................................
//…................................
try {
/**
* TODO(cleanup): reference a spec and get rid of the ugly comments
*/
ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(envelope.teleService);
dos.writeByte(0); //servicePresent
dos.writeInt(0); //serviceCategory
dos.writeInt(destAddr.digitMode);
dos.writeInt(destAddr.numberMode);
dos.writeInt(destAddr.ton); // number_type
dos.writeInt(destAddr.numberPlan);
dos.writeByte(destAddr.numberOfDigits);
dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits
// Subaddress is not supported.
dos.writeInt(0); //subaddressType
dos.writeByte(0); //subaddr_odd
dos.writeByte(0); //subaddr_nbr_of_digits
dos.writeInt(encodedBearerData.length);
dos.write(encodedBearerData, 0, encodedBearerData.length);
dos.close();
SubmitPdu pdu = new SubmitPdu();
pdu.encodedMessage = baos.toByteArray();
pdu.encodedScAddress = null;
return pdu;
} catch(IOException ex) {
Log.e(LOG_TAG, "creating SubmitPdu failed: ", ex);
}
return null;
}
调用 getSubmitPdu 这个函数,可以得到一个 SubmitPdu 对象, 里面的encodedMessage 这个成员, 正是我们打包的pdu byte 数组 。 调用
SmsManager.getDefault().copyMessageToIcc(null, pdu.encodedMessage, SmsManager.STATUS_ON_ICC_SENT, subscription);
方法就可以实现 复制短信到uim卡 。具体实现:
private boolean copyToSim(MessageItem msgItem, int subscription) {
int boxId = msgItem.mBoxId;
String address = msgItem.mAddress;
String text = msgItem.mBody;
long timestamp = msgItem.mDate != 0 ? msgItem.mDate : System.currentTimeMillis();
ArrayList<String> messages = SmsManager.getDefault().divideMessage(text);
boolean ret = true;
for (String message : messages) {
if (Sms.isOutgoingFolder(boxId)) {
SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(null, address, message, false);
ret &= SmsManager.getDefault().copyMessageToIcc(null, pdu.encodedMessage,
SmsManager.STATUS_ON_ICC_SENT, subscription);
} else {
byte[] pdu = MessageUtils.getDeliveryPdu(null, address, message, timestamp);
ret &= SmsManager.getDefault().copyMessageToIcc(null, pdu,
SmsManager.STATUS_ON_ICC_READ, subscription);
}
if (!ret) {
break;
}
}
return ret;
}
函数getDeliveryPdu , 是在短信的 MessageUtils 中实现的方法。打包过程,和 privateGetSubmitPdu 这个方法一样 。
注: 参数SmsManager.STATUS_ON_ICC_SENT, SmsManager.STATUS_ON_ICC_READ, 是代表发送还是接受的。