diff --git a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java index d3950ee1396..5c2dec21810 100644 --- a/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java +++ b/src/com/android/settings/display/DeviceStateAutoRotateSettingController.java @@ -35,7 +35,6 @@ import com.android.settings.core.TogglePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManager; -import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; import com.android.settingslib.search.SearchIndexableRaw; import java.util.List; @@ -46,7 +45,7 @@ public class DeviceStateAutoRotateSettingController extends TogglePreferenceCont private TwoStatePreference mPreference; - private final DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager; + private final DeviceStateAutoRotateSettingManager mAutoRotateSettingsManager; private final int mOrder; private final DeviceStateAutoRotateSettingManager.DeviceStateAutoRotateSettingListener mDeviceStateAutoRotateSettingListener = () -> updateState(mPreference); @@ -62,7 +61,8 @@ public class DeviceStateAutoRotateSettingController extends TogglePreferenceCont mMetricsFeatureProvider = metricsFeatureProvider; mDeviceState = deviceState; mDeviceStateDescription = deviceStateDescription; - mAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(context); + mAutoRotateSettingsManager = + DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(context); mOrder = order; } diff --git a/src/com/android/settings/display/DeviceStateAutoRotateSettingManagerProvider.kt b/src/com/android/settings/display/DeviceStateAutoRotateSettingManagerProvider.kt new file mode 100644 index 00000000000..906ffe4b566 --- /dev/null +++ b/src/com/android/settings/display/DeviceStateAutoRotateSettingManagerProvider.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2025 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.settings.display + +import android.content.Context +import android.hardware.devicestate.DeviceStateManager +import android.os.Build +import android.os.Handler +import android.os.Looper +import com.android.internal.annotations.VisibleForTesting +import com.android.settingslib.devicestate.AndroidSecureSettings +import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManager +import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManagerProvider.createInstance +import com.android.settingslib.devicestate.PosturesHelper +import com.android.settingslib.utils.ThreadUtils +import com.android.window.flags.Flags + +/** + * Provides appropriate instance of [DeviceStateAutoRotateSettingManager], based on the value of + * [Flags.FLAG_ENABLE_DEVICE_STATE_AUTO_ROTATE_SETTING_REFACTOR]. + */ +object DeviceStateAutoRotateSettingManagerProvider { + private var nullableSingletonSettingManager: DeviceStateAutoRotateSettingManager? = null + + /** + * Provides a singleton instance of [DeviceStateAutoRotateSettingManager], based on the + * value of[Flags.FLAG_ENABLE_DEVICE_STATE_AUTO_ROTATE_SETTING_REFACTOR]. It is supposed to + * be used by apps that don't support dagger to provide and manager instance. + */ + @JvmStatic + fun getSingletonInstance(context: Context) = + nullableSingletonSettingManager ?: createInstance( + context, + ThreadUtils.getBackgroundExecutor(), + AndroidSecureSettings(context.contentResolver), + Handler(Looper.getMainLooper()), + PosturesHelper(context, context.getSystemService(DeviceStateManager::class.java)) + ).also { + nullableSingletonSettingManager = it + } + + /** Resets the singleton instance of [DeviceStateAutoRotateSettingManager]. */ + @JvmStatic + @VisibleForTesting + fun resetInstance() { + nullableSingletonSettingManager = null + } +} diff --git a/src/com/android/settings/display/DeviceStateAutoRotationHelper.java b/src/com/android/settings/display/DeviceStateAutoRotationHelper.java index 3bf9def2316..7b285248e1c 100644 --- a/src/com/android/settings/display/DeviceStateAutoRotationHelper.java +++ b/src/com/android/settings/display/DeviceStateAutoRotationHelper.java @@ -16,6 +16,8 @@ package com.android.settings.display; +import static com.android.settingslib.devicestate.DeviceStateAutoRotateSettingUtils.isDeviceStateRotationLockEnabled; + import android.content.Context; import android.util.Log; @@ -25,7 +27,6 @@ import com.android.internal.view.RotationPolicy; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; import com.android.settingslib.devicestate.SettableDeviceState; import com.android.settingslib.search.SearchIndexableRaw; @@ -51,8 +52,8 @@ public class DeviceStateAutoRotationHelper { static ImmutableList createPreferenceControllers( Context context) { - List settableDeviceStates = DeviceStateRotationLockSettingsManager - .getInstance(context).getSettableDeviceStates(); + List settableDeviceStates = DeviceStateAutoRotateSettingManagerProvider + .getSingletonInstance(context).getSettableDeviceStates(); int numDeviceStates = settableDeviceStates.size(); if (numDeviceStates == 0) { return ImmutableList.of(); @@ -99,7 +100,7 @@ public class DeviceStateAutoRotationHelper { /** Returns whether the device state based auto-rotation settings are enabled. */ public static boolean isDeviceStateRotationEnabled(Context context) { return RotationPolicy.isRotationLockToggleVisible(context) - && DeviceStateRotationLockSettingsManager.isDeviceStateRotationLockEnabled(context); + && isDeviceStateRotationLockEnabled(context); } /** @@ -108,6 +109,6 @@ public class DeviceStateAutoRotationHelper { */ public static boolean isDeviceStateRotationEnabledForA11y(Context context) { return RotationPolicy.isRotationSupported(context) - && DeviceStateRotationLockSettingsManager.isDeviceStateRotationLockEnabled(context); + && isDeviceStateRotationLockEnabled(context); } } diff --git a/src/com/android/settings/display/SmartAutoRotateController.java b/src/com/android/settings/display/SmartAutoRotateController.java index c99b2f853ca..4bc28ff41e0 100644 --- a/src/com/android/settings/display/SmartAutoRotateController.java +++ b/src/com/android/settings/display/SmartAutoRotateController.java @@ -47,7 +47,6 @@ import com.android.settings.core.TogglePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManager; -import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; /** * SmartAutoRotateController controls whether auto rotation is enabled @@ -75,7 +74,7 @@ public class SmartAutoRotateController extends TogglePreferenceController implem } }; - private final DeviceStateRotationLockSettingsManager mDeviceStateAutoRotateSettingsManager; + private final DeviceStateAutoRotateSettingManager mDeviceStateAutoRotateSettingsManager; private final DeviceStateAutoRotateSettingManager.DeviceStateAutoRotateSettingListener mDeviceStateAutoRotateSettingListener = () -> updateState(mPreference); private RotationPolicy.RotationPolicyListener mRotationPolicyListener; @@ -85,8 +84,9 @@ public class SmartAutoRotateController extends TogglePreferenceController implem mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); mPrivacyManager = SensorPrivacyManager.getInstance(context); mPowerManager = context.getSystemService(PowerManager.class); - mDeviceStateAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance( - context); + mDeviceStateAutoRotateSettingsManager = + DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance( + context); } @Override diff --git a/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java index c98ad3df5a3..88623ac6889 100644 --- a/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/LockScreenRotationPreferenceControllerTest.java @@ -16,9 +16,14 @@ package com.android.settings.accessibility; +import static com.android.settings.testutils.DeviceStateAutoRotateSettingTestUtils.setDeviceStateRotationLockEnabled; + import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + import android.content.Context; +import android.content.res.Resources; import android.os.UserHandle; import android.provider.Settings; @@ -26,12 +31,14 @@ import androidx.preference.SwitchPreference; import com.android.internal.view.RotationPolicy; import com.android.settings.core.BasePreferenceController; -import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; import com.android.settings.testutils.shadow.ShadowRotationPolicy; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @@ -41,48 +48,45 @@ import org.robolectric.annotation.Config; com.android.settings.testutils.shadow.ShadowSystemSettings.class, }) public class LockScreenRotationPreferenceControllerTest { - + @Mock + private Resources mResources; private Context mContext; private SwitchPreference mPreference; private LockScreenRotationPreferenceController mController; @Before public void setUp() { - mContext = RuntimeEnvironment.application; + MockitoAnnotations.initMocks(this); + mContext = Mockito.spy(RuntimeEnvironment.application); mPreference = new SwitchPreference(mContext); + when(mContext.getResources()).thenReturn(mResources); + mController = new LockScreenRotationPreferenceController(mContext, "lock_screen"); } @Test - @Config(shadows = { - ShadowRotationPolicy.class, - ShadowDeviceStateRotationLockSettingsManager.class - }) + @Config(shadows = {ShadowRotationPolicy.class}) public void getAvailabilityStatus_supportedRotation_shouldReturnAvailable() { ShadowRotationPolicy.setRotationSupported(true /* supported */); + setDeviceStateRotationLockEnabled(false, mResources); assertThat(mController.getAvailabilityStatus()).isEqualTo( BasePreferenceController.AVAILABLE); } @Test - @Config(shadows = { - ShadowRotationPolicy.class, - ShadowDeviceStateRotationLockSettingsManager.class - }) + @Config(shadows = {ShadowRotationPolicy.class}) public void getAvailabilityStatus_deviceStateRotationEnabled_returnsUnsupported() { ShadowRotationPolicy.setRotationSupported(true /* supported */); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + setDeviceStateRotationLockEnabled(true, mResources); assertThat(mController.getAvailabilityStatus()).isEqualTo( BasePreferenceController.UNSUPPORTED_ON_DEVICE); } @Test - @Config(shadows = { - ShadowRotationPolicy.class, - ShadowDeviceStateRotationLockSettingsManager.class - }) public void getAvailabilityStatus_unsupportedRotation_shouldReturnUnsupportedOnDevice() { + @Config(shadows = {ShadowRotationPolicy.class}) + public void getAvailabilityStatus_unsupportedRotation_shouldReturnUnsupportedOnDevice() { ShadowRotationPolicy.setRotationSupported(false /* supported */); assertThat(mController.getAvailabilityStatus()).isEqualTo( diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragmentTest.java b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragmentTest.java index d1c32a2281f..6fce9a83390 100644 --- a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragmentTest.java +++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateDetailsFragmentTest.java @@ -39,7 +39,6 @@ import android.hardware.devicestate.DeviceStateManager; import com.android.settings.R; import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; import org.junit.Before; import org.junit.Test; @@ -144,16 +143,15 @@ public class DeviceStateAutoRotateDetailsFragmentTest { } private void enableDeviceStateSettableRotationStates(String[] settableStates, - String[] settableStatesDescriptions) { + String[] settableStatesDescriptions) { when(mResources.getStringArray( com.android.internal.R.array.config_perDeviceStateRotationLockDefaults)).thenReturn( settableStates); when(mResources.getStringArray( R.array.config_settableAutoRotationDeviceStatesDescriptions)).thenReturn( settableStatesDescriptions); - DeviceStateRotationLockSettingsManager.resetInstance(); - DeviceStateRotationLockSettingsManager.getInstance(mContext) - .resetStateForTesting(mResources); + DeviceStateAutoRotateSettingManagerProvider.resetInstance(); + when(mContext.getResources()).thenReturn(mResources); } // Sets up posture mappings for PosturesHelper diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateOverviewControllerTest.java b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateOverviewControllerTest.java index a5416e70413..4c2c694a4bd 100644 --- a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateOverviewControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateOverviewControllerTest.java @@ -18,30 +18,48 @@ package com.android.settings.display; import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; +import static com.android.settings.testutils.DeviceStateAutoRotateSettingTestUtils.setDeviceStateRotationLockEnabled; import static com.google.common.truth.Truth.assertThat; -import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.res.Resources; + import com.android.settings.testutils.shadow.ShadowRotationPolicy; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowRotationPolicy.class, ShadowDeviceStateRotationLockSettingsManager.class}) +@Config(shadows = {ShadowRotationPolicy.class}) public class DeviceStateAutoRotateOverviewControllerTest { + @Mock + private Resources mResources; + private DeviceStateAutoRotateOverviewController mController; - private final DeviceStateAutoRotateOverviewController mController = - new DeviceStateAutoRotateOverviewController( - RuntimeEnvironment.application, "device_state_auto_rotate"); + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + Context context = Mockito.spy(RuntimeEnvironment.application); + when(context.getResources()).thenReturn(mResources); + + mController = new DeviceStateAutoRotateOverviewController( + context, "device_state_auto_rotate"); + } @Test public void getAvailabilityStatus_rotationAndDeviceStateRotationEnabled_returnsAvailable() { ShadowRotationPolicy.setRotationSupported(true); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + setDeviceStateRotationLockEnabled(true, mResources); int availability = mController.getAvailabilityStatus(); @@ -51,7 +69,7 @@ public class DeviceStateAutoRotateOverviewControllerTest { @Test public void getAvailabilityStatus_rotationNotSupported_returnsUnsupportedOnDevice() { ShadowRotationPolicy.setRotationSupported(false); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + setDeviceStateRotationLockEnabled(true, mResources); int availability = mController.getAvailabilityStatus(); @@ -61,7 +79,7 @@ public class DeviceStateAutoRotateOverviewControllerTest { @Test public void getAvailabilityStatus_deviceStateRotationNotSupported_returnsUnsupportedOnDevice() { ShadowRotationPolicy.setRotationSupported(true); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false); + setDeviceStateRotationLockEnabled(false, mResources); int availability = mController.getAvailabilityStatus(); diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java index cb1be85f881..63a4af21e91 100644 --- a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingControllerTest.java @@ -18,14 +18,17 @@ package com.android.settings.display; import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; +import static com.android.settings.testutils.DeviceStateAutoRotateSettingTestUtils.setDeviceStateRotationLockEnabled; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.settings.SettingsEnums; import android.content.Context; +import android.content.res.Resources; import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; @@ -34,10 +37,9 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; import com.android.settings.testutils.shadow.ShadowRotationPolicy; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; +import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManager; import com.android.settingslib.search.SearchIndexableRaw; import org.junit.Before; @@ -54,10 +56,7 @@ import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) -@Config(shadows = { - ShadowRotationPolicy.class, - ShadowDeviceStateRotationLockSettingsManager.class -}) +@Config(shadows = {ShadowRotationPolicy.class}) public class DeviceStateAutoRotateSettingControllerTest { private static final DeviceState DEFAULT_DEVICE_STATE = new DeviceState( @@ -66,10 +65,11 @@ public class DeviceStateAutoRotateSettingControllerTest { private static final int DEFAULT_ORDER = -10; private final Context mContext = Mockito.spy(RuntimeEnvironment.application); - private DeviceStateRotationLockSettingsManager mAutoRotateSettingsManager; + private DeviceStateAutoRotateSettingManager mAutoRotateSettingsManager; @Mock private MetricsFeatureProvider mMetricsFeatureProvider; @Mock private DeviceStateManager mDeviceStateManager; + @Mock private Resources mResources; private DeviceStateAutoRotateSettingController mController; @@ -78,11 +78,14 @@ public class DeviceStateAutoRotateSettingControllerTest { MockitoAnnotations.initMocks(this); doReturn(mContext).when(mContext).getApplicationContext(); + when(mContext.getResources()).thenReturn(mResources); doReturn(mDeviceStateManager).when(mContext).getSystemService(DeviceStateManager.class); doReturn(List.of(DEFAULT_DEVICE_STATE)).when( mDeviceStateManager).getSupportedDeviceStates(); + setDeviceStateRotationLockEnabled(false, mResources); mAutoRotateSettingsManager = - DeviceStateRotationLockSettingsManager.getInstance(mContext); + DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(mContext); + mController = new DeviceStateAutoRotateSettingController( mContext, DEFAULT_DEVICE_STATE.getIdentifier(), @@ -108,7 +111,7 @@ public class DeviceStateAutoRotateSettingControllerTest { @Test public void getAvailabilityStatus_rotationAndDeviceStateRotationEnabled_returnsAvailable() { ShadowRotationPolicy.setRotationSupported(true); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + setDeviceStateRotationLockEnabled(true, mResources); int availability = mController.getAvailabilityStatus(); @@ -118,7 +121,7 @@ public class DeviceStateAutoRotateSettingControllerTest { @Test public void getAvailabilityStatus_deviceStateRotationDisabled_returnsUnsupported() { ShadowRotationPolicy.setRotationSupported(true); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false); + setDeviceStateRotationLockEnabled(false, mResources); int availability = mController.getAvailabilityStatus(); @@ -128,7 +131,7 @@ public class DeviceStateAutoRotateSettingControllerTest { @Test public void getAvailabilityStatus_rotationDisabled_returnsUnsupported() { ShadowRotationPolicy.setRotationSupported(false); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + setDeviceStateRotationLockEnabled(true, mResources); int availability = mController.getAvailabilityStatus(); diff --git a/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingManagerProviderTest.kt b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingManagerProviderTest.kt new file mode 100644 index 00000000000..f2e59c5a005 --- /dev/null +++ b/tests/robotests/src/com/android/settings/display/DeviceStateAutoRotateSettingManagerProviderTest.kt @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2025 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.settings.display; + +import android.content.Context +import android.content.res.Resources +import android.hardware.devicestate.DeviceStateManager +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.SetFlagsRule +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.internal.R +import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManagerImpl +import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager +import com.android.window.flags.Flags +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Assert.assertNotSame +import org.junit.Assert.assertSame +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit +import org.mockito.Mockito.`when` as whenever + +@SmallTest +@RunWith(AndroidJUnit4::class) +class DeviceStateAutoRotateSettingManagerProviderTest { + + @get:Rule + val setFlagsRule: SetFlagsRule = SetFlagsRule() + @get:Rule + val rule = MockitoJUnit.rule() + + @Mock + private lateinit var mockContext: Context + @Mock + private lateinit var mockDeviceStateManager: DeviceStateManager + @Mock + private lateinit var mockResources: Resources + + private val context: Context = ApplicationProvider.getApplicationContext() + + @Before + fun setup() { + whenever(mockContext.contentResolver).thenReturn(context.contentResolver) + whenever(mockContext.getSystemService(DeviceStateManager::class.java)).thenReturn( + mockDeviceStateManager + ) + whenever(mockContext.resources).thenReturn(mockResources) + whenever(mockResources.getStringArray(R.array.config_perDeviceStateRotationLockDefaults)) + .thenReturn(arrayOf()) + } + + @After + fun tearDown() { + DeviceStateAutoRotateSettingManagerProvider.resetInstance() + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_DEVICE_STATE_AUTO_ROTATE_SETTING_REFACTOR) + fun getSingletonInstance_refactorFlagEnabled_returnsRefactoredManager() { + val manager = DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(mockContext) + + assertThat(manager).isInstanceOf(DeviceStateAutoRotateSettingManagerImpl::class.java) + } + + @Test + @DisableFlags(Flags.FLAG_ENABLE_DEVICE_STATE_AUTO_ROTATE_SETTING_REFACTOR) + fun getSingletonInstance_refactorFlagDisabled_returnsLegacyManager() { + val manager = DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(mockContext) + + assertThat(manager).isInstanceOf(DeviceStateRotationLockSettingsManager::class.java) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_DEVICE_STATE_AUTO_ROTATE_SETTING_REFACTOR) + fun getSingletonInstance_resetInstance_returnsNewInstance() { + val manager1 = DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(mockContext) + DeviceStateAutoRotateSettingManagerProvider.resetInstance() + val manager2 = DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(mockContext) + + assertNotSame(manager1, manager2) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_DEVICE_STATE_AUTO_ROTATE_SETTING_REFACTOR) + fun getSingletonInstance_getInstanceTwice_returnsSameInstance() { + val manager1 = DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(mockContext) + val manager2 = DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(mockContext) + + assertSame(manager1, manager2) + } +} diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java index e2542b0d55b..a1eb89c249a 100644 --- a/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java @@ -19,6 +19,7 @@ package com.android.settings.display; import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; +import static com.android.settings.testutils.DeviceStateAutoRotateSettingTestUtils.setDeviceStateRotationLockEnabled; import static com.google.common.truth.Truth.assertThat; @@ -33,6 +34,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.res.Resources; import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.os.UserHandle; @@ -41,11 +43,11 @@ import android.provider.Settings; import androidx.preference.Preference; import com.android.settings.testutils.ResolveInfoBuilder; -import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; +import com.android.settings.testutils.shadow.ShadowDeviceStateAutoRotateSettingManager; import com.android.settings.testutils.shadow.ShadowRotationPolicy; import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager; import com.android.settings.testutils.shadow.ShadowSystemSettings; -import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; +import com.android.settingslib.devicestate.DeviceStateAutoRotateSettingManager; import org.junit.Before; import org.junit.Test; @@ -73,17 +75,21 @@ public class SmartAutoRotateControllerTest { private Preference mPreference; @Mock private DeviceStateManager mDeviceStateManager; + @Mock + private Resources mResources; private ContentResolver mContentResolver; - private DeviceStateRotationLockSettingsManager mDeviceStateAutoRotateSettingsManager; + private DeviceStateAutoRotateSettingManager mDeviceStateAutoRotateSettingManager; @Before public void setUp() { MockitoAnnotations.initMocks(this); final Context context = Mockito.spy(RuntimeEnvironment.application); mContentResolver = RuntimeEnvironment.application.getContentResolver(); + mResources = Mockito.spy(RuntimeEnvironment.application.getResources()); when(context.getPackageManager()).thenReturn(mPackageManager); when(context.getContentResolver()).thenReturn(mContentResolver); + when(context.getResources()).thenReturn(mResources); doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName(); doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( Manifest.permission.CAMERA, PACKAGE_NAME); @@ -91,8 +97,9 @@ public class SmartAutoRotateControllerTest { doReturn(context).when(context).getApplicationContext(); doReturn(mDeviceStateManager).when(context).getSystemService(DeviceStateManager.class); doReturn(getDeviceStateList()).when(mDeviceStateManager).getSupportedDeviceStates(); - mDeviceStateAutoRotateSettingsManager = DeviceStateRotationLockSettingsManager.getInstance( - context); + setDeviceStateRotationLockEnabled(false, mResources); + mDeviceStateAutoRotateSettingManager = + DeviceStateAutoRotateSettingManagerProvider.getSingletonInstance(context); mController = Mockito.spy(new SmartAutoRotateController(context, "test_key")); when(mController.isCameraLocked()).thenReturn(false); @@ -144,7 +151,7 @@ public class SmartAutoRotateControllerTest { @Test @Config(shadows = { - ShadowDeviceStateRotationLockSettingsManager.class, + ShadowDeviceStateAutoRotateSettingManager.class, ShadowRotationPolicy.class }) public void getAvailabilityStatus_deviceStateRotationLocked_returnDisableDependentSetting() { @@ -158,7 +165,7 @@ public class SmartAutoRotateControllerTest { @Test @Config(shadows = { - ShadowDeviceStateRotationLockSettingsManager.class, + ShadowDeviceStateAutoRotateSettingManager.class, ShadowRotationPolicy.class }) public void getAvailabilityStatus_deviceStateRotationUnlocked_returnAvailable() { @@ -182,18 +189,18 @@ public class SmartAutoRotateControllerTest { private void enableDeviceStateRotation() { ShadowRotationPolicy.setRotationSupported(true); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + setDeviceStateRotationLockEnabled(true, mResources); } private void lockDeviceStateRotation() { - ShadowDeviceStateRotationLockSettingsManager shadowManager = - Shadow.extract(mDeviceStateAutoRotateSettingsManager); + ShadowDeviceStateAutoRotateSettingManager shadowManager = + Shadow.extract(mDeviceStateAutoRotateSettingManager); shadowManager.setRotationLockedForAllStates(true); } private void unlockDeviceStateRotation() { - ShadowDeviceStateRotationLockSettingsManager shadowManager = - Shadow.extract(mDeviceStateAutoRotateSettingsManager); + ShadowDeviceStateAutoRotateSettingManager shadowManager = + Shadow.extract(mDeviceStateAutoRotateSettingManager); shadowManager.setRotationLockedForAllStates(false); } diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java index 9f1b5d4357f..1fb4703fc7c 100644 --- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java @@ -18,6 +18,8 @@ package com.android.settings.display; import static android.provider.Settings.Secure.CAMERA_AUTOROTATE; +import static com.android.settings.testutils.DeviceStateAutoRotateSettingTestUtils.setDeviceStateRotationLockEnabled; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -40,7 +42,6 @@ import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.ResolveInfoBuilder; -import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager; import com.android.settings.testutils.shadow.ShadowSystemSettings; @@ -57,8 +58,7 @@ import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) @Config(shadows = { ShadowSystemSettings.class, - ShadowSensorPrivacyManager.class, - ShadowDeviceStateRotationLockSettingsManager.class + ShadowSensorPrivacyManager.class }) public class SmartAutoRotatePreferenceControllerTest { @@ -104,7 +104,7 @@ public class SmartAutoRotatePreferenceControllerTest { new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate")); when(mController.isCameraLocked()).thenReturn(false); when(mController.isPowerSaveMode()).thenReturn(false); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false); + setDeviceStateRotationLockEnabled(false, mResources); } @Test @@ -213,7 +213,7 @@ public class SmartAutoRotatePreferenceControllerTest { @Test public void getAvailabilityStatus_deviceStateRotationEnabled_returnsUnsupported() { enableAutoRotationPreference(); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + setDeviceStateRotationLockEnabled(true, mResources); assertThat(mController.getAvailabilityStatus()).isEqualTo( BasePreferenceController.UNSUPPORTED_ON_DEVICE); diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java index 16155384cf8..731cffb8719 100644 --- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java @@ -27,6 +27,7 @@ import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED import static com.android.settings.display.SmartAutoRotatePreferenceFragment.AUTO_ROTATE_MAIN_SWITCH_PREFERENCE_KEY; import static com.android.settings.display.SmartAutoRotatePreferenceFragment.AUTO_ROTATE_SWITCH_PREFERENCE_KEY; +import static com.android.settings.testutils.DeviceStateAutoRotateSettingTestUtils.setDeviceStateRotationLockEnabled; import static com.google.common.truth.Truth.assertThat; @@ -55,10 +56,8 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.testutils.ResolveInfoBuilder; -import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager; import com.android.settings.testutils.shadow.ShadowRotationPolicy; import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; import org.junit.Before; import org.junit.Test; @@ -75,7 +74,6 @@ import java.util.Set; @RunWith(RobolectricTestRunner.class) @Config(shadows = { com.android.settings.testutils.shadow.ShadowFragment.class, - ShadowDeviceStateRotationLockSettingsManager.class, ShadowRotationPolicy.class }) public class SmartAutoRotatePreferenceFragmentTest { @@ -174,7 +172,7 @@ public class SmartAutoRotatePreferenceFragmentTest { @Test public void createHeader_faceDetectionSupported_switchBarIsEnabled() { - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false); + setDeviceStateRotationLockEnabled(false, mResources); mFragment.createHeader(mActivity); verify(mRotateMainSwitchPreference, never()).setVisible(false); @@ -184,7 +182,7 @@ public class SmartAutoRotatePreferenceFragmentTest { @Test public void createHeader_deviceStateRotationSupported_switchBarIsDisabled() { ShadowRotationPolicy.setRotationSupported(true); - ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(true); + setDeviceStateRotationLockEnabled(true, mResources); mFragment.createHeader(mActivity); @@ -258,15 +256,14 @@ public class SmartAutoRotatePreferenceFragmentTest { private void enableDeviceStateSettableRotationStates( String[] settableStates, String[] settableStatesDescriptions) { when(mResources.getStringArray( - com.android.internal.R.array.config_perDeviceStateRotationLockDefaults)) + com.android.internal.R.array.config_perDeviceStateRotationLockDefaults)) .thenReturn(settableStates); when(mResources.getStringArray(R.array.config_settableAutoRotationDeviceStatesDescriptions)) .thenReturn(settableStatesDescriptions); when(mResources.getBoolean(R.bool.config_auto_rotate_face_detection_available)) .thenReturn(true); - DeviceStateRotationLockSettingsManager.resetInstance(); - DeviceStateRotationLockSettingsManager.getInstance(mContext) - .resetStateForTesting(mResources); + DeviceStateAutoRotateSettingManagerProvider.resetInstance(); + when(mContext.getResources()).thenReturn(mResources); } // Sets up posture mappings for PosturesHelper diff --git a/tests/robotests/src/com/android/settings/testutils/DeviceStateAutoRotateSettingTestUtils.java b/tests/robotests/src/com/android/settings/testutils/DeviceStateAutoRotateSettingTestUtils.java new file mode 100644 index 00000000000..3359b2f9dc5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/DeviceStateAutoRotateSettingTestUtils.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2025 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.settings.testutils; + +import static org.mockito.Mockito.when; + +import android.content.res.Resources; + +/** + * Helper for testing device state auto rotate setting + */ +public class DeviceStateAutoRotateSettingTestUtils { + + /** + * Mock {@link mockResources} to return device state auto rotate enabled or disabled based on + * value passed for {@link enable}. + */ + public static void setDeviceStateRotationLockEnabled(boolean enable, Resources mockResources) { + String[] perDeviceStateRotationLockDefaults = new String[0]; + if (enable) { + perDeviceStateRotationLockDefaults = new String[]{"test_value"}; + } + when(mockResources.getStringArray( + com.android.internal.R.array.config_perDeviceStateRotationLockDefaults)) + .thenReturn(perDeviceStateRotationLockDefaults); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateRotationLockSettingsManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateAutoRotateSettingManager.java similarity index 73% rename from tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateRotationLockSettingsManager.java rename to tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateAutoRotateSettingManager.java index ed266e3b23e..b44d79e3acc 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateRotationLockSettingsManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDeviceStateAutoRotateSettingManager.java @@ -16,28 +16,16 @@ package com.android.settings.testutils.shadow; -import android.content.Context; - import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; @Implements(DeviceStateRotationLockSettingsManager.class) -public class ShadowDeviceStateRotationLockSettingsManager { +public class ShadowDeviceStateAutoRotateSettingManager { - private static boolean sDeviceStateRotationLockEnabled; private boolean mIsRotationLockedForAllStates; - @Implementation - public static boolean isDeviceStateRotationLockEnabled(Context context) { - return sDeviceStateRotationLockEnabled; - } - - public static void setDeviceStateRotationLockEnabled(boolean enabled) { - sDeviceStateRotationLockEnabled = enabled; - } - @Implementation public boolean isRotationLockedForAllStates() { return mIsRotationLockedForAllStates;