Android P系统设置之SettingsProvider源码分析

相关源码:
\frameworks\base\services\java\com\android\server\SystemServer.java
\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
\frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\SettingsProvider.java

\frameworks\base\packages\SettingsProvider\res\values\defaults.xml

SettingsProvider是系统设置的内容提供者。

它将设置类型分类三类:

  • Global,全局,对系统中所有用户公开,第三方App没有写权限
  • Secure,安全相关的用户偏好设置,第三方App没有写权限
  • System,用户偏好系统设置

在最新android 9.0系统中,数据存储由原来的数据库settings.db,转移保存到xml中:

  • data/system/users/0/settings_global.xml
  • data/system/users/userid/settings_system.xml
  • data/system/users/userid/settings_secure.xml

settings.db删除不再使用。

SettingsProvider启动

\frameworks\base\services\java\com\android\server\SystemServer.java
在installSystemProviders()中启动了SettingsProvider

private void startOtherServices() {
	//省略一部分代码
	//...
	
	traceBeginAndSlog("InstallSystemProviders");
	mActivityManagerService.installSystemProviders();
	// Now that SettingsProvider is ready, reactivate SQLiteCompatibilityWalFlags
	SQLiteCompatibilityWalFlags.reset();
	traceEnd();
	
	//省略一部分代码
	//...
}

\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
installSystemProviders()中三个关键的步骤,1,2,3

public final void installSystemProviders() {
	// 1、获取系统中所有的Provider,最终通过调用包管理PackageManagerService中的queryContentProviders()方法来查询所有的Provider
    List<ProviderInfo> providers;
    synchronized (this) {
        ProcessRecord app = mProcessNames.get("system", SYSTEM_UID);
        providers = generateApplicationProvidersLocked(app);
        if (providers != null) {
            for (int i=providers.size()-1; i>=0; i--) {
                ProviderInfo pi = (ProviderInfo)providers.get(i);
                if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
                    Slog.w(TAG, "Not installing system proc provider " + pi.name
                            + ": not system .apk");
                    providers.remove(i);
                }
            }
        }
    }
	// 2、调用ActivityThread中的installSystemProviders来完成Provider的安装,包括SettingsProvider
    if (providers != null) {
        mSystemThread.installSystemProviders(providers);
    }

    synchronized (this) {
        mSystemProvidersInstalled = true;
    }

    mConstants.start(mContext.getContentResolver());
    mCoreSettingsObserver = new CoreSettingsObserver(this);
    mFontScaleSettingObserver = new FontScaleSettingObserver();
    mDevelopmentSettingsObserver = new DevelopmentSettingsObserver();
    GlobalSettingsToPropertiesMapper.start(mContext.getContentResolver());

	// 3、Provider启动完成
    // Now that the settings provider is published we can consider sending
    // in a rescue party.
    RescueParty.onSettingsProviderPublished(mContext);

    //mUsageStatsService.monitorPackages();
}

其中,第二步中,installSystemProviders()会调用到SettingsProvider中的onCreate()方法。

\frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\SettingsProvider.java

@Override
public boolean onCreate() {
    Settings.setInSystemServer();

    // fail to boot if there're any backed up settings that don't have a non-null validator
    ensureAllBackedUpSystemSettingsHaveValidators();
    ensureAllBackedUpGlobalSettingsHaveValidators();
    ensureAllBackedUpSecureSettingsHaveValidators();

    synchronized (mLock) {
        mUserManager = UserManager.get(getContext());
        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
        mPackageManager = AppGlobals.getPackageManager();
        mHandlerThread = new HandlerThread(LOG_TAG,
                Process.THREAD_PRIORITY_BACKGROUND);
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper());
        mSettingsRegistry = new SettingsRegistry();
    }
    mHandler.post(() -> {
        registerBroadcastReceivers();
        startWatchingUserRestrictionChanges();
    });
    ServiceManager.addService("settings", new SettingsService(this));
    return true;
}

其中,关键的部分是:mSettingsRegistry = new SettingsRegistry();

final class SettingsRegistry {
    private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid";
    private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml";
    private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml";
    private static final String SETTINGS_FILE_SECURE = "settings_secure.xml";
    private static final String SETTINGS_FILE_SSAID = "settings_ssaid.xml";
    private static final String SSAID_USER_KEY = "userkey";

    public SettingsRegistry() {
        mHandler = new MyHandler(getContext().getMainLooper());
        // 1、对xml的修改做版本管理
        mGenerationRegistry = new GenerationRegistry(mLock);
        // 2、创建Backup,做系统备份
        mBackupManager = new BackupManager(getContext());
        // 3、迁移所有的系统设置数据
        migrateAllLegacySettingsIfNeeded();
        syncSsaidTableOnStart();
    }

    private void migrateAllLegacySettingsIfNeeded() {
        synchronized (mLock) {
            final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);.
            // 1、判断settings_global.xml是否存在,如果不存怎,就返回,不用做数据迁移
            //    所以,settings_global.xml一般都是存在,只有升级后系统第一次启动的时候才会不存在,
            //	  数据迁移,只会发生在系统升级后第一次启动的情况
            File globalFile = getSettingsFile(key);
            if (SettingsState.stateFileExists(globalFile)) {
                return;
            }

            mSettingsCreationBuildId = Build.ID;

            final long identity = Binder.clearCallingIdentity();
            try {
            	// 2、获取系统中所有的用户(多用户,一般user0)
                List<UserInfo> users = mUserManager.getUsers(true);

                final int userCount = users.size();
                for (int i = 0; i < userCount; i++) {
                    final int userId = users.get(i).id;
					// 3、关键代码,通过DatabaseHelper类创建数据库settings.db,并使用默认设置对数据库表数据初始化
                    DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
                    SQLiteDatabase database = dbHelper.getWritableDatabase();
                    migrateLegacySettingsForUserLocked(dbHelper, database, userId);
                    
					// 4、关键代码,生成和初始化xml文件
                    // Upgrade to the latest version.
                    UpgradeController upgrader = new UpgradeController(userId);
                    upgrader.upgradeIfNeededLocked();

                    // Drop from memory if not a running user.
                    if (!mUserManager.isUserRunning(new UserHandle(userId))) {
                        removeUserStateLocked(userId, false);
                    }
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }
}

重点,migrateLegacySettingsForUserLocked()和upgradeIfNeededLocked()。

DatabaseHelper类

SettingsRegistry类中的migrateAllLegacySettingsIfNeeded中执行了DatabaseHelper去创建数据库settings.db.
DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
SQLiteDatabase database = dbHelper.getWritableDatabase();
DatabaseHelper()中执行了dbNameForUser(),SQLiteOpenHelper 创建了数据库settings.db。
在settings.db数据库创建后,回调onCreate函数。onCreate()中,创建了数据的表。

class DatabaseHelper extends SQLiteOpenHelper {

	private static final String DATABASE_NAME = "settings.db";

	public DatabaseHelper(Context context, int userHandle) {
      super(context, dbNameForUser(userHandle), null, DATABASE_VERSION);
      mContext = context;
      mUserHandle = userHandle;
  	}

	static String dbNameForUser(final int userHandle) {
     // The owner gets the unadorned db name;
     if (userHandle == UserHandle.USER_SYSTEM) {
         return DATABASE_NAME;
     } else {
         // Place the database in the user-specific data tree so that it's
         // cleaned up automatically when the user is deleted.
         File databaseFile = new File(
                 Environment.getUserSystemDirectory(userHandle), DATABASE_NAME);
         // If databaseFile doesn't exist, database can be kept in memory. It's safe because the
         // database will be migrated and disposed of immediately after onCreate finishes
         if (!databaseFile.exists()) {
             Log.i(TAG, "No previous database file exists - running in in-memory mode");
             return null;
         }
         return databaseFile.getPath();
     }
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		
	   db.execSQL("CREATE TABLE system (" +
	               "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
	               "name TEXT UNIQUE ON CONFLICT REPLACE," +
	               "value TEXT" +
	               ");");
	   db.execSQL("CREATE INDEX systemIndex1 ON system (name);");
	
		// 1、创建表,createSecureTable,Secure数据表
	   createSecureTable(db);
	
	   // 2、创建表,createGlobalTable,Global数据表
	   // Only create the global table for the singleton 'owner/system' user
	   if (mUserHandle == UserHandle.USER_SYSTEM) {
	       createGlobalTable(db);
	   }
	
	   db.execSQL("CREATE TABLE bluetooth_devices (" +
	               "_id INTEGER PRIMARY KEY," +
	               "name TEXT," +
	               "addr TEXT," +
	               "channel INTEGER," +
	               "type INTEGER" +
	               ");");
	
	   db.execSQL("CREATE TABLE bookmarks (" +
	               "_id INTEGER PRIMARY KEY," +
	               "title TEXT," +
	               "folder TEXT," +
	               "intent TEXT," +
	               "shortcut INTEGER," +
	               "ordering INTEGER" +
	               ");");
	
	   db.execSQL("CREATE INDEX bookmarksIndex1 ON bookmarks (folder);");
	   db.execSQL("CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);");
	
	   // Populate bookmarks table with initial bookmarks
	   boolean onlyCore = false;
	   try {
	       onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService(
	               "package")).isOnlyCoreApps();
	   } catch (RemoteException e) {
	   }
	   if (!onlyCore) {
	       loadBookmarks(db);
	   }
	
		// 3、默认数据填充数据库
	   // Load initial volume levels into DB
	   loadVolumeLevels(db);
	
		// 4、默认数据填充数据库
	   // Load inital settings values
	   loadSettings(db);
	}
}

Settings.db数据迁移到xml中

还是继续看SettingsRegistry 中的migrateLegacySettingsForUserLocked()和upgradeIfNeededLocked(),

SettingsProvider中几个数据类型的定义:

//SettingsState.java中
public static final int SETTINGS_TYPE_GLOBAL = 0;
public static final int SETTINGS_TYPE_SYSTEM = 1;
public static final int SETTINGS_TYPE_SECURE = 2;
public static final int SETTINGS_TYPE_SSAID = 3;
public static final int SETTINGS_TYPE_MASK = 0xF0000000;
public static final int SETTINGS_TYPE_SHIFT = 28;
//SettingsProvider.java中
public static final int SETTINGS_TYPE_GLOBAL = SettingsState.SETTINGS_TYPE_GLOBAL;
public static final int SETTINGS_TYPE_SYSTEM = SettingsState.SETTINGS_TYPE_SYSTEM;
public static final int SETTINGS_TYPE_SECURE = SettingsState.SETTINGS_TYPE_SECURE;
public static final int SETTINGS_TYPE_SSAID = SettingsState.SETTINGS_TYPE_SSAID;
final class SettingsRegistry {
  private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper, SQLiteDatabase database, int userId) {
     // 1、处理System数据,	
     // Move over the system settings.
     final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
     //生成对应的SettingsState对象保存在mSettingsStates中,生成settings_system.xml
     ensureSettingsStateLocked(systemKey);
     SettingsState systemSettings = mSettingsStates.get(systemKey);
     //数据迁移,将settings.db的数据迁移到settings_system.xml中
     migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
     systemSettings.persistSyncLocked();
     
     // 2、处理Secure 数据,
     // Move over the secure settings.
     // Do this after System settings, since this is the first thing we check when deciding
     // to skip over migration from db to xml for a secondary user.
     final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
     //生成对应的SettingsState对象保存在mSettingsStates中,生成settings_secure.xml
     ensureSettingsStateLocked(secureKey);
     SettingsState secureSettings = mSettingsStates.get(secureKey);
     //数据迁移,将settings.db的数据迁移到settings_secure.xml中
     migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE);
     ensureSecureSettingAndroidIdSetLocked(secureSettings);
     secureSettings.persistSyncLocked();
     // 3、处理Global 数据,     
     // Move over the global settings if owner.
     // Do this last, since this is the first thing we check when deciding
     // to skip over migration from db to xml for owner user.
     if (userId == UserHandle.USER_SYSTEM) {
         final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId);
         //生成对应的SettingsState对象保存在mSettingsStates中,生成settings_global.xml
         ensureSettingsStateLocked(globalKey);
         SettingsState globalSettings = mSettingsStates.get(globalKey);
         //数据迁移,将settings.db的数据迁移到settings_global.xml中
         migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL);
         // If this was just created
         if (mSettingsCreationBuildId != null) {
             globalSettings.insertSettingLocked(Settings.Global.DATABASE_CREATION_BUILDID,
                     mSettingsCreationBuildId, null, true,
                     SettingsState.SYSTEM_PACKAGE_NAME);
         }
         globalSettings.persistSyncLocked();
     }

	//数据迁移完成后,是否删除settings.db,或者做一个备份
     // Drop the database as now all is moved and persisted.
     if (DROP_DATABASE_ON_MIGRATION) {
         dbHelper.dropDatabase();
     } else {
         dbHelper.backupDatabase();
     }
  }

  //ensureSettingsStateLocked是一个重要的方法,给每一个数据类型key,穿件一个对应的SettingsState对象并保存在mSettingsStates
  private void ensureSettingsStateLocked(int key) {
      if (mSettingsStates.get(key) == null) {
          final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key));
          SettingsState settingsState = new SettingsState(getContext(), mLock,
                  getSettingsFile(key), key, maxBytesPerPackage, mHandlerThread.getLooper());
          mSettingsStates.put(key, settingsState);
      }
  }

}

SettingsState中,persistSyncLocked()方法最终完成xml的数据写入。

DatabaseHelper中settings.db的数据默认值来自于\frameworks\base\packages\SettingsProvider\res\values\defaults.xml。

具体是在loadSecureSettings(),loadSetting()方法中加载的。

Provider数据读写

写数据调用接口的方法:

// Add a persistent setting to allow other apps to know the device has been provisioned.
Settings.Secure.putInt(getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 1);
        
// Enable the GPS.
// Not needed since this SDK will contain the Settings app.
Settings.Secure.putString(getContentResolver(),Settings.Secure.LOCATION_PROVIDERS_ALLOWED, LocationManager.GPS_PROVIDER);

读数据调用接口的方法:

Settings.Secure.getint(mContext.getContentResolver(),Settings.Secure.DEVICE_PROVISIONED);
Settings.Secure.getString(mContext.getContentResolver(),Settings.Secure.LOCATION_PROVIDERS_ALLOWED);

调式

1、在以下目录可以看到以下保存在xml中的值。

  • data/system/users/0/settings_global.xml
  • data/system/users/userid/settings_system.xml
  • data/system/users/userid/settings_secure.xml

2、将private static final boolean DROP_DATABASE_ON_MIGRATION = false;设置为false,可以保存settings.db数据。
为true时会删除掉。

3、在DatabaseHelper类中loadSetting()方法打印数据:

private void loadSetting(SQLiteStatement stmt, String key, Object value) {
	Log.i(TAG, "sunxiaolin,loadSetting,key=" + key + ", value=" + value.toString());
    stmt.bindString(1, key);
    stmt.bindString(2, value.toString());
    stmt.execute();
}

2019-09-12 15:08:29.271 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=screen_brightness, value=102
2019-09-12 15:08:29.271 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=screen_brightness_for_vr, value=86
2019-09-12 15:08:29.271 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=screen_brightness_mode, value=0
2019-09-12 15:08:29.271 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=accelerometer_rotation, value=0
2019-09-12 15:08:29.271 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=haptic_feedback_enabled, value=1
2019-09-12 15:08:29.271 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=notification_light_pulse, value=1
2019-09-12 15:08:29.271 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=dtmf_tone, value=1
2019-09-12 15:08:29.272 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=sound_effects_enabled, value=1
2019-09-12 15:08:29.272 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=haptic_feedback_enabled, value=1
2019-09-12 15:08:29.272 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=lockscreen_sounds_enabled, value=1
2019-09-12 15:08:29.272 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=pointer_speed, value=0
2019-09-12 15:08:29.272 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=location_providers_allowed, value=gps,network
2019-09-12 15:08:29.272 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=mock_location, value=1
2019-09-12 15:08:29.272 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=backup_enabled, value=0
2019-09-12 15:08:29.273 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=backup_transport, value=android/com.android.internal.backup.LocalTransport
2019-09-12 15:08:29.273 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=mount_play_not_snd, value=1
2019-09-12 15:08:29.273 1990-1990/? I/SettingsProvider: sunxiaolin,loadSetting,key=mount_ums_autostart, value=0

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
AndroidSettingsProvider是一个系统级应用程序,用于管理设备的设置信息。当Android系统升级时,SettingsProvider也会相应地进行升级。 首先,升级会带来一些新的设置选项。随着Android版本的更新,新的功能和特性将被引入到系统中,这些功能和特性将需要对应的设置选项来进行配置。因此,SettingsProvider需要进行升级,以支持这些新的设置选项。 其次,升级还会修复一些已知的问题和漏洞。在旧版本的SettingsProvider中可能存在一些bug或者安全漏洞,这些问题会被逐步修复和解决。升级后的SettingsProvider将包含修复后的代码,以提高系统的稳定性和安全性。 此外,升级还可能会改变SettingsProvider的数据结构或存储方式。为了满足新的需求和功能,SettingsProvider的数据存储可能需要进行调整和优化。这可能涉及到数据库表结构的更改或者数据存储的格式改变等。 最后,升级还可能会提供更好的性能和响应速度。随着系统的发展,我们对设备的性能和用户体验的要求也在不断提高。升级后的SettingsProvider可能会经过优化,以提供更快的数据查询和更新速度,从而使用户的设置操作更加流畅和高效。 综上所述,Android系统的升级会带来SettingsProvider的升级,以支持新的设置选项、修复问题和漏洞、改变数据结构和存储方式,并提供更好的性能和响应速度。这些升级将不断提高Android设备的功能和使用体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunxiaolin2016

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值