android读取imei原理,IMEI 的获取原理追踪

imei 是怎么生成及获取的,原理是什么,如果改码的话,怎样才是最简单的最有效的?

framework 层的接口获取

首先掉到这里

android.telephony.TelephonyManager

public String getDeviceId() {

try {

ITelephony telephony = getITelephony();

if (telephony == null)

return null;

return telephony.getDeviceId(mContext.getOpPackageName());

} catch (RemoteException ex) {

return null;

} catch (NullPointerException ex) {

return null;

}

}

在追踪会走到 GsmCdmaPhone.java 这个类里面

代码路径:

1454 @Override

1455 public String getDeviceId() {

1456 if (isPhoneTypeGsm()) {

1457 return mImei;

1458 } else {

1459 CarrierConfigManager configManager = (CarrierConfigManager)

1460 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);

1461 boolean force_imei = configManager.getConfigForSubId(getSubId())

1462 .getBoolean(CarrierConfigManager.KEY_FORCE_IMEI_BOOL);

1463 if (force_imei) return mImei;

1464

1465 String id = getMeid();

1466 if ((id == null) || id.matches("^0*$")) {

1467 loge("getDeviceId(): MEID is not initialized use ESN");

1468 id = getEsn();

1469 }

1470 return id;

1471 }

1472 }

而这个 mImei 是怎么来的?这个是回调传过来的;

237 @Override

2238 public void handleMessage(Message msg) {

2239 AsyncResult ar;

2240 Message onComplete;

2241

2242 switch (msg.what) {

2243 case EVENT_RADIO_AVAILABLE: {

2244 handleRadioAvailable();

2245 }

2246 break;

2247

2248 case EVENT_GET_DEVICE_IDENTITY_DONE:{

2249 ar = (AsyncResult)msg.obj;

2250

2251 if (ar.exception != null) {

2252 break;

2253 }

2254 String[] respId = (String[])ar.result;

2255 mImei = respId[0];

2256 mImeiSv = respId[1];

2257 mEsn = respId[2];

2258 mMeid = respId[3];

根据 EVENT_GET_DEVICE_IDENTITY_DONE 类型往上搜谁会传这个类型;

代码路径:

2200 private void handleRadioAvailable() {

2201 mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));

2202

2203 mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));

2204 mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));

2205 startLceAfterRadioIsAvailable();

2206 }

然后跟踪 mCi.getDeviceIdentity 这个函数

搜索 getDeviceIdentity 函数,会进入 RIL.java 类内

代码路径:

2804 @Override

2805 public void getDeviceIdentity(Message result) {

2806 IRadio radioProxy = getRadioProxy(result);

2807 if (radioProxy != null) {

2808 RILRequest rr = obtainRequest(RIL_REQUEST_DEVICE_IDENTITY, result,

2809 mRILDefaultWorkSource);

2810

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

2812

2813 try {

2814 radioProxy.getDeviceIdentity(rr.mSerial);

2815 } catch (RemoteException | RuntimeException e) {

2816 handleRadioProxyExceptionForRR(rr, "getDeviceIdentity", e);

2817 }

2818 }

2819 }

往下继续走 getDeviceIdentity(int) 函数,这里全局搜索,发小会走到 ril_service.cpp 类内;

源码路径:

1894 Return RadioImpl::getDeviceIdentity(int32_t serial) {

1895 #if VDBG

1896 RLOGD("getDeviceIdentity: serial %d", serial);

1897 #endif

1898 dispatchVoid(serial, mSlotId, RIL_REQUEST_DEVICE_IDENTITY);

1899 return Void();

1900 }

然后会走到 dispatchVoid 函数内;

538 bool dispatchVoid(int serial, int slotId, int request) {

539 RequestInfo *pRI = android::addRequestToList(serial, slotId, request);

540 if (pRI == NULL) {

541 return false;

542 }

543 CALL_ONREQUEST(request, NULL, 0, pRI, slotId);

544 return true;

545 }

而这里 CALL_ONREQUEST 函数的定义是

RIL_RadioFunctions *s_vendorFunctions = NULL;

#define CALL_ONREQUEST(a, b, c, d, e) s_vendorFunctions->onRequest((a), (b), (c), (d))

8486 void radio::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {

8487 using namespace android::hardware;

8488 int simCount = 1;

8489 const char *serviceNames[] = {

8490 android::RIL_getServiceName()

8491 #if (SIM_COUNT >= 2)

8492 , RIL2_SERVICE_NAME

8493 #if (SIM_COUNT >= 3)

8494 , RIL3_SERVICE_NAME

8495 #if (SIM_COUNT >= 4)

8496 , RIL4_SERVICE_NAME

8497 #endif

8498 #endif

8499 #endif

8500 };

8501

8502 #if (SIM_COUNT >= 2)

8503 simCount = SIM_COUNT;

8504 #endif

8505

8506 s_vendorFunctions = callbacks;

这里要看 RIL_RadioFunctions 的 onRequest 函数,

7119 typedef struct {

7120 int version; /* set to RIL_VERSION */

7121 RIL_RequestFunc onRequest;

7122 RIL_RadioStateRequest onStateRequest;

7123 RIL_Supports supports;

7124 RIL_Cancel onCancel;

7125 RIL_GetVersion getVersion;

7126 } RIL_RadioFunctions;

接着第 6 步,所以需要追 registerService 函数,然后会追到 ril_service.cpp 类内

代码地址:

423 extern "C" void

424 RIL_register (const RIL_RadioFunctions *callbacks) {

425 RLOGI("SIM_COUNT: %d", SIM_COUNT);

426

427 if (callbacks == NULL) {

428 RLOGE("RIL_register: RIL_RadioFunctions * null");

429 return;

430 }

431 if (callbacks->version < RIL_VERSION_MIN) {

432 RLOGE("RIL_register: version %d is to old, min version is %d",

433 callbacks->version, RIL_VERSION_MIN);

.......

memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));

.......

461 radio::registerService(&s_callbacks, s_commands);

462 RLOGI("RILHIDL called registerService");

463

464 }

可以看到 s_callbacks 来自 callbacks 所以继续往上追;

追到 rild.c 内;

代码地址:

101 int main(int argc, char **argv) {

......

213 funcs = rilInit(&s_rilEnv, argc, rilArgv);

214 RLOGD("RIL_Init rilInit completed");

215

216 RIL_register(funcs);

217

218 RLOGD("RIL_Init RIL_register completed");

219

220 if (rilUimInit) {

221 RLOGD("RIL_register_socket started");

222 RIL_register_socket(rilUimInit, RIL_SAP_SOCKET, argc, rilArgv);

223 }

在这个函数没会调用 dlsym(dlHandle, "RIL_Init"); 函数来获取句柄,可以仔细去看完整的函数代码;

所以根据 "RIL_Init" 继续往上追,可以追到 reference-ril.c 内

代码地址:

3766 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)

3767 {

3768 int ret;

3769 int fd = -1;

......

3821 return &s_callbacks;

3822 }

这个函数会返回 s_callbacks,所以看下 s_callbacks 是什么;

198 static const RIL_RadioFunctions s_callbacks = {

199 RIL_VERSION,

200 onRequest,

201 currentState,

202 onSupports,

203 onCancel,

204 getVersion

205 };

可以看到 s_callbacks 结构体的定义,所以 onRequest 函数就是 RIL_RequestFunc 函数,对应第 6 步内;

所以应该分析 s_callbacks->onRequest 函数

代码地址:

2344 static void

2345 onRequest (int request, void *data, size_t datalen, RIL_Token t)

2346 {

2347 ATResponse *p_response;

2348 int err;

2349 ......

2544 case RIL_REQUEST_GET_IMEI:

2545 p_response = NULL;

2546 err = at_send_command_numeric("AT+CGSN", &p_response);

2547

2548 if (err < 0 || p_response->success == 0) {

2549 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);

2550 } else {

2551 RIL_onRequestComplete(t, RIL_E_SUCCESS,

2552 p_response->p_intermediates->line, sizeof(char *));

2553 }

2554 at_response_free(p_response);

2555 break;

2556

这里面有很多 case ,只单看 RIL_REQUEST_GET_IMEI 可以看到 imei 的获取方式是通过 "AT+CGSN" 的命令获取的;

搞 rom 开发改码,是不是可以在 这个 case 内把要改的值给返回呢?

而 "AT+CGSN" 背后的原理是什么呢?

贴个 at_send_command_numeric 命令

而 "AT+CGSN" 背后的原理是什么呢?

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值