diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java index 8c25a05ca31..f8d5f96786e 100644 --- a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java +++ b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java @@ -16,15 +16,25 @@ package com.android.settings.display; +import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; import static android.provider.Settings.Secure.CAMERA_AUTOROTATE; +import static com.android.settings.display.SmartAutoRotateController.hasSufficientPermission; +import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable; + +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.SensorPrivacyManager; +import android.os.PowerManager; import android.os.UserHandle; import android.provider.Settings; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.view.RotationPolicy; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; @@ -41,8 +51,21 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle private RotationPolicy.RotationPolicyListener mRotationPolicyListener; private Preference mPreference; + private final SensorPrivacyManager mPrivacyManager; + private final PowerManager mPowerManager; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + refreshSummary(mPreference); + } + }; + public SmartAutoRotatePreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); + mPrivacyManager = SensorPrivacyManager.getInstance(context); + mPrivacyManager + .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> refreshSummary(mPreference)); + mPowerManager = context.getSystemService(PowerManager.class); } @Override @@ -59,6 +82,8 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle @Override public void onStart() { + mContext.registerReceiver(mReceiver, + new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); if (mRotationPolicyListener == null) { mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() { @Override @@ -75,12 +100,27 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle @Override public void onStop() { + mContext.unregisterReceiver(mReceiver); if (mRotationPolicyListener != null) { RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener); } } + /** + * Need this because all controller tests use Roboelectric. No easy way to mock this service, + * so we mock the call we need + */ + @VisibleForTesting + boolean isCameraLocked() { + return mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA); + } + + @VisibleForTesting + boolean isPowerSaveMode() { + return mPowerManager.isPowerSaveMode(); + } + @Override public CharSequence getSummary() { int activeStringId = R.string.auto_rotate_option_off; @@ -89,7 +129,11 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle mContext.getContentResolver(), CAMERA_AUTOROTATE, 0, UserHandle.USER_CURRENT); - activeStringId = cameraRotate == 1 ? R.string.auto_rotate_option_face_based + activeStringId = cameraRotate == 1 && isRotationResolverServiceAvailable(mContext) + && hasSufficientPermission(mContext) + && !isCameraLocked() + && !isPowerSaveMode() + ? R.string.auto_rotate_option_face_based : R.string.auto_rotate_option_on; } return mContext.getString(activeStringId); diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java index cc3b20da896..068de3472b5 100644 --- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java @@ -20,46 +20,65 @@ import static android.provider.Settings.Secure.CAMERA_AUTOROTATE; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; +import android.Manifest; import android.content.ContentResolver; 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.os.UserHandle; import android.provider.Settings; 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.ShadowSensorPrivacyManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Answers; 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 = ShadowSensorPrivacyManager.class) public class SmartAutoRotatePreferenceControllerTest { - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Context mContext; + private static final String PACKAGE_NAME = "package_name"; @Mock private PackageManager mPackageManager; + @Mock + private Resources mResources; + private Context mContext; private ContentResolver mContentResolver; private SmartAutoRotatePreferenceController mController; @Before public void setUp() { MockitoAnnotations.initMocks(this); + mContext = Mockito.spy(RuntimeEnvironment.application); FakeFeatureFactory.setupForTest(); mContentResolver = RuntimeEnvironment.application.getContentResolver(); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mContext.getResources()).thenReturn(mResources); when(mContext.getContentResolver()).thenReturn(mContentResolver); + + doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName(); + doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( + Manifest.permission.CAMERA, PACKAGE_NAME); when(mContext.getString(R.string.auto_rotate_option_off)) .thenReturn("Off"); when(mContext.getString(R.string.auto_rotate_option_on)) @@ -68,8 +87,14 @@ public class SmartAutoRotatePreferenceControllerTest { .thenReturn("On - Face-based"); disableCameraBasedRotation(); + final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build(); + resolveInfo.serviceInfo = new ServiceInfo(); + when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo); - mController = new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate"); + mController = Mockito.spy( + new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate")); + when(mController.isCameraLocked()).thenReturn(false); + when(mController.isPowerSaveMode()).thenReturn(false); } @Test @@ -82,33 +107,37 @@ public class SmartAutoRotatePreferenceControllerTest { } @Test - public void updatePreference_settingsIsOff_shouldTurnOffToggle() { + public void getSummary_settingsIsOff_returnsOff() { disableAutoRotation(); assertThat(mController.getSummary()).isEqualTo("Off"); } @Test - public void updatePreference_settingsIsOn_shouldTurnOnToggle() { + public void getSummary_settingsIsOn_returnsOn() { enableAutoRotation(); assertThat(mController.getSummary()).isEqualTo("On"); } @Test - public void updatePreference_settingsIsCameraBased_shouldTurnOnToggle() { + public void getSummary_autoRotateOffSmartAutoRotateOn_returnsOff() { + enableCameraBasedRotation(); + disableAutoRotation(); + + assertThat(mController.getSummary()).isEqualTo("Off"); + } + + @Test + public void updatePreference_smartAutoRotateOn_returnsFaceBased() { enableCameraBasedRotation(); enableAutoRotation(); assertThat(mController.getSummary()).isEqualTo("On - Face-based"); - - disableAutoRotation(); - - assertThat(mController.getSummary()).isEqualTo("Off"); } @Test - public void updatePreference_settingsIsOff_noSmartAuto_shouldTurnOffToggle() { + public void getSummary_noSmartAuto_returnsOff() { disableAutoRotation(); Settings.Secure.putStringForUser(mContentResolver, CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT); @@ -118,7 +147,7 @@ public class SmartAutoRotatePreferenceControllerTest { } @Test - public void updatePreference_settingsIsOn_noSmartAuto_shouldTurnOnToggle() { + public void getSummary_noSmartAuto_returnsOn() { enableAutoRotation(); Settings.Secure.putStringForUser(mContentResolver, CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT); @@ -126,6 +155,34 @@ public class SmartAutoRotatePreferenceControllerTest { assertThat(mController.getSummary()).isEqualTo("On"); } + @Test + public void getSummary_noCameraPermission_returnsOn() { + enableAutoRotation(); + enableCameraBasedRotation(); + doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( + Manifest.permission.CAMERA, PACKAGE_NAME); + + assertThat(mController.getSummary()).isEqualTo("On"); + } + + @Test + public void getSummary_cameraDisabled_returnsOn() { + enableAutoRotation(); + enableCameraBasedRotation(); + when(mController.isCameraLocked()).thenReturn(true); + + assertThat(mController.getSummary()).isEqualTo("On"); + } + + @Test + public void getSummary_powerSaveEnabled_returnsOn() { + enableAutoRotation(); + enableCameraBasedRotation(); + when(mController.isPowerSaveMode()).thenReturn(true); + + assertThat(mController.getSummary()).isEqualTo("On"); + } + @Test public void testGetAvailabilityStatus() { assertThat(mController.getAvailabilityStatus()).isEqualTo(BasePreferenceController @@ -158,14 +215,14 @@ public class SmartAutoRotatePreferenceControllerTest { private void enableAutoRotationPreference() { when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true); - when(mContext.getResources().getBoolean(anyInt())).thenReturn(true); + when(mResources.getBoolean(anyInt())).thenReturn(true); Settings.System.putInt(mContentResolver, Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0); } private void disableAutoRotationPreference() { when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true); - when(mContext.getResources().getBoolean(anyInt())).thenReturn(true); + when(mResources.getBoolean(anyInt())).thenReturn(true); Settings.System.putInt(mContentResolver, Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 1); }