美文网首页
IMEI 的获取原理追踪

IMEI 的获取原理追踪

作者: that_is_this | 来源:发表于2020-04-03 19:09 被阅读0次

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

推荐个源码阅读网站:http://www.aospxref.com/
这个速度挺好的。

  1. 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;
        }
    }
  1. 在追踪会走到 GsmCdmaPhone.java 这个类里面

代码路径:

http://www.aospxref.com/android-9.0.0_r45/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaPhone.java#1455

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];
  1. 根据 EVENT_GET_DEVICE_IDENTITY_DONE 类型往上搜谁会传这个类型;

代码路径:

http://www.aospxref.com/android-9.0.0_r45/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaPhone.java

这些定义变量都在 Phone.java 类内:
路径:http://www.aospxref.com/android-9.0.0_r45/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/Phone.java#174

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 这个函数

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

代码路径:

http://www.aospxref.com/android-9.0.0_r45/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java#getRadioProxy

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      }
  1. 往下继续走 getDeviceIdentity(int) 函数,这里全局搜索,发小会走到 ril_service.cpp 类内;

源码路径:

http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/libril/ril_service.cpp

1894  Return<void> 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))

而 s_vendorFunctions 函数的来源呢?在这
代码地址:http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/libril/ril_service.cpp#8506

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;
  1. 这里要看 RIL_RadioFunctions 的 onRequest 函数,

RIL_RadioFunctions 结构体的定义是:
代码路径:http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/reference-ril/ril.h#7126

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;
  1. 接着第 6 步,所以需要追 registerService 函数,然后会追到 ril_service.cpp 类内

代码地址:

http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/libril/ril.cpp#461

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  }
  1. 可以看到 s_callbacks 来自 callbacks 所以继续往上追;

追到 rild.c 内;
代码地址:

http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/rild/rild.c#216

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"); 函数来获取句柄,可以仔细去看完整的函数代码;

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

代码地址:

http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/reference-ril/reference-ril.c#3766

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 步内;

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

代码地址:

http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/reference-ril/reference-ril.c#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  

代码地址: http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/reference-ril/reference-ril.c#2544

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

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

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

  1. 贴个 at_send_command_numeric 命令

代码地址:http://www.aospxref.com/android-9.0.0_r45/xref/hardware/ril/reference-ril/atchannel.c#816

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

相关文章

网友评论

      本文标题:IMEI 的获取原理追踪

      本文链接:https://www.haomeiwen.com/subject/fxmkphtx.html