Loading services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +9 −18 Original line number Diff line number Diff line Loading @@ -38,8 +38,9 @@ import java.util.HashSet; /** * Maps system settings to system properties. * <p>The properties are dynamically updated when settings change. * @hide */ class SettingsToPropertiesMapper { public class SettingsToPropertiesMapper { private static final String TAG = "SettingsToPropertiesMapper"; Loading Loading @@ -156,8 +157,8 @@ class SettingsToPropertiesMapper { * during current device booting. * @return */ public boolean isNativeFlagsResetPerformed() { String value = systemPropertiesGet(RESET_PERFORMED_PROPERTY); public static boolean isNativeFlagsResetPerformed() { String value = SystemProperties.get(RESET_PERFORMED_PROPERTY); return "true".equals(value); } Loading @@ -166,7 +167,7 @@ class SettingsToPropertiesMapper { * booting. * @return */ public String[] getResetNativeCategories() { public static String[] getResetNativeCategories() { if (!isNativeFlagsResetPerformed()) { return new String[0]; } Loading Loading @@ -214,7 +215,7 @@ class SettingsToPropertiesMapper { 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))) { if (TextUtils.isEmpty(SystemProperties.get(key))) { return; } value = ""; Loading @@ -224,7 +225,7 @@ class SettingsToPropertiesMapper { } try { systemPropertiesSet(key, value); SystemProperties.set(key, value); } catch (Exception e) { // Failure to set a property can be caused by SELinux denial. This usually indicates // that the property wasn't whitelisted in sepolicy. Loading @@ -250,17 +251,7 @@ class SettingsToPropertiesMapper { } @VisibleForTesting protected String systemPropertiesGet(String key) { return SystemProperties.get(key); } @VisibleForTesting protected void systemPropertiesSet(String key, String value) { SystemProperties.set(key, value); } @VisibleForTesting protected String getResetFlagsFileContent() { static String getResetFlagsFileContent() { String content = null; try { File reset_flag_file = new File(RESET_RECORD_FILE_PATH); Loading services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java→services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java +85 −76 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * Copyright (C) 2019 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. Loading @@ -16,52 +16,98 @@ package com.android.server.am; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import android.content.ContentResolver; import android.os.SystemProperties; import android.provider.Settings; import android.test.mock.MockContentResolver; import android.text.TextUtils; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.Preconditions; import com.android.internal.util.test.FakeSettingsProvider; import com.android.dx.mockito.inline.extended.ExtendedMockito; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; /** * Tests for {@link SettingsToPropertiesMapper} * * Build/Install/Run: * atest FrameworksServicesTests:SettingsToPropertiesMapperTest * Test SettingsToPropertiesMapper. */ @RunWith(AndroidJUnit4.class) @SmallTest public class SettingsToPropertiesMapperTest { private static final String NAME_VALID_CHARACTERS_REGEX = "^[\\w\\-@:]*$"; private static final String[] TEST_MAPPING = new String[] { Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS }; private TestMapper mTestMapper; private MockContentResolver mMockContentResolver; private MockitoSession mSession; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private ContentResolver mMockContentResolver; private SettingsToPropertiesMapper mTestMapper; private HashMap<String, String> mSystemSettingsMap; private HashMap<String, String> mGlobalSettingsMap; @Before public void setupForEach() { // Use FakeSettingsProvider to not affect global state mMockContentResolver = new MockContentResolver(InstrumentationRegistry.getContext()); mMockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); mTestMapper = new TestMapper(mMockContentResolver); public void setUp() throws Exception { mSession = ExtendedMockito.mockitoSession().initMocks( this) .strictness(Strictness.LENIENT) .spyStatic(SystemProperties.class) .spyStatic(Settings.Global.class) .spyStatic(SettingsToPropertiesMapper.class) .startMocking(); mSystemSettingsMap = new HashMap<>(); mGlobalSettingsMap = new HashMap<>(); // Mock SystemProperties setter and various getters doAnswer((Answer<Void>) invocationOnMock -> { String key = invocationOnMock.getArgument(0); String value = invocationOnMock.getArgument(1); mSystemSettingsMap.put(key, value); return null; } ).when(() -> SystemProperties.set(anyString(), anyString())); doAnswer((Answer<String>) invocationOnMock -> { String key = invocationOnMock.getArgument(0); String storedValue = mSystemSettingsMap.get(key); return storedValue == null ? "" : storedValue; } ).when(() -> SystemProperties.get(anyString())); // Mock Settings.Global methods doAnswer((Answer<String>) invocationOnMock -> { String key = invocationOnMock.getArgument(1); return mGlobalSettingsMap.get(key); } ).when(() -> Settings.Global.getString(any(), anyString())); mTestMapper = new SettingsToPropertiesMapper( mMockContentResolver, TEST_MAPPING, new String[] {}); } @After public void tearDown() throws Exception { mSession.finishMocking(); } @Test Loading Loading @@ -108,30 +154,27 @@ public class SettingsToPropertiesMapperTest { @Test public void testUpdatePropertiesFromSettings() { Settings.Global.putString(mMockContentResolver, Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue"); mGlobalSettingsMap.put(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue"); String systemPropertyName = "persist.device_config.global_settings." + "sqlite_compatibility_wal_flags"; mTestMapper.updatePropertiesFromSettings(); String propValue = mTestMapper.systemPropertiesGet(systemPropertyName); String propValue = mSystemSettingsMap.get(systemPropertyName); Assert.assertEquals("testValue", propValue); Settings.Global.putString(mMockContentResolver, Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2"); mGlobalSettingsMap.put(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2"); mTestMapper.updatePropertyFromSetting( Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, systemPropertyName); propValue = mTestMapper.systemPropertiesGet(systemPropertyName); propValue = mSystemSettingsMap.get(systemPropertyName); Assert.assertEquals("testValue2", propValue); Settings.Global.putString(mMockContentResolver, Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null); mGlobalSettingsMap.put(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null); mTestMapper.updatePropertyFromSetting( Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, systemPropertyName); propValue = mTestMapper.systemPropertiesGet(systemPropertyName); propValue = mSystemSettingsMap.get(systemPropertyName); Assert.assertEquals("", propValue); } Loading Loading @@ -163,71 +206,37 @@ public class SettingsToPropertiesMapperTest { public void testUpdatePropertiesFromSettings_PropertyAndSettingNotPresent() { // Test that empty property will not not be set if setting is not set mTestMapper.updatePropertiesFromSettings(); String propValue = mTestMapper.systemPropertiesGet("TestProperty"); String propValue = mSystemSettingsMap.get("TestProperty"); Assert.assertNull("Property should not be set if setting is null", propValue); } @Test public void testIsNativeFlagsResetPerformed() { mTestMapper.systemPropertiesSet("device_config.reset_performed", "true"); mSystemSettingsMap.put("device_config.reset_performed", "true"); Assert.assertTrue(mTestMapper.isNativeFlagsResetPerformed()); mTestMapper.systemPropertiesSet("device_config.reset_performed", "false"); mSystemSettingsMap.put("device_config.reset_performed", "false"); Assert.assertFalse(mTestMapper.isNativeFlagsResetPerformed()); mTestMapper.systemPropertiesSet("device_config.reset_performed", ""); mSystemSettingsMap.put("device_config.reset_performed", ""); Assert.assertFalse(mTestMapper.isNativeFlagsResetPerformed()); } @Test public void testGetResetNativeCategories() { mTestMapper.systemPropertiesSet("device_config.reset_performed", ""); Assert.assertEquals(mTestMapper.getResetNativeCategories().length, 0); doReturn("persist.device_config.category1.flag;" + "persist.device_config.category2.flag;persist.device_config.category3.flag;" + "persist.device_config.category3.flag2") .when(() -> SettingsToPropertiesMapper.getResetFlagsFileContent()); mTestMapper.systemPropertiesSet("device_config.reset_performed", "true"); mTestMapper.setFileContent(""); mSystemSettingsMap.put("device_config.reset_performed", ""); Assert.assertEquals(mTestMapper.getResetNativeCategories().length, 0); mTestMapper.systemPropertiesSet("device_config.reset_performed", "true"); mTestMapper.setFileContent("persist.device_config.category1.flag;" + "persist.device_config.category2.flag;persist.device_config.category3.flag;" + "persist.device_config.category3.flag2"); mSystemSettingsMap.put("device_config.reset_performed", "true"); List<String> categories = Arrays.asList(mTestMapper.getResetNativeCategories()); Assert.assertEquals(3, categories.size()); Assert.assertTrue(categories.contains("category1")); Assert.assertTrue(categories.contains("category2")); Assert.assertTrue(categories.contains("category3")); } private static class TestMapper extends SettingsToPropertiesMapper { private final Map<String, String> mProps = new HashMap<>(); private String mFileContent = ""; TestMapper(ContentResolver contentResolver) { super(contentResolver, TEST_MAPPING, new String[] {}); } @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); } protected void setFileContent(String fileContent) { mFileContent = fileContent; } @Override protected String getResetFlagsFileContent() { return mFileContent; } } } Loading
services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +9 −18 Original line number Diff line number Diff line Loading @@ -38,8 +38,9 @@ import java.util.HashSet; /** * Maps system settings to system properties. * <p>The properties are dynamically updated when settings change. * @hide */ class SettingsToPropertiesMapper { public class SettingsToPropertiesMapper { private static final String TAG = "SettingsToPropertiesMapper"; Loading Loading @@ -156,8 +157,8 @@ class SettingsToPropertiesMapper { * during current device booting. * @return */ public boolean isNativeFlagsResetPerformed() { String value = systemPropertiesGet(RESET_PERFORMED_PROPERTY); public static boolean isNativeFlagsResetPerformed() { String value = SystemProperties.get(RESET_PERFORMED_PROPERTY); return "true".equals(value); } Loading @@ -166,7 +167,7 @@ class SettingsToPropertiesMapper { * booting. * @return */ public String[] getResetNativeCategories() { public static String[] getResetNativeCategories() { if (!isNativeFlagsResetPerformed()) { return new String[0]; } Loading Loading @@ -214,7 +215,7 @@ class SettingsToPropertiesMapper { 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))) { if (TextUtils.isEmpty(SystemProperties.get(key))) { return; } value = ""; Loading @@ -224,7 +225,7 @@ class SettingsToPropertiesMapper { } try { systemPropertiesSet(key, value); SystemProperties.set(key, value); } catch (Exception e) { // Failure to set a property can be caused by SELinux denial. This usually indicates // that the property wasn't whitelisted in sepolicy. Loading @@ -250,17 +251,7 @@ class SettingsToPropertiesMapper { } @VisibleForTesting protected String systemPropertiesGet(String key) { return SystemProperties.get(key); } @VisibleForTesting protected void systemPropertiesSet(String key, String value) { SystemProperties.set(key, value); } @VisibleForTesting protected String getResetFlagsFileContent() { static String getResetFlagsFileContent() { String content = null; try { File reset_flag_file = new File(RESET_RECORD_FILE_PATH); Loading
services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java→services/tests/mockingservicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java +85 −76 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * Copyright (C) 2019 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. Loading @@ -16,52 +16,98 @@ package com.android.server.am; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import android.content.ContentResolver; import android.os.SystemProperties; import android.provider.Settings; import android.test.mock.MockContentResolver; import android.text.TextUtils; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.Preconditions; import com.android.internal.util.test.FakeSettingsProvider; import com.android.dx.mockito.inline.extended.ExtendedMockito; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; /** * Tests for {@link SettingsToPropertiesMapper} * * Build/Install/Run: * atest FrameworksServicesTests:SettingsToPropertiesMapperTest * Test SettingsToPropertiesMapper. */ @RunWith(AndroidJUnit4.class) @SmallTest public class SettingsToPropertiesMapperTest { private static final String NAME_VALID_CHARACTERS_REGEX = "^[\\w\\-@:]*$"; private static final String[] TEST_MAPPING = new String[] { Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS }; private TestMapper mTestMapper; private MockContentResolver mMockContentResolver; private MockitoSession mSession; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private ContentResolver mMockContentResolver; private SettingsToPropertiesMapper mTestMapper; private HashMap<String, String> mSystemSettingsMap; private HashMap<String, String> mGlobalSettingsMap; @Before public void setupForEach() { // Use FakeSettingsProvider to not affect global state mMockContentResolver = new MockContentResolver(InstrumentationRegistry.getContext()); mMockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); mTestMapper = new TestMapper(mMockContentResolver); public void setUp() throws Exception { mSession = ExtendedMockito.mockitoSession().initMocks( this) .strictness(Strictness.LENIENT) .spyStatic(SystemProperties.class) .spyStatic(Settings.Global.class) .spyStatic(SettingsToPropertiesMapper.class) .startMocking(); mSystemSettingsMap = new HashMap<>(); mGlobalSettingsMap = new HashMap<>(); // Mock SystemProperties setter and various getters doAnswer((Answer<Void>) invocationOnMock -> { String key = invocationOnMock.getArgument(0); String value = invocationOnMock.getArgument(1); mSystemSettingsMap.put(key, value); return null; } ).when(() -> SystemProperties.set(anyString(), anyString())); doAnswer((Answer<String>) invocationOnMock -> { String key = invocationOnMock.getArgument(0); String storedValue = mSystemSettingsMap.get(key); return storedValue == null ? "" : storedValue; } ).when(() -> SystemProperties.get(anyString())); // Mock Settings.Global methods doAnswer((Answer<String>) invocationOnMock -> { String key = invocationOnMock.getArgument(1); return mGlobalSettingsMap.get(key); } ).when(() -> Settings.Global.getString(any(), anyString())); mTestMapper = new SettingsToPropertiesMapper( mMockContentResolver, TEST_MAPPING, new String[] {}); } @After public void tearDown() throws Exception { mSession.finishMocking(); } @Test Loading Loading @@ -108,30 +154,27 @@ public class SettingsToPropertiesMapperTest { @Test public void testUpdatePropertiesFromSettings() { Settings.Global.putString(mMockContentResolver, Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue"); mGlobalSettingsMap.put(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue"); String systemPropertyName = "persist.device_config.global_settings." + "sqlite_compatibility_wal_flags"; mTestMapper.updatePropertiesFromSettings(); String propValue = mTestMapper.systemPropertiesGet(systemPropertyName); String propValue = mSystemSettingsMap.get(systemPropertyName); Assert.assertEquals("testValue", propValue); Settings.Global.putString(mMockContentResolver, Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2"); mGlobalSettingsMap.put(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2"); mTestMapper.updatePropertyFromSetting( Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, systemPropertyName); propValue = mTestMapper.systemPropertiesGet(systemPropertyName); propValue = mSystemSettingsMap.get(systemPropertyName); Assert.assertEquals("testValue2", propValue); Settings.Global.putString(mMockContentResolver, Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null); mGlobalSettingsMap.put(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null); mTestMapper.updatePropertyFromSetting( Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, systemPropertyName); propValue = mTestMapper.systemPropertiesGet(systemPropertyName); propValue = mSystemSettingsMap.get(systemPropertyName); Assert.assertEquals("", propValue); } Loading Loading @@ -163,71 +206,37 @@ public class SettingsToPropertiesMapperTest { public void testUpdatePropertiesFromSettings_PropertyAndSettingNotPresent() { // Test that empty property will not not be set if setting is not set mTestMapper.updatePropertiesFromSettings(); String propValue = mTestMapper.systemPropertiesGet("TestProperty"); String propValue = mSystemSettingsMap.get("TestProperty"); Assert.assertNull("Property should not be set if setting is null", propValue); } @Test public void testIsNativeFlagsResetPerformed() { mTestMapper.systemPropertiesSet("device_config.reset_performed", "true"); mSystemSettingsMap.put("device_config.reset_performed", "true"); Assert.assertTrue(mTestMapper.isNativeFlagsResetPerformed()); mTestMapper.systemPropertiesSet("device_config.reset_performed", "false"); mSystemSettingsMap.put("device_config.reset_performed", "false"); Assert.assertFalse(mTestMapper.isNativeFlagsResetPerformed()); mTestMapper.systemPropertiesSet("device_config.reset_performed", ""); mSystemSettingsMap.put("device_config.reset_performed", ""); Assert.assertFalse(mTestMapper.isNativeFlagsResetPerformed()); } @Test public void testGetResetNativeCategories() { mTestMapper.systemPropertiesSet("device_config.reset_performed", ""); Assert.assertEquals(mTestMapper.getResetNativeCategories().length, 0); doReturn("persist.device_config.category1.flag;" + "persist.device_config.category2.flag;persist.device_config.category3.flag;" + "persist.device_config.category3.flag2") .when(() -> SettingsToPropertiesMapper.getResetFlagsFileContent()); mTestMapper.systemPropertiesSet("device_config.reset_performed", "true"); mTestMapper.setFileContent(""); mSystemSettingsMap.put("device_config.reset_performed", ""); Assert.assertEquals(mTestMapper.getResetNativeCategories().length, 0); mTestMapper.systemPropertiesSet("device_config.reset_performed", "true"); mTestMapper.setFileContent("persist.device_config.category1.flag;" + "persist.device_config.category2.flag;persist.device_config.category3.flag;" + "persist.device_config.category3.flag2"); mSystemSettingsMap.put("device_config.reset_performed", "true"); List<String> categories = Arrays.asList(mTestMapper.getResetNativeCategories()); Assert.assertEquals(3, categories.size()); Assert.assertTrue(categories.contains("category1")); Assert.assertTrue(categories.contains("category2")); Assert.assertTrue(categories.contains("category3")); } private static class TestMapper extends SettingsToPropertiesMapper { private final Map<String, String> mProps = new HashMap<>(); private String mFileContent = ""; TestMapper(ContentResolver contentResolver) { super(contentResolver, TEST_MAPPING, new String[] {}); } @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); } protected void setFileContent(String fileContent) { mFileContent = fileContent; } @Override protected String getResetFlagsFileContent() { return mFileContent; } } }