Migrate SecureSetting to use SecureSettings proxy

Improves testability

Test: atest SystemUITests
Change-Id: Ie4c23324b5f9fd138d475abe61c67e6164da5588
This commit is contained in:
Fabian Kozynski
2020-10-28 15:24:18 -04:00
parent d323c8d428
commit ffe7fcc7ff
10 changed files with 222 additions and 64 deletions

View File

@@ -89,6 +89,7 @@ import com.android.systemui.qs.SecureSetting;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
import java.util.List;
@@ -120,6 +121,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private final BroadcastDispatcher mBroadcastDispatcher;
private final Handler mMainHandler;
private final TunerService mTunerService;
private final SecureSettings mSecureSettings;
private DisplayManager.DisplayListener mDisplayListener;
private CameraAvailabilityListener mCameraListener;
private final UserTracker mUserTracker;
@@ -199,11 +201,13 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@Inject
public ScreenDecorations(Context context,
@Main Handler handler,
SecureSettings secureSettings,
BroadcastDispatcher broadcastDispatcher,
TunerService tunerService,
UserTracker userTracker) {
super(context);
mMainHandler = handler;
mSecureSettings = secureSettings;
mBroadcastDispatcher = broadcastDispatcher;
mTunerService = tunerService;
mUserTracker = userTracker;
@@ -309,7 +313,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
// Watch color inversion and invert the overlay as needed.
if (mColorInversionSetting == null) {
mColorInversionSetting = new SecureSetting(mContext, mHandler,
mColorInversionSetting = new SecureSetting(mSecureSettings, mHandler,
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
mUserTracker.getUserId()) {
@Override

View File

@@ -16,18 +16,17 @@
package com.android.systemui.qs;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings.Secure;
import com.android.systemui.statusbar.policy.Listenable;
import com.android.systemui.util.settings.SecureSettings;
/** Helper for managing a secure setting. **/
public abstract class SecureSetting extends ContentObserver implements Listenable {
private static final int DEFAULT = 0;
private final Context mContext;
private SecureSettings mSecureSettings;
private final String mSettingName;
private boolean mListening;
@@ -36,19 +35,20 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl
protected abstract void handleValueChanged(int value, boolean observedChange);
public SecureSetting(Context context, Handler handler, String settingName, int userId) {
public SecureSetting(SecureSettings secureSettings, Handler handler, String settingName,
int userId) {
super(handler);
mContext = context;
mSecureSettings = secureSettings;
mSettingName = settingName;
mUserId = userId;
}
public int getValue() {
return Secure.getIntForUser(mContext.getContentResolver(), mSettingName, DEFAULT, mUserId);
return mSecureSettings.getIntForUser(mSettingName, DEFAULT, mUserId);
}
public void setValue(int value) {
Secure.putIntForUser(mContext.getContentResolver(), mSettingName, value, mUserId);
mSecureSettings.putIntForUser(mSettingName, value, mUserId);
}
@Override
@@ -57,10 +57,10 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl
mListening = listening;
if (listening) {
mObservedValue = getValue();
mContext.getContentResolver().registerContentObserver(
Secure.getUriFor(mSettingName), false, this, mUserId);
mSecureSettings.registerContentObserverForUser(
mSecureSettings.getUriFor(mSettingName), false, this, mUserId);
} else {
mContext.getContentResolver().unregisterContentObserver(this);
mSecureSettings.unregisterContentObserver(this);
mObservedValue = DEFAULT;
}
}

View File

@@ -30,6 +30,7 @@ import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.util.settings.SecureSettings;
import dagger.Binds;
import dagger.Module;
@@ -48,14 +49,24 @@ public interface QSModule {
AutoAddTracker.Builder autoAddTrackerBuilder,
QSTileHost host,
@Background Handler handler,
SecureSettings secureSettings,
HotspotController hotspotController,
DataSaverController dataSaverController,
ManagedProfileController managedProfileController,
NightDisplayListener nightDisplayListener,
CastController castController) {
AutoTileManager manager = new AutoTileManager(context, autoAddTrackerBuilder,
host, handler, hotspotController, dataSaverController, managedProfileController,
nightDisplayListener, castController);
AutoTileManager manager = new AutoTileManager(
context,
autoAddTrackerBuilder,
host,
handler,
secureSettings,
hotspotController,
dataSaverController,
managedProfileController,
nightDisplayListener,
castController
);
manager.init();
return manager;
}

View File

@@ -36,6 +36,7 @@ import com.android.systemui.qs.SecureSetting;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.settings.SecureSettings;
import javax.inject.Inject;
@@ -62,15 +63,20 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
BatteryController batteryController
BatteryController batteryController,
SecureSettings secureSettings
) {
super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
activityStarter, qsLogger);
mBatteryController = batteryController;
mBatteryController.observe(getLifecycle(), this);
int currentUser = host.getUserContext().getUserId();
mSetting = new SecureSetting(mContext, mHandler, Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
currentUser) {
mSetting = new SecureSetting(
secureSettings,
mHandler,
Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
currentUser
) {
@Override
protected void handleValueChanged(int value, boolean observedChange) {
// mHandler is the background handler so calling this is OK

View File

@@ -39,6 +39,7 @@ import com.android.systemui.qs.SecureSetting;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.SecureSettings;
import javax.inject.Inject;
@@ -63,12 +64,13 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> {
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
UserTracker userTracker
UserTracker userTracker,
SecureSettings secureSettings
) {
super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
activityStarter, qsLogger);
mSetting = new SecureSetting(mContext, mainHandler,
mSetting = new SecureSetting(secureSettings, mainHandler,
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, userTracker.getUserId()) {
@Override
protected void handleValueChanged(int value, boolean observedChange) {

View File

@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
import com.android.systemui.util.UserAwareController;
import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
import java.util.Objects;
@@ -60,6 +61,7 @@ public class AutoTileManager implements UserAwareController {
protected final Context mContext;
protected final QSTileHost mHost;
protected final Handler mHandler;
protected final SecureSettings mSecureSettings;
protected final AutoAddTracker mAutoTracker;
private final HotspotController mHotspotController;
private final DataSaverController mDataSaverController;
@@ -71,6 +73,7 @@ public class AutoTileManager implements UserAwareController {
public AutoTileManager(Context context, AutoAddTracker.Builder autoAddTrackerBuilder,
QSTileHost host,
@Background Handler handler,
SecureSettings secureSettings,
HotspotController hotspotController,
DataSaverController dataSaverController,
ManagedProfileController managedProfileController,
@@ -78,6 +81,7 @@ public class AutoTileManager implements UserAwareController {
CastController castController) {
mContext = context;
mHost = host;
mSecureSettings = secureSettings;
mCurrentUser = mHost.getUserContext().getUser();
mAutoTracker = autoAddTrackerBuilder.setUserId(mCurrentUser.getIdentifier()).build();
mHandler = handler;
@@ -170,7 +174,7 @@ public class AutoTileManager implements UserAwareController {
String spec = split[1];
// Populate all the settings. As they may not have been added in other users
AutoAddSetting s = new AutoAddSetting(
mContext, mHandler, setting, mCurrentUser.getIdentifier(), spec);
mSecureSettings, mHandler, setting, mCurrentUser.getIdentifier(), spec);
mAutoAddSettingList.add(s);
} else {
Log.w(TAG, "Malformed item in array: " + tile);
@@ -321,13 +325,13 @@ public class AutoTileManager implements UserAwareController {
private final String mSpec;
AutoAddSetting(
Context context,
SecureSettings secureSettings,
Handler handler,
String setting,
int userId,
String tileSpec
) {
super(context, handler, setting, userId);
super(secureSettings, handler, setting, userId);
mSpec = tileSpec;
}

View File

@@ -64,6 +64,8 @@ import com.android.systemui.R.dimen;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
@@ -84,6 +86,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
private ScreenDecorations mScreenDecorations;
private WindowManager mWindowManager;
private DisplayManager mDisplayManager;
private SecureSettings mSecureSettings;
private Handler mMainHandler;
@Mock
private TunerService mTunerService;
@@ -98,6 +101,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mTestableLooper = TestableLooper.get(this);
mMainHandler = new Handler(mTestableLooper.getLooper());
mSecureSettings = new FakeSettings();
mWindowManager = mock(WindowManager.class);
WindowMetrics metrics = mContext.getSystemService(WindowManager.class)
@@ -111,7 +115,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
when(mDisplayManager.getDisplay(anyInt())).thenReturn(display);
mContext.addMockSystemService(DisplayManager.class, mDisplayManager);
mScreenDecorations = spy(new ScreenDecorations(mContext, mMainHandler,
mScreenDecorations = spy(new ScreenDecorations(mContext, mMainHandler, mSecureSettings,
mBroadcastDispatcher, mTunerService, mUserTracker) {
@Override
public void start() {

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2020 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.systemui.qs
import android.os.Handler
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.fail
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
private typealias Callback = (Int, Boolean) -> Unit
@SmallTest
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
class SecureSettingTest : SysuiTestCase() {
companion object {
private const val TEST_SETTING = "setting"
private const val USER = 0
private const val OTHER_USER = 1
private val FAIL_CALLBACK: Callback = { _, _ -> fail("Callback should not be called") }
}
private lateinit var testableLooper: TestableLooper
private lateinit var setting: SecureSetting
private lateinit var secureSettings: SecureSettings
private lateinit var callback: Callback
@Before
fun setUp() {
testableLooper = TestableLooper.get(this)
secureSettings = FakeSettings()
setting = object : SecureSetting(
secureSettings,
Handler(testableLooper.looper),
TEST_SETTING,
USER
) {
override fun handleValueChanged(value: Int, observedChange: Boolean) {
callback(value, observedChange)
}
}
// Default empty callback
callback = { _, _ -> Unit }
}
@After
fun tearDown() {
setting.isListening = false
}
@Test
fun testNotListeningByDefault() {
callback = FAIL_CALLBACK
assertThat(setting.isListening).isFalse()
secureSettings.putIntForUser(TEST_SETTING, 2, USER)
testableLooper.processAllMessages()
}
@Test
fun testChangedWhenListeningCallsCallback() {
var changed = false
callback = { _, _ -> changed = true }
setting.isListening = true
secureSettings.putIntForUser(TEST_SETTING, 2, USER)
testableLooper.processAllMessages()
assertThat(changed).isTrue()
}
@Test
fun testListensToCorrectSetting() {
callback = FAIL_CALLBACK
setting.isListening = true
secureSettings.putIntForUser("other", 2, USER)
testableLooper.processAllMessages()
}
@Test
fun testGetCorrectValue() {
secureSettings.putIntForUser(TEST_SETTING, 2, USER)
assertThat(setting.value).isEqualTo(2)
secureSettings.putIntForUser(TEST_SETTING, 4, USER)
assertThat(setting.value).isEqualTo(4)
}
@Test
fun testSetValue() {
setting.value = 5
assertThat(secureSettings.getIntForUser(TEST_SETTING, USER)).isEqualTo(5)
}
@Test
fun testChangeUser() {
setting.isListening = true
setting.setUserId(OTHER_USER)
setting.isListening = true
assertThat(setting.currentUser).isEqualTo(OTHER_USER)
}
@Test
fun testDoesntListenInOtherUsers() {
callback = FAIL_CALLBACK
setting.isListening = true
secureSettings.putIntForUser(TEST_SETTING, 3, OTHER_USER)
testableLooper.processAllMessages()
}
@Test
fun testListensToCorrectUserAfterChange() {
var changed = false
callback = { _, _ -> changed = true }
setting.isListening = true
setting.setUserId(OTHER_USER)
secureSettings.putIntForUser(TEST_SETTING, 2, OTHER_USER)
testableLooper.processAllMessages()
assertThat(changed).isTrue()
}
}

View File

@@ -29,6 +29,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
@@ -60,6 +62,7 @@ class BatterySaverTileTest : SysuiTestCase() {
private lateinit var qsLogger: QSLogger
@Mock
private lateinit var batteryController: BatteryController
private lateinit var secureSettings: SecureSettings
private lateinit var testableLooper: TestableLooper
private lateinit var tile: BatterySaverTile
@@ -70,6 +73,8 @@ class BatterySaverTileTest : SysuiTestCase() {
`when`(qsHost.userContext).thenReturn(userContext)
`when`(userContext.userId).thenReturn(USER)
secureSettings = FakeSettings()
tile = BatterySaverTile(
qsHost,
testableLooper.looper,
@@ -78,7 +83,8 @@ class BatterySaverTileTest : SysuiTestCase() {
statusBarStateController,
activityStarter,
qsLogger,
batteryController)
batteryController,
secureSettings)
}
@Test

View File

@@ -22,31 +22,22 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContentResolver;
import android.testing.TestableContext;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -61,6 +52,8 @@ import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -100,10 +93,12 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Mock private Context mUserContext;
private AutoTileManager mAutoTileManager;
private SecureSettings mSecureSettings;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mSecureSettings = new FakeSettings();
mContext.getOrCreateTestableResources().addOverride(
R.array.config_quickSettingsAutoAdd,
@@ -119,7 +114,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
when(mQsTileHost.getUserContext()).thenReturn(mUserContext);
when(mUserContext.getUser()).thenReturn(UserHandle.of(USER));
mAutoTileManager = createAutoTileManager(new MyContextWrapper(mContext));
mAutoTileManager = createAutoTileManager(mContext);
mAutoTileManager.init();
}
@@ -138,6 +133,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
CastController castController) {
return new AutoTileManager(context, autoAddTrackerBuilder, mQsTileHost,
Handler.createAsync(TestableLooper.get(this).getLooper()),
mSecureSettings,
hotspotController,
dataSaverController,
managedProfileController,
@@ -342,7 +338,6 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void testSettingTileAdded_onChanged() {
changeValue(TEST_SETTING, 1);
waitForIdleSync();
verify(mAutoAddTracker).setTileAdded(TEST_SPEC);
verify(mQsTileHost).addTile(TEST_SPEC);
}
@@ -350,7 +345,6 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void testSettingTileAddedComponentAtEnd_onChanged() {
changeValue(TEST_SETTING_COMPONENT, 1);
waitForIdleSync();
verify(mAutoAddTracker).setTileAdded(TEST_CUSTOM_SPEC);
verify(mQsTileHost).addTile(ComponentName.unflattenFromString(TEST_COMPONENT)
, /* end */ true);
@@ -359,10 +353,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void testSettingTileAdded_onlyOnce() {
changeValue(TEST_SETTING, 1);
waitForIdleSync();
TestableLooper.get(this).processAllMessages();
changeValue(TEST_SETTING, 2);
waitForIdleSync();
verify(mAutoAddTracker).setTileAdded(TEST_SPEC);
verify(mQsTileHost).addTile(TEST_SPEC);
}
@@ -370,7 +361,6 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void testSettingTileNotAdded_onChangedTo0() {
changeValue(TEST_SETTING, 0);
waitForIdleSync();
verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC);
verify(mQsTileHost, never()).addTile(TEST_SPEC);
}
@@ -380,7 +370,6 @@ public class AutoTileManagerTest extends SysuiTestCase {
when(mAutoAddTracker.isAdded(TEST_SPEC)).thenReturn(true);
changeValue(TEST_SETTING, 1);
waitForIdleSync();
verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC);
verify(mQsTileHost, never()).addTile(TEST_SPEC);
}
@@ -401,28 +390,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
// Will only notify if it's listening
private void changeValue(String key, int value) {
SecureSetting s = mAutoTileManager.getSecureSettingForKey(key);
Settings.Secure.putInt(mContext.getContentResolver(), key, value);
if (s != null && s.isListening()) {
s.onChange(false);
}
}
class MyContextWrapper extends ContextWrapper {
private TestableContentResolver mSpiedTCR;
MyContextWrapper(TestableContext context) {
super(context);
mSpiedTCR = spy(context.getContentResolver());
doNothing().when(mSpiedTCR).registerContentObserver(any(), anyBoolean(), any(),
anyInt());
doNothing().when(mSpiedTCR).unregisterContentObserver(any());
}
@Override
public ContentResolver getContentResolver() {
return mSpiedTCR;
}
mSecureSettings.putIntForUser(key, value, USER);
TestableLooper.get(this).processAllMessages();
}
}