Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7a66b30 authored by Abel Tesfaye's avatar Abel Tesfaye
Browse files

Add warning message when camera privacy lock is enabled for

smart auto rotate settings fragment

Test: locally with flame, make RunSettingsRoboTests -j$(nproc)
ROBOTEST_FILTER=SmartAutoRotateCameraStateControllerTest,SmartAutoRotateControllerTest

Bug: 177462182
Change-Id: If443bd2456f3fbe76876777be912b204a50f4088
parent 1b82a330
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2851,6 +2851,10 @@
    <string name="adaptive_sleep_contextual_slice_title">Turn on screen attention</string>
    <!-- Description about the contextual adaptive sleep card [CHAR LIMIT=NONE]-->
    <string name="adaptive_sleep_contextual_slice_summary">Keep screen on when looking at it</string>
    <!-- auto_rotate settings screen, title about the camera privacy lock enabled [CHAR LIMIT=NONE]-->
    <string name="auto_rotate_camera_lock_title">Camera is locked</string>
    <!-- Description feature's privacy sensitive details to make sure users understand what feature users, what it saves/sends etc [CHAR LIMIT=NONE]-->
    <string name="auto_rotate_camera_lock_summary">Camera must be unlocked for Face Detection</string>
    <!-- auto_rotate settings screen, title about the required permission is missing [CHAR LIMIT=NONE]-->
    <string name="auto_rotate_summary_no_permission">Camera access is required for Face Detection. Tap to manage permissions for Device Personalization Services</string>
    <!-- auto_rotate settings screen, text for the camera permission button [CHAR LIMIT=NONE]-->
+6 −0
Original line number Diff line number Diff line
@@ -26,6 +26,12 @@
        android:summary="@string/auto_rotate_summary_no_permission"
        settings:controller="com.android.settings.display.SmartAutoRotatePermissionController" />

    <com.android.settingslib.widget.BannerMessagePreference
        android:key="camera_lock_state"
        android:title="@string/auto_rotate_camera_lock_title"
        android:summary="@string/auto_rotate_camera_lock_summary"
        settings:controller="com.android.settings.display.SmartAutoRotateCameraStateController" />

    <SwitchPreference
        android:key="face_based_rotate"
        android:title="@string/auto_rotate_switch_face_based"
+74 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 static android.hardware.SensorPrivacyManager.Sensors.CAMERA;

import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;

import android.content.Context;
import android.hardware.SensorPrivacyManager;

import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.BannerMessagePreference;

/**
 * The controller of camera based rotate privacy sensor warning preference. The preference appears
 * when the privacy sensor service disables camera functionality completely.
 */
public class SmartAutoRotateCameraStateController extends BasePreferenceController {

    private final SensorPrivacyManager mPrivacyManager;
    private Preference mPreference;

    public SmartAutoRotateCameraStateController(Context context, String key) {
        super(context, key);
        mPrivacyManager = SensorPrivacyManager.getInstance(context);
        mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> {
            mPreference.setVisible(enabled);
            updateState(mPreference);
        });
    }

    @VisibleForTesting
    boolean isCameraLocked() {
        return mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA);
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(getPreferenceKey());
        ((BannerMessagePreference) mPreference)
                .setPositiveButtonText(R.string.allow)
                .setPositiveButtonOnClickListener(v -> {
                    mPrivacyManager.setSensorPrivacy(CAMERA, false);
                });
    }

    @Override
    @AvailabilityStatus
    public int getAvailabilityStatus() {
        return isRotationResolverServiceAvailable(mContext)
                && isCameraLocked() ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
    }
}
+33 −2
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.settings.display;

import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.provider.Settings.Secure.CAMERA_AUTOROTATE;

import android.Manifest;
@@ -23,12 +24,15 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.hardware.SensorPrivacyManager;
import android.provider.Settings;
import android.service.rotationresolver.RotationResolverService;
import android.text.TextUtils;

import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.view.RotationPolicy;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
@@ -41,10 +45,14 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
        Preference.OnPreferenceChangeListener {

    private final MetricsFeatureProvider mMetricsFeatureProvider;
    private final SensorPrivacyManager mPrivacyManager;
    private Preference mPreference;

    public SmartAutoRotateController(Context context, String preferenceKey) {
        super(context, preferenceKey);
        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
        mPrivacyManager = SensorPrivacyManager.getInstance(context);
        mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> updateState(mPreference));
    }

    @Override
@@ -53,16 +61,39 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
            return UNSUPPORTED_ON_DEVICE;
        }
        return !RotationPolicy.isRotationLocked(mContext) && hasSufficientPermission(mContext)
                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
                && !isCameraLocked() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
    }

    @Override
    public void updateState(Preference preference) {
        super.updateState(preference);
        if (preference != null) {
            preference.setEnabled(getAvailabilityStatus() == AVAILABLE);
        }
    }

    /**
     * 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);
    }

    @Override
    public boolean isChecked() {
        return hasSufficientPermission(mContext) && Settings.Secure.getInt(
        return hasSufficientPermission(mContext) && !isCameraLocked() && Settings.Secure.getInt(
                mContext.getContentResolver(),
                CAMERA_AUTOROTATE, 0) == 1;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(getPreferenceKey());
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_CAMERA_ROTATE_TOGGLE,
+6 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import static com.android.settings.display.SmartAutoRotateController.hasSufficie
import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;

import android.app.settings.SettingsEnums;
import android.hardware.SensorPrivacyManager;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
@@ -47,6 +48,7 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
    private static final String TAG = "SmartAutoRotatePreferenceFragment";

    private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
    private SensorPrivacyManager mPrivacyManager;
    private AutoRotateSwitchBarController mSwitchBarController;
    private static final String FACE_SWITCH_PREFERENCE_ID = "face_based_rotate";

@@ -66,6 +68,7 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
        switchBar.show();
        mSwitchBarController = new AutoRotateSwitchBarController(activity, switchBar,
                getSettingsLifecycle());
        mPrivacyManager = SensorPrivacyManager.getInstance(activity);
        final Preference footerPreference = findPreference(FooterPreference.KEY_FOOTER);
        if (footerPreference != null) {
            footerPreference.setTitle(Html.fromHtml(getString(R.string.smart_rotate_text_headline),
@@ -84,9 +87,11 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
                public void onChange() {
                    mSwitchBarController.onChange();
                    final boolean isLocked = RotationPolicy.isRotationLocked(getContext());
                    final boolean isCameraLocked = mPrivacyManager.isSensorPrivacyEnabled(
                            SensorPrivacyManager.Sensors.CAMERA);
                    final Preference preference = findPreference(FACE_SWITCH_PREFERENCE_ID);
                    if (preference != null && hasSufficientPermission(getContext())) {
                        preference.setEnabled(!isLocked);
                        preference.setEnabled(!isLocked && !isCameraLocked);
                    }
                }
            };
Loading