sSystemCaches.append(userHandle, new SettingsCache(TABLE_SYSTEM)); sSecureCaches.append(userHandle, new SettingsCache(TABLE_SECURE)); sKnownMutationsInFlight.append(userHandle, new AtomicInteger(0)); } } //通过DataBaseOpenHelper获取可写DB SQLiteDatabase db = dbhelper.getWritableDatabase(); // Watch for external modifications to the database files, // keeping our caches in sync. We synchronize the observer set // separately, and of course it has to run after the db file // itself was set up by the DatabaseHelper. synchronized (sObserverInstances) { if (sObserverInstances.get(userHandle) == null) { SettingsFileObserver observer = new SettingsFileObserver(userHandle, db.getPath()); sObserverInstances.append(userHandle, observer); observer.startWatching(); } } //device第一次boot时为UserHandle生成一个对应的随机64 ID,并保存到Secure中 ensureAndroidIdIsSet(userHandle); //开启一个线程来异步将Settings几个表中(/global,/secure,/system)的内容填充到缓存当中。 startAsyncCachePopulation(userHandle);
private Cursor queryForUser(Uri url, String[] select, String where, String[] whereArgs, String sort, int forUser) { if (LOCAL_LOGV) Slog.v(TAG, "query(" + url + ") for user " + forUser); //解析content://settings/xxx, 条件语句和条件的值都Sql查询语句。 SqlArguments args = new SqlArguments(url, where, whereArgs); DatabaseHelper dbH; //通过UserHandle获取对应的DatabaseHelper,Global表属于整个设备。 dbH = getOrEstablishDatabase( TABLE_GLOBAL.equals(args.table) ? UserHandle.USER_OWNER : forUser); SQLiteDatabase db = dbH.getReadableDatabase();
// The favorites table was moved from this provider to a provider inside Home // Home still need to query this table to upgrade from pre-cupcake builds // However, a cupcake+ build with no data does not contain this table which will // cause an exception in the SQL stack. The following line is a special case to // let the caller of the query have a chance to recover and avoid the exception if (TABLE_FAVORITES.equals(args.table)) { return null; } else if (TABLE_OLD_FAVORITES.equals(args.table)) { args.table = TABLE_FAVORITES; Cursor cursor = db.rawQuery("PRAGMA table_info(favorites);", null); if (cursor != null) { boolean exists = cursor.getCount() > 0; cursor.close(); if (!exists) return null; } else { return null; } }
SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(args.table); //查表返回Cursor Cursor ret = qb.query(db, select, args.where, args.args, null, null, sort); // the default Cursor interface does not support per-user observation try { AbstractCursor c = (AbstractCursor) ret; c.setNotificationUri(getContext().getContentResolver(), url, forUser); } catch (ClassCastException e) { // details of the concrete Cursor implementation have changed and this code has // not been updated to match -- complain and fail hard. Log.wtf(TAG, "Incompatible cursor derivation!"); throw e; } return ret; }
final int callingUser = UserHandle.getCallingUserId(); if (callingUser != desiredUserHandle) { getContext().enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Not permitted to access settings for other users"); } if (LOCAL_LOGV) Slog.v(TAG, "insert(" + url + ") for user " + desiredUserHandle + " by " + callingUser); //将Uri 转换成SQL语句 SqlArguments args = new SqlArguments(url); //favorite表已经迁移,直接返回。 if (TABLE_FAVORITES.equals(args.table)) { return null; }
// Location providers的处理。 // Android的位置服务都是由一堆的provider来提供。 // Support enabling/disabling a single provider (using "+" or "-" prefix) String name = initialValues.getAsString(Settings.Secure.NAME); if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) { if (!parseProviderList(url, initialValues)) return null; }
//对于已经迁移到Global表中的Key/Value,则直接写入到Global表中。 if (name != null) { if (sSecureGlobalKeys.contains(name) || sSystemGlobalKeys.contains(name)) { if (!TABLE_GLOBAL.equals(args.table)) { if (LOCAL_LOGV) Slog.i(TAG, "Rewrite of insert() of now-global key " + name); } args.table = TABLE_GLOBAL; // next condition will rewrite the user handle } }
// Check write permissions only after determining which table the insert will touch checkWritePermissions(args); // The global table is stored under the owner, always if (TABLE_GLOBAL.equals(args.table)) { desiredUserHandle = UserHandle.USER_OWNER; } //寻找到table对应的LRU SettingsCache SettingsCache cache = cacheForTable(desiredUserHandle, args.table); String value = initialValues.getAsString(Settings.NameValueTable.VALUE); if (SettingsCache.isRedundantSetValue(cache, name, value)) { //该Key/Value在对应的SettingsCache中已经存在,直接返回对应的Uri return Uri.withAppendedPath(url, name); } //UserHandle正在操作的计数 + 1 final AtomicInteger mutationCount = sKnownMutationsInFlight.get(desiredUserHandle); mutationCount.incrementAndGet(); //获取UserHandle对应的DatabaseHelper和DB DatabaseHelper dbH = getOrEstablishDatabase(desiredUserHandle); SQLiteDatabase db = dbH.getWritableDatabase(); //插入进去 final long rowId = db.insert(args.table, null, initialValues); //UserHandle正在操作的计数 - 1 mutationCount.decrementAndGet(); //插入失败,返回空 if (rowId <= 0) return null; //保存Key/Value到SettingsCache中。 SettingsCache.populate(cache, initialValues); // before we notify if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + initialValues + " for user " + desiredUserHandle); // Note that we use the original url here, not the potentially-rewritten table name //封装Uri url = getUriFor(url, initialValues, rowId); //notify一些重要的监听者 //比如BackUpManager、ContentResolver框架、SystemProperties的监听者。 sendNotify(url, desiredUserHandle); return url;
private Bundle lookupValue(DatabaseHelper dbHelper, String table, final SettingsCache cache, String key) { if (cache == null) { Slog.e(TAG, "cache is null for user " + UserHandle.getCallingUserId() + " : key=" + key); return null; } //先尝试从SettingsCache中获取 synchronized (cache) { Bundle value = cache.get(key); if (value != null) { if (value != TOO_LARGE_TO_CACHE_MARKER) { return value; } // else we fall through and read the value from disk } else if (cache.fullyMatchesDisk()) { // Fast path (very common). Don't even try touch disk // if we know we've slurped it all in. Trying to // touch the disk would mean waiting for yaffs2 to // give us access, which could takes hundreds of // milliseconds. And we're very likely being called // from somebody's UI thread... return NULL_SETTING; } } //缓存中不存在再尝试从DB中获取,并保存到SettingsCache中。 SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = null; try { cursor = db.query(table, COLUMN_VALUE, "name=?", new String[]{key}, null, null, null, null); if (cursor != null && cursor.getCount() == 1) { cursor.moveToFirst(); return cache.putIfAbsent(key, cursor.getString(0)); } } catch (SQLiteException e) { Log.w(TAG, "settings lookup error", e); return null; } finally { if (cursor != null) cursor.close(); } cache.putIfAbsent(key, null); return NULL_SETTING; }