安卓获取APP对应的Android id的原理分析
android_id 的生成原理是由系统生成的随机数,并与应用 app 签名,经过 HmacSHA256 算法生成的;从 android 8 以后开始就是随机的了,每个应用获取到的简要步骤;获取的方式如下所示:
android_id 的生成原理是由系统生成的随机数,并与应用 app 签名,经过 HmacSHA256 算法生成的;
从 android 8 以后开始就是随机的了,每个应用获取到的简要步骤;
获取的方式如下所示:
androidId = android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
final boolean isSelf = (userHandle == UserHandle.myUserId());
if (isSelf) {
synchronized (NameValueCache.this) {
if (mGenerationTracker != null) {
if (mGenerationTracker.isGenerationChanged()) {
if (true) {
Log.i(TAG, "Generation changed for type:"
+ mUri.getPath() + " in package:"
+ cr.getPackageName() +" and user:" + userHandle);
}
mValues.clear();
} else if (mValues.containsKey(name)) {
//如果APP已经安装第二次读取位置
Log.v(TAG, "getStringForUser clear name= " + name + " key: " + mValues.get(name));
mValues.remove(name);
// return mValues.get(name);
}
}
}
final long token = Binder.clearCallingIdentity();
try {
Log.w(TAG, "call here ------" );
b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
}
if (b != null) {
//这里 call getSecureSetting获取 value
String value = b.getString(Settings.NameValueTable.VALUE);
Log.w(TAG, "NameValueCache b.getString(Settings " + value + " isSelf " + isSelf + " needsGenerationTracker " + needsGenerationTracker);
Log.w(TAG, "NameValueCache value " + value);
// Don't update our cache for reads of other users' data
if (isSelf) {
synchronized (NameValueCache.this) {
if (needsGenerationTracker) {
MemoryIntArray array = b.getParcelable(
CALL_METHOD_TRACK_GENERATION_KEY);
final int index = b.getInt(
CALL_METHOD_GENERATION_INDEX_KEY, -1);
if (array != null && index >= 0) {
final int generation = b.getInt(
CALL_METHOD_GENERATION_KEY, 0);
if (true) {
Log.i(TAG, "Received generation tracker for type:"
+ mUri.getPath() + " in package:"
+ cr.getPackageName() + " and user:"
+ userHandle + " with index:" + index);
}
if (mGenerationTracker != null) {
mGenerationTracker.destroy();
}
mGenerationTracker = new GenerationTracker(array, index,
generation, () -> {
synchronized (NameValueCache.this) {
Log.e(TAG, "Error accessing generation"
+ " tracker - removing");
if (mGenerationTracker != null) {
GenerationTracker generationTracker =
mGenerationTracker;
mGenerationTracker = null;
generationTracker.destroy();
mValues.clear();
}
}
});
}
}
//第一次APP安装执行到这里,保存生成的Android id
mValues.put(name, value);
}
首先从缓存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
private Setting getSecureSetting(String name, int requestingUserId) {
执行到这里说明此App在缓存中不存在。在这里获取
if (isNewSsaidSetting(name)) {
PackageInfo callingPkg = getCallingPackageInfo(owningUserId);
synchronized (mLock) {
//getStringForUser -> getSecureSetting ,进入下一步生成android id
Slog.e(LOG_TAG, "getSecureSetting to getSsaidSettingLocked " + callingPkg.packageName + " owningUserId " + owningUserId);
return getSsaidSettingLocked(callingPkg, owningUserId);
}
}
}
private Setting getSsaidSettingLocked(PackageInfo callingPkg, int owningUserId) {
//首先获取APP的 userid,因为Android id 是根据 key = userid 保存在文件和settings中
String name = Integer.toString(
UserHandle.getUid(owningUserId, UserHandle.getAppId(Binder.getCallingUid())));
//获取msettings 保存的 app 的 android id 对应的 setting
final Setting ssaid = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SSAID, owningUserId,
name);
//获取 setting对应的SettingsState
final SettingsState ssaidSettings = mSettingsRegistry.getSettingsLocked(
SETTINGS_TYPE_SSAID, owningUserId);
//如果 app 对应的setting 不存在,就重新生成 走到这里生成userkey
if (ssaid == null || ssaid.isNull() || ssaid.getValue() == null) {
Slog.e(LOG_TAG, "ssaid is null . go generate====");
Setting setting = mSettingsRegistry.generateSsaidLocked(callingPkg, owningUserId);
return mascaradeSsaidSetting(ssaidSettings, setting);
}
return mascaradeSsaidSetting(ssaidSettings, ssaid);
}
上段代码主要是获取相关的app 对应的setting ,获取不到就重新生成一个。
下面就进入到真正生成Android id的相关逻辑流程
public Setting generateSsaidLocked(PackageInfo callingPkg, int userId) {
// Read the user's key from the ssaid table.
//这里获取生成Android id所用的系统随机数
Setting userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY);
if (userKeySetting == null || userKeySetting.isNull()
|| userKeySetting.getValue() == null) {
// Lazy initialize and store the user key.
//如果默认的系统key不存在,这里生成默认Android userkey
Slog.e(LOG_TAG, "generateSsaidLocked -------");
generateUserKeyLocked(userId);
userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY);
if (userKeySetting == null || userKeySetting.isNull()
|| userKeySetting.getValue() == null) {
throw new IllegalStateException("User key not accessible");
}
}
final String userKey = userKeySetting.getValue();
// Convert the user's key back to a byte array.
final byte[] keyBytes = ByteStringUtils.fromHexToByteArray(userKey);
// Validate that the key is of expected length.
// Keys are currently 32 bytes, but were once 16 bytes during Android O development.
if (keyBytes == null || (keyBytes.length != 16 && keyBytes.length != 32)) {
throw new IllegalStateException("User key invalid");
}
//下面就是对APP做相关的算法生成Android id
final Mac m;
try {
m = Mac.getInstance("HmacSHA256");
m.init(new SecretKeySpec(keyBytes, m.getAlgorithm()));
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("HmacSHA256 is not available", e);
} catch (InvalidKeyException e) {
throw new IllegalStateException("Key is corrupted", e);
}
Slog.e(LOG_TAG, "generateSsaidLocked -------Mac " + m);
// Mac each of the developer signatures.
for (int i = 0; i < callingPkg.signatures.length; i++) {
byte[] sig = callingPkg.signatures[i].toByteArray();
m.update(getLengthPrefix(sig), 0, 4);
m.update(sig);
}
// Convert result to a string for storage in settings table. Only want first 64 bits.
final String ssaid = ByteStringUtils.toHexString(m.doFinal()).substring(0, 16)
.toLowerCase(Locale.US);
// Save the ssaid in the ssaid table.
final String uid = Integer.toString(callingPkg.applicationInfo.uid);
生成新的Android id 插入到msetting表中和写入到ssid.xml中
final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
final boolean success = ssaidSettings.insertSettingLocked(uid, ssaid, null, true,
callingPkg.packageName);
if (!success) {
throw new IllegalStateException("Ssaid settings not accessible");
}
return getSettingLocked(SETTINGS_TYPE_SSAID, userId, uid);
}
Android生成 userkey 所用的生成随机数的代码如下所示。
final byte[] keyBytes1 = new byte[32];
final SecureRandom rand1 = new SecureRandom();
rand1.nextBytes(keyBytes1);
final String userKey = ByteStringUtils.toHexString(keyBytes1);
更多推荐
所有评论(0)