当前位置:   article > 正文

安卓获取APP对应的Android id的原理分析_android_id和应用有关吧

android_id和应用有关吧

android_id 的生成原理是由系统生成的随机数,并与应用 app 签名,经过 HmacSHA256 算法生成的;
从 android 8 以后开始就是随机的了,每个应用获取到的简要步骤;
获取的方式如下所示:

androidId = android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
  1. public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
  2. final boolean isSelf = (userHandle == UserHandle.myUserId());
  3. if (isSelf) {
  4. synchronized (NameValueCache.this) {
  5. if (mGenerationTracker != null) {
  6. if (mGenerationTracker.isGenerationChanged()) {
  7. if (true) {
  8. Log.i(TAG, "Generation changed for type:"
  9. + mUri.getPath() + " in package:"
  10. + cr.getPackageName() +" and user:" + userHandle);
  11. }
  12. mValues.clear();
  13. } else if (mValues.containsKey(name)) {
  14. //如果APP已经安装第二次读取位置
  15. Log.v(TAG, "getStringForUser clear name= " + name + " key: " + mValues.get(name));
  16. mValues.remove(name);
  17. // return mValues.get(name);
  18. }
  19. }
  20. }
  21. final long token = Binder.clearCallingIdentity();
  22. try {
  23. Log.w(TAG, "call here ------" );
  24. b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
  25. } finally {
  26. Binder.restoreCallingIdentity(token);
  27. }
  28. } else {
  29. b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
  30. }
  31. if (b != null) {
  32. //这里 call getSecureSetting获取 value
  33. String value = b.getString(Settings.NameValueTable.VALUE);
  34. Log.w(TAG, "NameValueCache b.getString(Settings " + value + " isSelf " + isSelf + " needsGenerationTracker " + needsGenerationTracker);
  35. Log.w(TAG, "NameValueCache value " + value);
  36. // Don't update our cache for reads of other users' data
  37. if (isSelf) {
  38. synchronized (NameValueCache.this) {
  39. if (needsGenerationTracker) {
  40. MemoryIntArray array = b.getParcelable(
  41. CALL_METHOD_TRACK_GENERATION_KEY);
  42. final int index = b.getInt(
  43. CALL_METHOD_GENERATION_INDEX_KEY, -1);
  44. if (array != null && index >= 0) {
  45. final int generation = b.getInt(
  46. CALL_METHOD_GENERATION_KEY, 0);
  47. if (true) {
  48. Log.i(TAG, "Received generation tracker for type:"
  49. + mUri.getPath() + " in package:"
  50. + cr.getPackageName() + " and user:"
  51. + userHandle + " with index:" + index);
  52. }
  53. if (mGenerationTracker != null) {
  54. mGenerationTracker.destroy();
  55. }
  56. mGenerationTracker = new GenerationTracker(array, index,
  57. generation, () -> {
  58. synchronized (NameValueCache.this) {
  59. Log.e(TAG, "Error accessing generation"
  60. + " tracker - removing");
  61. if (mGenerationTracker != null) {
  62. GenerationTracker generationTracker =
  63. mGenerationTracker;
  64. mGenerationTracker = null;
  65. generationTracker.destroy();
  66. mValues.clear();
  67. }
  68. }
  69. });
  70. }
  71. }
  72. //第一次APP安装执行到这里,保存生成的Android id
  73. mValues.put(name, value);
  74. }

首先从缓存mValues变量中去找,如果没有查询到,就调用SettingsProvider的call()接口,如果call()接口也没有查询到,再调用query()接口。这里用的是call()接口,下文就以call()接口往下分析。cp.call()会调用到SettingsProvider的call()方法
APP安装后第一次尝试读取Android id ,mValues 一定为NULL,所有就会调用SettingsProvider 相关接口读取Android id。读取成功会保存到mValues缓存中。
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
接着会调用到SettingsProvider.java内部函数getSecureSetting

  1. private Setting getSecureSetting(String name, int requestingUserId) {
  2. 执行到这里说明此App在缓存中不存在。在这里获取
  3. if (isNewSsaidSetting(name)) {
  4. PackageInfo callingPkg = getCallingPackageInfo(owningUserId);
  5. synchronized (mLock) {
  6. //getStringForUser -> getSecureSetting ,进入下一步生成android id
  7. Slog.e(LOG_TAG, "getSecureSetting to getSsaidSettingLocked " + callingPkg.packageName + " owningUserId " + owningUserId);
  8. return getSsaidSettingLocked(callingPkg, owningUserId);
  9. }
  10. }
  11. }
  1. private Setting getSsaidSettingLocked(PackageInfo callingPkg, int owningUserId) {
  2. //首先获取APP的 userid,因为Android id 是根据 key = userid 保存在文件和settings中
  3. String name = Integer.toString(
  4. UserHandle.getUid(owningUserId, UserHandle.getAppId(Binder.getCallingUid())));
  5. //获取msettings 保存的 app 的 android id 对应的 setting
  6. final Setting ssaid = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SSAID, owningUserId,
  7. name);
  8. //获取 setting对应的SettingsState
  9. final SettingsState ssaidSettings = mSettingsRegistry.getSettingsLocked(
  10. SETTINGS_TYPE_SSAID, owningUserId);
  11. //如果 app 对应的setting 不存在,就重新生成 走到这里生成userkey
  12. if (ssaid == null || ssaid.isNull() || ssaid.getValue() == null) {
  13. Slog.e(LOG_TAG, "ssaid is null . go generate====");
  14. Setting setting = mSettingsRegistry.generateSsaidLocked(callingPkg, owningUserId);
  15. return mascaradeSsaidSetting(ssaidSettings, setting);
  16. }
  17. return mascaradeSsaidSetting(ssaidSettings, ssaid);
  18. }

上段代码主要是获取相关的app 对应的setting ,获取不到就重新生成一个。
下面就进入到真正生成Android id的相关逻辑流程

  1. public Setting generateSsaidLocked(PackageInfo callingPkg, int userId) {
  2. // Read the user's key from the ssaid table.
  3. //这里获取生成Android id所用的系统随机数
  4. Setting userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY);
  5. if (userKeySetting == null || userKeySetting.isNull()
  6. || userKeySetting.getValue() == null) {
  7. // Lazy initialize and store the user key.
  8. //如果默认的系统key不存在,这里生成默认Android userkey
  9. Slog.e(LOG_TAG, "generateSsaidLocked -------");
  10. generateUserKeyLocked(userId);
  11. userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY);
  12. if (userKeySetting == null || userKeySetting.isNull()
  13. || userKeySetting.getValue() == null) {
  14. throw new IllegalStateException("User key not accessible");
  15. }
  16. }
  17. final String userKey = userKeySetting.getValue();
  18. // Convert the user's key back to a byte array.
  19. final byte[] keyBytes = ByteStringUtils.fromHexToByteArray(userKey);
  20. // Validate that the key is of expected length.
  21. // Keys are currently 32 bytes, but were once 16 bytes during Android O development.
  22. if (keyBytes == null || (keyBytes.length != 16 && keyBytes.length != 32)) {
  23. throw new IllegalStateException("User key invalid");
  24. }
  25. //下面就是对APP做相关的算法生成Android id
  26. final Mac m;
  27. try {
  28. m = Mac.getInstance("HmacSHA256");
  29. m.init(new SecretKeySpec(keyBytes, m.getAlgorithm()));
  30. } catch (NoSuchAlgorithmException e) {
  31. throw new IllegalStateException("HmacSHA256 is not available", e);
  32. } catch (InvalidKeyException e) {
  33. throw new IllegalStateException("Key is corrupted", e);
  34. }
  35. Slog.e(LOG_TAG, "generateSsaidLocked -------Mac " + m);
  36. // Mac each of the developer signatures.
  37. for (int i = 0; i < callingPkg.signatures.length; i++) {
  38. byte[] sig = callingPkg.signatures[i].toByteArray();
  39. m.update(getLengthPrefix(sig), 0, 4);
  40. m.update(sig);
  41. }
  42. // Convert result to a string for storage in settings table. Only want first 64 bits.
  43. final String ssaid = ByteStringUtils.toHexString(m.doFinal()).substring(0, 16)
  44. .toLowerCase(Locale.US);
  45. // Save the ssaid in the ssaid table.
  46. final String uid = Integer.toString(callingPkg.applicationInfo.uid);
  47. 生成新的Android id 插入到msetting表中和写入到ssid.xml中
  48. final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
  49. final boolean success = ssaidSettings.insertSettingLocked(uid, ssaid, null, true,
  50. callingPkg.packageName);
  51. if (!success) {
  52. throw new IllegalStateException("Ssaid settings not accessible");
  53. }
  54. return getSettingLocked(SETTINGS_TYPE_SSAID, userId, uid);
  55. }

Android生成 userkey 所用的生成随机数的代码如下所示。

  1. final byte[] keyBytes1 = new byte[32];
  2. final SecureRandom rand1 = new SecureRandom();
  3. rand1.nextBytes(keyBytes1);
  4. final String userKey = ByteStringUtils.toHexString(keyBytes1);

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/242123
推荐阅读
相关标签
  

闽ICP备14008679号