源码的查看推荐在AndroidXRef进行查看。
1.一般我们获取android_id是通过以下的方式进行获取
Settings.System.getString(context.contentResolver, Settings.System.ANDROID_ID)
跟踪android.provider.Settings中的getString方法
private static final HashSet<String> MOVED_TO_SECURE;
static {
MOVED_TO_SECURE = new HashSet<>(30);
//(1)这里设置了android_id的常量
MOVED_TO_SECURE.add(Secure.ANDROID_ID);
MOVED_TO_SECURE.add(Secure.HTTP_PROXY);
....
// At one time in System, then Global, but now back in Secure
MOVED_TO_SECURE.add(Secure.INSTALL_NON_MARKET_APPS);
}
public static String getString(ContentResolver resolver, String name) {
return getStringForUser(resolver, name, resolver.getUserId());
}
/** @hide */
@UnsupportedAppUsage
public static String getStringForUser(ContentResolver resolver, String name,
int userHandle) {
//(2)通过判断name进行调用不同的对象的方法 ,从(1)中可以看到是MOVED_TO_SECURE包含了android_id
if (MOVED_TO_SECURE.contains(name)) {
Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+ " to android.provider.Settings.Secure, returning read-only value.");
return Secure.getStringForUser(resolver, name, userHandle);
}
if (MOVED_TO_GLOBAL.contains(name) || MOVED_TO_SECURE_THEN_GLOBAL.contains(name)) {
Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+ " to android.provider.Settings.Global, returning read-only value.");
return Global.getStringForUser(resolver, name, userHandle);
}
return sNameValueCache.getStringForUser(resolver, name, userHandle);
}
接着跟踪Secure.getStringForUser(resolver, name, userHandle)方法。这是Settings一个内部类
android.provider.Settings.Secure
public static final class Secure extends NameValueTable {
// NOTE: If you add new settings here, be sure to add them to
// com.android.providers.settings.SettingsProtoDumpUtil#dumpProtoSecureSettingsLocked.
.....
/**
* Look up a name in the database.
* @param resolver to access the database with
* @param name to look up in the table
* @return the corresponding value, or null if not present
*/
public static String getString(ContentResolver resolver, String name) {
return getStringForUser(resolver, name, resolver.getUserId());
}
/** @hide */
@UnsupportedAppUsage
public static String getStringForUser(ContentResolver resolver, String name,
int userHandle) {
if (MOVED_TO_GLOBAL.contains(name)) {
Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure"
+ " to android.provider.Settings.Global.");
return Global.getStringForUser(resolver, name, userHandle);
}
if (MOVED_TO_LOCK_SETTINGS.contains(name)) {
.......
}
//由于MOVED_TO_GLOBAL和MOVED_TO_LOCK_SETTINGS都没有包含android_id,所以调用了下面的这个方法
return sNameValueCache.getStringForUser(resolver, name, userHandle);
}
}
跟踪 android.provider.Settings.NameValueCache 中的getStringForUser方法
@UnsupportedAppUsage
public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
.....
//(1)通过mProviderHolder获取provide对象
IContentProvider cp = mProviderHolder.getProvider(cr);
// Try the fast path first, not using query(). If this
// fails (alternate Settings provider that doesn't support
// this interface?) then we fall back to the query/table
// interface.
if (mCallGetCommand != null) {
try {
....
Bundle b;
// If we're in system server and in a binder transaction we need to clear the
// calling uid. This works around code in system server that did not call
// clearCallingIdentity, previously this wasn't needed because reading settings
// did not do permission checking but thats no longer the case.
// Long term this should be removed and callers should properly call
// clearCallingIdentity or use a ContentResolver from the caller as needed.
if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
final long token = Binder.clearCallingIdentity();
try {
//(2) 通过(1)中获取的provide在这里获取android_id的值
b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
mCallGetCommand, name, args);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
mCallGetCommand, name, args);
}
if (b != null) {
......
}
// If the response Bundle is null, we fall through
// to the query interface below.
} catch (RemoteException e) {
// Not supported by the remote side? Fall through
// to query().
}
}
...
}
由以上的代码可以看到是通过provide进行获取android_id的值,接下来我们跟踪这个provide是哪里提供的
android.provider.Settings.java
private final ContentProviderHolder mProviderHolder;
// The method we'll call (or null, to not use) on the provider
// for the fast path of retrieving settings.
private final String mCallGetCommand;
private final String mCallSetCommand;
@GuardedBy("this")
private GenerationTracker mGenerationTracker;
public NameValueCache(Uri uri, String getCommand, String setCommand,
ContentProviderHolder providerHolder) {
mUri = uri;
mCallGetCommand = getCommand;
mCallSetCommand = setCommand;
//(1)NameValueCache对象初始化的时候会初始化providerHolder对象
mProviderHolder = providerHolder;
}
//(3)初始化sProviderHolder 对象
private static final ContentProviderHolder sProviderHolder =
new ContentProviderHolder(DeviceConfig.CONTENT_URI);
// Populated lazily, guarded by class object:
private static final NameValueCache sNameValueCache = new NameValueCache(
DeviceConfig.CONTENT_URI,
CALL_METHOD_GET_CONFIG,
CALL_METHOD_PUT_CONFIG,
//(2)在这里进行NameValueCache对象初始化
sProviderHolder);
//(4) android.provider.DeviceConfig.java 中的常量
public static final Uri CONTENT_URI = Uri.parse("content://" + Settings.AUTHORITY + "/config");
//(5) android.provider.Settings.java 中的常量
public static final String AUTHORITY = "settings";
以上的代码除了(4)以外都是在Settings.java中,最后我们得到“content://settings/config”
通过上面的查询可以发现,是frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java这个类提供了接口。
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
跟踪SettingsProvide.java 中的onCreate的方法
@Override
302 public boolean onCreate() {
303 Settings.setInSystemServer();
304
305 // fail to boot if there're any backed up settings that don't have a non-null validator
306 ensureAllBackedUpSystemSettingsHaveValidators();
307 ensureAllBackedUpGlobalSettingsHaveValidators();
308 ensureAllBackedUpSecureSettingsHaveValidators();
309
310 synchronized (mLock) {
311 mUserManager = UserManager.get(getContext());
312 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
313 mPackageManager = AppGlobals.getPackageManager();
314 mHandlerThread = new HandlerThread(LOG_TAG,
315 Process.THREAD_PRIORITY_BACKGROUND);
316 mHandlerThread.start();
317 mHandler = new Handler(mHandlerThread.getLooper());
//对Setting内容进行初始化
318 mSettingsRegistry = new SettingsRegistry();
319 }
320 mHandler.post(() -> {
321 registerBroadcastReceivers();
322 startWatchingUserRestrictionChanges();
323 });
324 ServiceManager.addService("settings", new SettingsService(this));
325 return true;
326 }
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java -》SettingsRegistry
public SettingsRegistry() {
2133 mHandler = new MyHandler(getContext().getMainLooper());
2134 mGenerationRegistry = new GenerationRegistry(mLock);
2135 mBackupManager = new BackupManager(getContext());
//(1)初始化所有常量
2136 migrateAllLegacySettingsIfNeeded();
2137 syncSsaidTableOnStart();
2138 }
private void migrateAllLegacySettingsIfNeeded() {
2585 synchronized (mLock) {
2586 final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
2587 File globalFile = getSettingsFile(key);
2588 if (SettingsState.stateFileExists(globalFile)) {
2589 return;
2590 }
2591
2592 mSettingsCreationBuildId = Build.ID;
2593
2594 final long identity = Binder.clearCallingIdentity();
2595 try {
2596 List<UserInfo> users = mUserManager.getUsers(true);
2597
2598 final int userCount = users.size();
2599 for (int i = 0; i < userCount; i++) {
2600 final int userId = users.get(i).id;
2601
2602 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
2603 SQLiteDatabase database = dbHelper.getWritableDatabase();
//(2)通过获取本地文件进行初始化操作
2604 migrateLegacySettingsForUserLocked(dbHelper, database, userId);
2605
2606 // Upgrade to the latest version.
2607 UpgradeController upgrader = new UpgradeController(userId);
2608 upgrader.upgradeIfNeededLocked();
2609
2610 // Drop from memory if not a running user.
2611 if (!mUserManager.isUserRunning(new UserHandle(userId))) {
2612 removeUserStateLocked(userId, false);
2613 }
2614 }
2615 } finally {
2616 Binder.restoreCallingIdentity(identity);
2617 }
2618 }
2619 }
private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper,
2636 SQLiteDatabase database, int userId) {
2637 // Move over the system settings.
2638 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
2639 ensureSettingsStateLocked(systemKey);
2640 SettingsState systemSettings = mSettingsStates.get(systemKey);
2641 migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
2642 systemSettings.persistSyncLocked();
2643
2644 // Move over the secure settings.
2645 // Do this after System settings, since this is the first thing we check when deciding
2646 // to skip over migration from db to xml for a secondary user.
2647 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
2648 ensureSettingsStateLocked(secureKey);
2649 SettingsState secureSettings = mSettingsStates.get(secureKey);
2650 migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE);
//(3)判断android_id进行初始化
2651 ensureSecureSettingAndroidIdSetLocked(secureSettings);
2652 secureSettings.persistSyncLocked();
2653
.......
2677 }
private void ensureSecureSettingAndroidIdSetLocked(SettingsState secureSettings) {
2714 Setting value = secureSettings.getSettingLocked(Settings.Secure.ANDROID_ID);
2715
2716 if (!value.isNull()) {
2717 return;
2718 }
2719
2720 final int userId = getUserIdFromKey(secureSettings.mKey);
2721
2722 final UserInfo user;
2723 final long identity = Binder.clearCallingIdentity();
2724 try {
2725 user = mUserManager.getUserInfo(userId);
2726 } finally {
2727 Binder.restoreCallingIdentity(identity);
2728 }
2729 if (user == null) {
2730 // Can happen due to races when deleting users - treat as benign.
2731 return;
2732 }
2733 //(4)这里进行了随机生成android_id并保存到本地文件中
2734 String androidId = Long.toHexString(new SecureRandom().nextLong());
2735 secureSettings.insertSettingLocked(Settings.Secure.ANDROID_ID, androidId,
2736 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
2737
2738 Slog.d(LOG_TAG, "Generated and saved new ANDROID_ID [" + androidId
2739 + "] for user " + userId);
2740
2741 // Write a drop box entry if it's a restricted profile
2742 if (user.isRestricted()) {
2743 DropBoxManager dbm = (DropBoxManager) getContext().getSystemService(
2744 Context.DROPBOX_SERVICE);
2745 if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) {
2746 dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis()
2747 + "," + DROPBOX_TAG_USERLOG + "," + androidId + "\n");
2748 }
2749 }
2750 }
在上面的流程中,通过获取本地的文件,进行对系统的一些基本的信息进行初始化,并保存到不同的文件中
android_id保存的文件路径: /data/system/users/0/settings_secure.xml
以上获取随机的android_id,并保存到本地文件之后。
我们通过provider就是通过这里的call方法去读取settings_secure.xml中的android_id的值
--------------------------------------------------android8.0后的android_id生成---------------------------------
由于在android8.0之后,应用的android_id 生成规则发生改变,不再和系统的android_id值一致,每个应用都在安装的时候拥有了自己的独特的android_id的值,并且有固定的生成规则
8.0后的android_id的生成规则也是在 frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java中的generateSsaidLocked方法中
public Setting generateSsaidLocked(PackageInfo callingPkg, int userId) {
// Read the user's key from the ssaid table.
//(1)获取系统的userkey值的setting对象
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.
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");
}
}
//(2)获取userkey的值,值的位置在/data/system/users/0/settings_ssaid.xml中的userkey的值
final String userKey = userKeySetting.getValue();
if (userKey == null || userKey.length() % 2 != 0) {
throw new IllegalStateException("User key invalid");
}
// Convert the user's key back to a byte array.
final byte[] keyBytes = HexEncoding.decode(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.length != 16 && keyBytes.length != 32) {
throw new IllegalStateException("User key invalid");
}
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);
}
// Mac each of the developer signatures.
//(3)获取应用相关的签名信息
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.
//(4) 通过以上获取的签名,userkey等信息生成独特的android_id
final String ssaid = HexEncoding.encodeToString(m.doFinal(), false /* upperCase */)
.substring(0, 16);
// Save the ssaid in the ssaid table.
final String uid = Integer.toString(callingPkg.applicationInfo.uid);
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);
}
从以上的代码中可以看到主要的生成规则和影响由于主要的用户组都是0,其中影响android_id 的就是/data/system/users/0/settings_ssaid.xml中的userkey值(这个值只会在系统第一次启动时随机,并且之后不会改变),和应用本身的签名,生成新的android_id之后,会保存在/data/system/users/0/settings_ssaid.xml中