Merge "Check in auto rotate settings summary for rotation resolver service" into sc-dev
diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
index 8c25a05..f8d5f96 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 @@
     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 @@
 
     @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 @@
 
     @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 @@
                     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 cc3b20d..068de34 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 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 @@
                 .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 @@
     }
 
     @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 @@
     }
 
     @Test
-    public void updatePreference_settingsIsOn_noSmartAuto_shouldTurnOnToggle() {
+    public void getSummary_noSmartAuto_returnsOn() {
         enableAutoRotation();
         Settings.Secure.putStringForUser(mContentResolver,
                 CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT);
@@ -127,6 +156,34 @@
     }
 
     @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
                 .UNSUPPORTED_ON_DEVICE);
@@ -158,14 +215,14 @@
 
     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);
     }