Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4aad0e5 authored by Hongyi Zhang's avatar Hongyi Zhang
Browse files

SettingsToPropertiesMapper integrate with DeviceConfig API

Test: Manual & Unit Test

Change-Id: Ib9a4f369ff7cae9b2b30faf44bfac986b2fd63f4
parent 1519a9a9
Loading
Loading
Loading
Loading
+26 −16
Original line number Diff line number Diff line
@@ -19,8 +19,10 @@ package com.android.server.am;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
@@ -61,13 +63,18 @@ class SettingsToPropertiesMapper {
    // Add the global setting you want to push to native level as experiment flag into this list.
    //
    // NOTE: please grant write permission system property prefix
    // with format persist.experiment.[experiment_category_name]. in system_server.te and grant read
    // permission in the corresponding .te file your feature belongs to.
    // with format persist.device_config.global_settings.[flag_name] in system_server.te and grant
    // read permission in the corresponding .te file your feature belongs to.
    @VisibleForTesting
    static final String[] sGlobalSettings = new String[] {
            Settings.Global.NATIVE_FLAGS_HEALTH_CHECK_ENABLED,
    };

    // All the flags under the listed DeviceConfig scopes will be synced to native level.
    //
    // NOTE: please grant write permission system property prefix
    // with format persist.device_config.[device_config_scope]. in system_server.te and grant read
    // permission in the corresponding .te file your feature belongs to.
    @VisibleForTesting
    static final String[] sDeviceConfigScopes = new String[] {
    };
@@ -104,19 +111,31 @@ class SettingsToPropertiesMapper {
            ContentObserver co = new ContentObserver(null) {
                @Override
                public void onChange(boolean selfChange) {
                    updatePropertyFromSetting(globalSetting, propName, true);
                    updatePropertyFromSetting(globalSetting, propName);
                }
            };

            // only updating on starting up when no native flags reset is performed during current
            // booting.
            if (!isNativeFlagsResetPerformed()) {
                updatePropertyFromSetting(globalSetting, propName, true);
                updatePropertyFromSetting(globalSetting, propName);
            }
            mContentResolver.registerContentObserver(settingUri, false, co);
        }

        // TODO: address sDeviceConfigScopes after DeviceConfig APIs are available.
        for (String deviceConfigScope : mDeviceConfigScopes) {
            DeviceConfig.addOnPropertyChangedListener(
                    deviceConfigScope,
                    AsyncTask.THREAD_POOL_EXECUTOR,
                    (String scope, String name, String value) -> {
                        String propertyName = makePropertyName(scope, name);
                        if (propertyName == null) {
                            log("unable to construct system property for " + scope + "/" + name);
                            return;
                        }
                        setProperty(propertyName, value);
                    });
        }
    }

    public static SettingsToPropertiesMapper start(ContentResolver contentResolver) {
@@ -184,15 +203,6 @@ class SettingsToPropertiesMapper {
        return propertyName;
    }

    private String getSetting(String name, boolean isGlobalSetting) {
        if (isGlobalSetting) {
            return Settings.Global.getString(mContentResolver, name);
        } else {
            // TODO: complete the code after DeviceConfig APIs implemented.
            return null;
        }
    }

    private void setProperty(String key, String value) {
        // Check if need to clear the property
        if (value == null) {
@@ -259,8 +269,8 @@ class SettingsToPropertiesMapper {
    }

    @VisibleForTesting
    void updatePropertyFromSetting(String settingName, String propName, boolean isGlobalSetting) {
        String settingValue = getSetting(settingName, isGlobalSetting);
    void updatePropertyFromSetting(String settingName, String propName) {
        String settingValue = Settings.Global.getString(mContentResolver, settingName);
        setProperty(propName, settingValue);
    }
}
+28 −6
Original line number Diff line number Diff line
@@ -41,11 +41,14 @@ import java.util.Map;

/**
 * Tests for {@link SettingsToPropertiesMapper}
 *
 *  Build/Install/Run:
 *  atest FrameworksServicesTests:SettingsToPropertiesMapperTest
 */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class SettingsToPropertiesMapperTest {
    private static final String NAME_VALID_CHARACTERS_REGEX = "^[\\w\\.\\-@:]*$";
    private static final String NAME_VALID_CHARACTERS_REGEX = "^[\\w\\-@:]*$";
    private static final String[] TEST_MAPPING = new String[] {
            Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS
    };
@@ -77,7 +80,28 @@ public class SettingsToPropertiesMapperTest {
            }
            if (!globalSetting.matches(NAME_VALID_CHARACTERS_REGEX)) {
                Assert.fail(globalSetting + " contains invalid characters. "
                        + "Only alphanumeric characters, '.', '-', '@', ':' and '_' are valid.");
                        + "Only alphanumeric characters, '-', '@', ':' and '_' are valid.");
            }
        }
    }

    @Test
    public void validateRegisteredDeviceConfigScopes() {
        HashSet<String> hashSet = new HashSet<>();
        for (String deviceConfigScope : SettingsToPropertiesMapper.sDeviceConfigScopes) {
            if (hashSet.contains(deviceConfigScope)) {
                Assert.fail("deviceConfigScope "
                        + deviceConfigScope
                        + " is registered more than once in "
                        + "SettingsToPropertiesMapper.sDeviceConfigScopes.");
            }
            hashSet.add(deviceConfigScope);
            if (TextUtils.isEmpty(deviceConfigScope)) {
                Assert.fail("empty deviceConfigScope registered.");
            }
            if (!deviceConfigScope.matches(NAME_VALID_CHARACTERS_REGEX)) {
                Assert.fail(deviceConfigScope + " contains invalid characters. "
                        + "Only alphanumeric characters, '-', '@', ':' and '_' are valid.");
            }
        }
    }
@@ -98,8 +122,7 @@ public class SettingsToPropertiesMapperTest {
                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2");
        mTestMapper.updatePropertyFromSetting(
                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
                systemPropertyName,
                true);
                systemPropertyName);
        propValue = mTestMapper.systemPropertiesGet(systemPropertyName);
        Assert.assertEquals("testValue2", propValue);

@@ -107,8 +130,7 @@ public class SettingsToPropertiesMapperTest {
                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null);
        mTestMapper.updatePropertyFromSetting(
                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
                systemPropertyName,
                true);
                systemPropertyName);
        propValue = mTestMapper.systemPropertiesGet(systemPropertyName);
        Assert.assertEquals("", propValue);
    }