平臺
RK3288 + Android 7.1 + EC20
流程
獲取手機號代碼:
TelephonyManager telMgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if (telMgr != null) {
String num = telMgr.getLine1Number();//手機號碼
}
接口跟蹤
//–frameworks/base/telephony/java/android/telephony/TelephonyManager.java
public String getLine1Number() {
return getLine1Number(getSubId());
}
public String getLine1Number(int subId) {
String number = null;
try {
ITelephony telephony = getITelephony();
if (telephony != null)
number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
if (number != null) {
return number;
}
try {
//手上測試卡執行的是這部分代碼:
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
// This could happen before phone restarts due to crashing
return null;
}
}
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneSubInfoController.java
public String getLine1Number(String callingPackage) {
return getLine1NumberForSubscriber(getDefaultSubscription(), callingPackage);
}
public String getLine1NumberForSubscriber(int subId, String callingPackage) {
Phone phone = getPhone(subId);
if (phone != null) {
// This is open to apps with WRITE_SMS.
if (!checkReadPhoneNumber(callingPackage, "getLine1Number")) {
return null;
}
return phone.getLine1Number();
} else {
loge("getLine1Number phone is null for Subscription:" + subId);
return null;
}
}
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@Override
public String getLine1Number() {
d("getLine1Number " + isPhoneTypeGsm());
if (isPhoneTypeGsm()) {
IccRecords r = mIccRecords.get();
return (r != null) ? r.getMsisdnNumber() : null;
} else {
return mSST.getMdnNumber();
}
}
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/SIMRecords.java
//直接返回mMsisdn
@Override
public String getMsisdnNumber() {
return mMsisdn;
}
//mMsisdn的賦值:
@Override
public void handleMessage(Message msg) {
//...
case EVENT_GET_MSISDN_DONE:
isRecordLoadResponse = true;
ar = (AsyncResult)msg.obj;
if (ar.exception != null) {
log("Invalid or missing EF[MSISDN]");
break;
}
adn = (AdnRecord)ar.result;
mMsisdn = adn.getNumber();
mMsisdnTag = adn.getAlphaTag();
log("MSISDN: " + /*mMsisdn*/ Rlog.pii(LOG_TAG, mMsisdn));
break;
//...
}
請求
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/SIMRecords.java
//發起獲取SIM卡卡號請求:
protected void fetchSimRecords() {
d("fetchSimRecords");
mRecordsRequested = true;
if (DBG) log("fetchSimRecords " + mRecordsToLoad);
mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
mRecordsToLoad++;
mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
mRecordsToLoad++;
// FIXME should examine EF[MSISDN]'s capability configuration
// to determine which is the voice/data/fax line
new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1,
obtainMessage(EVENT_GET_MSISDN_DONE));
}
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/AdnRecordLoader.java
class AdnRecordLoader extends Handler
/**
* Resulting AdnRecord is placed in response.obj.result
* or response.obj.exception is set
*/
public void
loadFromEF(int ef, int extensionEF, int recordNumber,
Message response) {
mEf = ef;
mExtensionEF = extensionEF;
mRecordNumber = recordNumber;
mUserResponse = response;
mFh.loadEFLinearFixed(
ef, getEFPath(ef), recordNumber,
obtainMessage(EVENT_ADN_LOAD_DONE));
}
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
public void loadEFLinearFixed(int fileid, String path, int recordNum, Message onLoaded) {
String efPath = (path == null) ? getEFPath(fileid) : path;
Message response
= obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
new LoadLinearFixedContext(fileid, recordNum, efPath, onLoaded));
d("loadEFLinearFixed fileid(" + fileid + "), path(" + path + ")");
mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, efPath,
0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);
}
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
@Override
public void iccIOForApp (int command, int fileid, String path, int p1, int p2, int p3,
String data, String pin2, String aid, Message result) {
//Note: This RIL request has not been renamed to ICC,
// but this request is also valid for SIM and RUIM
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SIM_IO, result);
rr.mParcel.writeInt(command);
rr.mParcel.writeInt(fileid);
rr.mParcel.writeString(path);
rr.mParcel.writeInt(p1);
rr.mParcel.writeInt(p2);
rr.mParcel.writeInt(p3);
rr.mParcel.writeString(data);
rr.mParcel.writeString(pin2);
rr.mParcel.writeString(aid);
if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: "
+ requestToString(rr.mRequest)
+ " 0x" + Integer.toHexString(command)
+ " 0x" + Integer.toHexString(fileid) + " "
+ " path: " + path + ","
+ p1 + "," + p2 + "," + p3
+ " aid: " + aid);
send(rr);
}
發送的過程消息順序: SIMRecords -> AdnRecordLoader -> IccFileHandler -> RIL
響應:
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
private void processResponse (Parcel p) {
int type;
type = p.readInt();
if (type == RESPONSE_UNSOLICITED || type == RESPONSE_UNSOLICITED_ACK_EXP) {
processUnsolicited (p, type);
} else if (type == RESPONSE_SOLICITED || type == RESPONSE_SOLICITED_ACK_EXP) {
RILRequest rr = processSolicited (p, type);
if (rr != null) {
if (type == RESPONSE_SOLICITED) {
decrementWakeLock(rr);
}
rr.release();
return;
}
} else if (type == RESPONSE_SOLICITED_ACK) {
int serial;
serial = p.readInt();
RILRequest rr;
synchronized (mRequestList) {
rr = mRequestList.get(serial);
}
if (rr == null) {
Rlog.w(RILJ_LOG_TAG, "Unexpected solicited ack response! sn: " + serial);
} else {
decrementWakeLock(rr);
if (RILJ_LOGD) {
riljLog(rr.serialString() + " Ack < " + requestToString(rr.mRequest));
}
}
}
}
private RILRequest processSolicited (Parcel p, int type) {
// ...
if (error == 0 || p.dataAvail() > 0) {
// either command succeeds or command fails but with data payload
try {switch (rr.mRequest) {
// ...
case RIL_REQUEST_SIM_IO: ret = responseICC_IO(p); break;
}
//...
if (error == 0) {
//IccIoResult ret.
if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)
+ " " + retToString(rr.mRequest, ret));
if (rr.mResult != null) {
if(rr.mRequest == RIL_REQUEST_SIM_IO){
Rlog.d("RIL", "SIM_IO response send " + rr.mResult.what + "{" + ret.toString() + "}");
}
AsyncResult.forMessage(rr.mResult, ret, null);
rr.mResult.sendToTarget();
}
}
}
private Object responseICC_IO(Parcel p) {
int sw1, sw2;
Message ret;
sw1 = p.readInt();
sw2 = p.readInt();
String s = p.readString();
Rlog.d("RIL", "responseICC_IO 0x" + Integer.toHexString(sw1)
+ " 0x" + Integer.toHexString(sw2) + " " + s);
if (true || RILJ_LOGV) riljLog("< iccIO: "
+ " 0x" + Integer.toHexString(sw1)
+ " 0x" + Integer.toHexString(sw2) + " "
+ s);
return new IccIoResult(sw1, sw2, s);
}
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
IccIoResult result;
Message response = null;
String str;
LoadLinearFixedContext lc;
byte data[];
int size;
int fileid;
int recordSize[];
String path = null;
try {
switch (msg.what)
case EVENT_GET_RECORD_SIZE_IMG_DONE:
case EVENT_GET_RECORD_SIZE_DONE:
ar = (AsyncResult)msg.obj;
lc = (LoadLinearFixedContext) ar.userObj;
result = (IccIoResult) ar.result;
response = lc.mOnLoaded;
if (processException(response, (AsyncResult) msg.obj)) {
break;
}
data = result.payload;
path = lc.mPath;
if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
throw new IccFileTypeMismatch();
}
if (EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
throw new IccFileTypeMismatch();
}
lc.mRecordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
+ (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
lc.mCountRecords = size / lc.mRecordSize;
if (lc.mLoadAll) {
lc.results = new ArrayList<byte[]>(lc.mCountRecords);
}
if (path == null) {
path = getEFPath(lc.mEfid);
}
mCi.iccIOForApp(COMMAND_READ_RECORD, lc.mEfid, path,
lc.mRecordNum,
READ_RECORD_MODE_ABSOLUTE,
lc.mRecordSize, null, null, mAid,
obtainMessage(EVENT_READ_RECORD_DONE, lc));
break;
}
//–frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/AdnRecordLoader.java
void handleMessage(){
case EVENT_ADN_LOAD_DONE:
ar = (AsyncResult)(msg.obj);
data = (byte[])(ar.result);
if (ar.exception != null) {
throw new RuntimeException("load failed", ar.exception);
}
if (VDBG) {
Rlog.d(LOG_TAG,"ADN EF: 0x"
+ Integer.toHexString(mEf)
+ ":" + mRecordNumber
+ "\n" + IccUtils.bytesToHexString(data));
}
adn = new AdnRecord(mEf, mRecordNumber, data);
mResult = adn;
if (adn.hasExtendedRecord()) {
// If we have a valid value in the ext record field,
// we're not done yet: we need to read the corresponding
// ext record and append it
mPendingExtLoads = 1;
mFh.loadEFLinearFixed(
mExtensionEF, adn.mExtRecord,
obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
}
break;
}
處理響應的順序: RIL -> IccFileHandler -> AdnRecordLoader -> SIMRecords
測試過程LOG整理
// RIL.java reference-ril.so
iccIOForApp 0xc0, 0x2fe2 requestSIM_IO 0x2fe2, 0, 0, 15
iccIOForApp 0xc0, 0x6f40 requestSIM_IO 0x6f40, 0, 0, 15
iccIOForApp 0xc0, 0x6fc9 requestSIM_IO 0x6fc9, 0, 0, 15
iccIOForApp 0xc0, 0x6fad requestSIM_IO 0x6fad, 0, 0, 15
iccIOForApp 0xc0, 0x6fca requestSIM_IO 0x6fca, 0, 0, 15
iccIOForApp 0xc0, 0x6f11 requestSIM_IO 0x6f11, 0, 0, 15
iccIOForApp 0xc0, 0x6fcb requestSIM_IO 0x6fcb, 0, 0, 15
iccIOForApp 0xc0, 0x6f13 requestSIM_IO 0x6f13, 0, 0, 15
iccIOForApp 0xc0, 0x6f46 requestSIM_IO 0x6f46, 0, 0, 15
iccIOForApp 0xc0, 0x6fcd requestSIM_IO 0x6fcd, 0, 0, 15
iccIOForApp 0xc0, 0x6fc5 requestSIM_IO 0x6fc5, 0, 0, 15
iccIOForApp 0xc0, 0x6f38 requestSIM_IO 0x6f38, 0, 0, 15
iccIOForApp 0xc0, 0x6f16 requestSIM_IO 0x6f16, 0, 0, 15
iccIOForApp 0xc0, 0x6f15 requestSIM_IO 0x6f15, 0, 0, 15
iccIOForApp 0xc0, 0x6f3e requestSIM_IO 0x6f3e, 0, 0, 15
iccIOForApp 0xc0, 0x6f3f requestSIM_IO 0x6f3f, 0, 0, 15
iccIOForApp 0xc0, 0x6f60 requestSIM_IO 0x6f60, 0, 0, 15
iccIOForApp 0xc0, 0x6f61 requestSIM_IO 0x6f61, 0, 0, 15
iccIOForApp 0xc0, 0x6f62 requestSIM_IO 0x6f62, 0, 0, 15
iccIOForApp 0xc0, 0x6fd9 requestSIM_IO 0x6fd9, 0, 0, 15
iccIOForApp 0xc0, 0x6f7b requestSIM_IO 0x6f7b, 0, 0, 15
iccIOForApp 0xb0, 0x2fe2 requestSIM_IO 0x2fe2, 0, 0, 10
iccIOForApp 0xb2, 0x6f40 requestSIM_IO 0x6f40, 1, 4, 28
iccIOForApp 0xb0, 0x6fad requestSIM_IO 0x6fad, 0, 0, 4
iccIOForApp 0xc0, 0x6f17 requestSIM_IO 0x6f17, 0, 0, 15
iccIOForApp 0xb2, 0x6fcb requestSIM_IO 0x6fcb, 1, 4, 16
iccIOForApp 0xb0, 0x6f46 requestSIM_IO 0x6f46, 0, 0, 17
iccIOForApp 0xb0, 0x6f38 requestSIM_IO 0x6f38, 0, 0, 11
iccIOForApp 0xb0, 0x6f60 requestSIM_IO 0x6f60, 0, 0, 40
iccIOForApp 0xb0, 0x6f61 requestSIM_IO 0x6f61, 0, 0, 3500
iccIOForApp 0xb0, 0x6f62 requestSIM_IO 0x6f62, 0, 0, 10
iccIOForApp 0xb0, 0x6fd9 requestSIM_IO 0x6fd9, 0, 0, 12
iccIOForApp 0xb0, 0x6f7b requestSIM_IO 0x6f7b, 0, 0, 60
RIL : responseICC_IO 0x90 0x0 0000000a2fe2040000000000000000
RIL : responseICC_IO 0x90 0x0 000000386f4004000000000000011c
RIL : responseICC_IO 0x90 0x0 000000046fad040000000000000000
RIL : responseICC_IO 0x6a 0x82 null
RIL : responseICC_IO 0x90 0x0 000000106fcb040000000000000110
RIL : responseICC_IO 0x6a 0x82 null
RIL : responseICC_IO 0x90 0x0 000000116f46040000000000000000
RIL : responseICC_IO 0x90 0x0 0000000b6f38040000000000000000
RIL : responseICC_IO 0x6a 0x82 null
RIL : responseICC_IO 0x6a 0x82 null
RIL : responseICC_IO 0x90 0x0 000000286f60040000000000000000
RIL : responseICC_IO 0x90 0x0 00000dac6f61040000000000000000
RIL : responseICC_IO 0x90 0x0 0000000a6f62040000000000000000
RIL : responseICC_IO 0x90 0x0 0000000c6fd9040000000000000000
RIL : responseICC_IO 0x90 0x0 0000003c6f7b040000000000000000
RIL : responseICC_IO 0x90 0x0 98683061691572783521
RIL : responseICC_IO 0x90 0x0 ffffffffffffffffffffffffffff0891688116325476f8ffffffffff
RIL : responseICC_IO 0x90 0x0 00000002
RIL : responseICC_IO 0x6a 0x82 null
RIL : responseICC_IO 0x90 0x0 00000000000000000000000000000000
RIL : responseICC_IO 0x90 0x0 01804E2D56FD75354FE1FFFFFFFFFFFFFF
RIL : responseICC_IO 0x90 0x0 802F1C2C230E0100C00050
RIL : responseICC_IO 0x90 0x0 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
RIL : responseICC_IO 0x90 0x0 54F430C08054F440008054F491C08054F460C08025F040C08025F099808025F000808025F030800025F0100080130014C080130062C080130073C0801300744080130041808044F001C00044F002800064F629C08064F679808064F639008064F699008005F530C08005F501008005F510C08054F080C00054F050C00062F220C08062F210C08025F550408025F510408002F801C08002F802C08015F001C08015F0108080030216C0000302
RIL : responseICC_IO 0x90 0x0 FFFFFFFFFFFFFFFFFFFF
RIL : responseICC_IO 0x90 0x0 64F01164F030FFFFFFFFFFFF
RIL : responseICC_IO 0x90 0x0 64F00064F01064F02064F06064F07064F002FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=6
IccFileHandler: handleMessage what=6
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=6
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=6
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=6
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=4
IccFileHandler: handleMessage what=5
IccFileHandler: handleMessage what=7
IccFileHandler: handleMessage what=5
IccFileHandler: handleMessage what=6
IccFileHandler: handleMessage what=7
IccFileHandler: handleMessage what=5
IccFileHandler: handleMessage what=5
IccFileHandler: handleMessage what=5
IccFileHandler: handleMessage what=5
IccFileHandler: handleMessage what=5
IccFileHandler: handleMessage what=5
IccFileHandler: handleMessage what=5
IccFileHandler: loadEFLinearFixed fileid(28439), path(null)
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,0000000a2fe2040000000000000000}
RIL : SIM_IO response send 6{IccIoResult sw1:0x90 sw2:0x0,000000386f4004000000000000011c}
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,000000046fad040000000000000000}
RIL : SIM_IO response send 4{IccIoResult sw1:0x6a sw2:0x82 Error: File not found}
RIL : SIM_IO response send 6{IccIoResult sw1:0x90 sw2:0x0,000000106fcb040000000000000110}
RIL : SIM_IO response send 4{IccIoResult sw1:0x6a sw2:0x82 Error: File not found}
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,000000116f46040000000000000000}
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,0000000b6f38040000000000000000}
RIL : SIM_IO response send 4{IccIoResult sw1:0x6a sw2:0x82 Error: File not found}
RIL : SIM_IO response send 4{IccIoResult sw1:0x6a sw2:0x82 Error: File not found}
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,000000286f60040000000000000000}
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,00000dac6f61040000000000000000}
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,0000000a6f62040000000000000000}
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,0000000c6fd9040000000000000000}
RIL : SIM_IO response send 4{IccIoResult sw1:0x90 sw2:0x0,0000003c6f7b040000000000000000}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,98683061691572783521}
RIL : SIM_IO response send 7{IccIoResult sw1:0x90 sw2:0x0ffffffffffffffffffffffffffff0891688116325476f8ffffffffff}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,00000002}
RIL : SIM_IO response send 6{IccIoResult sw1:0x6a sw2:0x82 Error: File not found}
RIL : SIM_IO response send 7{IccIoResult sw1:0x90 sw2:0x0,00000000000000000000000000000000}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,01804e2d56fd75354fe1ffffffffffffff}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,802f1c2c230e0100c00050}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,54f430c08054f440008054f491c08054f460c08025f040c08025f099808025f000808025f030800025f0100080130014c080130062c080130073c0801300744080130041808044f001c00044f002800064f629c08064f679808064f639008064f699008005f530c08005f501008005f510c08054f080c00054f050c00062f220c08062f210c08025f550408025f510408002f801c08002f802c08015f001c08015f0108080030216c0000302}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,ffffffffffffffffffff}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,64f01164f030ffffffffffff}
RIL : SIM_IO response send 5{IccIoResult sw1:0x90 sw2:0x0,64f00064f01064f02064f06064f07064f002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff}
RILC : respose SIM_IO number[18612345678], 11
RILC : respose SIM_IO [18612345678]:[ffffffffffffffffffffffffffff0891688116325476f8ffffffffff]
AdnRecordLoader: handleMessage what=1
AdnRecordLoader: handleMessage what=10x6f40:1[ffffffffffffffffffffffffffff0891688116325476f8ffffffffff]
AdnRecord: parseRecord len(28), footerOffset(14), numberLength(8)
AdnRecordLoader: handleMessage what=1
SIMRecords: SIMRecords EVENT_GET_MSISDN_DONE
結語
以上代碼及相關邏輯並非通用, RIL本身存在一定的複雜性, 具體情況需具體分析.
僅供參考