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

Commit a938a467 authored by Fyodor Kupolov's avatar Fyodor Kupolov Committed by Android (Google) Code Review
Browse files

Merge "Added GlobalSettingsToPropertiesMapper"

parents 26db21ba 77bf7207
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12245,6 +12245,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mConstants.start(mContext.getContentResolver());
        mCoreSettingsObserver = new CoreSettingsObserver(this);
        mFontScaleSettingObserver = new FontScaleSettingObserver();
        GlobalSettingsToPropertiesMapper.start(mContext.getContentResolver());
        // Now that the settings provider is published we can consider sending
        // in a rescue party.
+112 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.am;

import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.SystemProperties;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

/**
 * Maps global system settings to system properties.
 * <p>The properties are dynamically updated when settings change.
 */
class GlobalSettingsToPropertiesMapper {

    private static final String TAG = "GlobalSettingsToPropertiesMapper";

    private static final String[][] sGlobalSettingsMapping = new String[][] {
    //  List mapping entries in the following format:
    //            {Settings.Global.SETTING_NAME, "system_property_name"},
    };


    private final ContentResolver mContentResolver;
    private final String[][] mGlobalSettingsMapping;

    @VisibleForTesting
    GlobalSettingsToPropertiesMapper(ContentResolver contentResolver,
            String[][] globalSettingsMapping) {
        mContentResolver = contentResolver;
        mGlobalSettingsMapping = globalSettingsMapping;
    }

    void updatePropertiesFromGlobalSettings() {
        for (String[] entry : mGlobalSettingsMapping) {
            final String settingName = entry[0];
            final String propName = entry[1];
            Uri settingUri = Settings.Global.getUriFor(settingName);
            Preconditions.checkNotNull(settingUri, "Setting " + settingName + " not found");
            ContentObserver co = new ContentObserver(null) {
                @Override
                public void onChange(boolean selfChange) {
                    updatePropertyFromSetting(settingName, propName);
                }
            };
            updatePropertyFromSetting(settingName, propName);
            mContentResolver.registerContentObserver(settingUri, false, co);
        }
    }

    public static void start(ContentResolver contentResolver) {
        new GlobalSettingsToPropertiesMapper(contentResolver, sGlobalSettingsMapping)
                .updatePropertiesFromGlobalSettings();
    }

    private String getGlobalSetting(String name) {
        return Settings.Global.getString(mContentResolver, name);
    }

    private void setProperty(String key, String value) {
        // Check if need to clear the property
        if (value == null) {
            // It's impossible to remove system property, therefore we check previous value to
            // avoid setting an empty string if the property wasn't set.
            if (TextUtils.isEmpty(systemPropertiesGet(key))) {
                return;
            }
            value = "";
        }
        try {
            systemPropertiesSet(key, value);
        } catch (IllegalArgumentException e) {
            Slog.e(TAG, "Unable to set property " + key + " value '" + value + "'", e);
        }
    }

    @VisibleForTesting
    protected String systemPropertiesGet(String key) {
        return SystemProperties.get(key);
    }

    @VisibleForTesting
    protected void systemPropertiesSet(String key, String value) {
        SystemProperties.set(key, value);
    }

    @VisibleForTesting
    void updatePropertyFromSetting(String settingName, String propName) {
        String settingValue = getGlobalSetting(settingName);
        setProperty(propName, settingValue);
    }
}
+112 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.am;

import android.content.ContentResolver;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;

import com.android.internal.util.Preconditions;
import com.android.internal.util.test.FakeSettingsProvider;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.HashMap;
import java.util.Map;

/**
 * Tests for {@link GlobalSettingsToPropertiesMapper}
 */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class GlobalSettingsToPropertiesMapperTest {
    private static final String[][] TEST_MAPPING = new String[][] {
        {Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "TestProperty"}
    };

    private TestMapper mTestMapper;
    private MockContentResolver mMockContentResolver;

    @Before
    public void setup() {
        // Use FakeSettingsProvider to not affect global state
        mMockContentResolver = new MockContentResolver(InstrumentationRegistry.getContext());
        mMockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
        mTestMapper = new TestMapper(mMockContentResolver);
    }

    @Test
    public void testUpdatePropertiesFromGlobalSettings() {
        Settings.Global.putString(mMockContentResolver,
                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue");

        mTestMapper.updatePropertiesFromGlobalSettings();
        String propValue = mTestMapper.systemPropertiesGet("TestProperty");
        Assert.assertEquals("testValue", propValue);

        Settings.Global.putString(mMockContentResolver,
                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2");
        mTestMapper.updatePropertyFromSetting(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
                "TestProperty");
        propValue = mTestMapper.systemPropertiesGet("TestProperty");
        Assert.assertEquals("testValue2", propValue);

        Settings.Global.putString(mMockContentResolver,
                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null);
        mTestMapper.updatePropertyFromSetting(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
                "TestProperty");
        propValue = mTestMapper.systemPropertiesGet("TestProperty");
        Assert.assertEquals("", propValue);
    }

    @Test
    public void testUpdatePropertiesFromGlobalSettings_PropertyAndSettingNotPresent() {
        // Test that empty property will not not be set if setting is not set
        mTestMapper.updatePropertiesFromGlobalSettings();
        String propValue = mTestMapper.systemPropertiesGet("TestProperty");
        Assert.assertNull("Property should not be set if setting is null", propValue);
    }

    private static class TestMapper extends GlobalSettingsToPropertiesMapper {
        private final Map<String, String> mProps = new HashMap<>();

        TestMapper(ContentResolver contentResolver) {
            super(contentResolver, TEST_MAPPING);
        }

        @Override
        protected String systemPropertiesGet(String key) {
            Preconditions.checkNotNull(key);
            return mProps.get(key);
        }

        @Override
        protected void systemPropertiesSet(String key, String value) {
            Preconditions.checkNotNull(value);
            Preconditions.checkNotNull(key);
            mProps.put(key, value);
        }
    }

}