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

Commit 989570a9 authored by Abel Tesfaye's avatar Abel Tesfaye Committed by Android (Google) Code Review
Browse files

Merge "Add warning message when power save mode is enabled for attention...

Merge "Add warning message when power save mode is enabled for attention settings fragment" into sc-dev
parents 43905b34 51ce2425
Loading
Loading
Loading
Loading
+71 −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 android.content.Context;
import android.os.PowerManager;

import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settingslib.widget.BannerMessagePreference;

/**
 * The controller of Screen attention's battery saver warning preference.
 * The preference appears when Screen Attention feature is disabled by battery saver mode.
 */
public class AdaptiveSleepBatterySaverPreferenceController {

    @VisibleForTesting
    final BannerMessagePreference mPreference;
    private final PowerManager mPowerManager;

    public AdaptiveSleepBatterySaverPreferenceController(Context context) {
        mPreference = new BannerMessagePreference(context);
        mPreference.setTitle(R.string.ambient_camera_summary_battery_saver_on);
        mPreference.setPositiveButtonText(R.string.disable_text);
        mPowerManager = context.getSystemService(PowerManager.class);
        mPreference.setPositiveButtonOnClickListener(p -> {
            mPowerManager.setPowerSaveModeEnabled(false);
        });
    }

    /**
     * Adds the controlled preference to the provided preference screen.
     */
    public void addToScreen(PreferenceScreen screen) {
        screen.addPreference(mPreference);
        updateVisibility();
    }

    /**
     * Need this because all controller tests use RoboElectric. No easy way to mock this service,
     * so we mock the call we need
     */
    @VisibleForTesting
    boolean isPowerSaveMode() {
        return mPowerManager.isPowerSaveMode();
    }

    /**
     * Refreshes the visibility of the preference.
     */
    public void updateVisibility() {
        mPreference.setVisible(isPowerSaveMode());
    }
}
+24 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.hardware.SensorPrivacyManager;
import android.os.PowerManager;
import android.os.UserManager;
import android.provider.Settings;
import android.service.attention.AttentionService;
@@ -53,6 +54,7 @@ public class AdaptiveSleepPreferenceController {
    private final PackageManager mPackageManager;
    private final Context mContext;
    private final MetricsFeatureProvider mMetricsFeatureProvider;
    private final PowerManager mPowerManager;

    @VisibleForTesting
    RestrictedSwitchPreference mPreference;
@@ -62,6 +64,20 @@ public class AdaptiveSleepPreferenceController {
        mRestrictionUtils = restrictionUtils;
        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
        mPrivacyManager = SensorPrivacyManager.getInstance(context);
        mPowerManager = context.getSystemService(PowerManager.class);
        mPreference = new RestrictedSwitchPreference(context);
        mPreference.setTitle(R.string.adaptive_sleep_title);
        mPreference.setSummary(R.string.adaptive_sleep_description);
        mPreference.setChecked(isChecked());
        mPreference.setKey(PREFERENCE_KEY);
        mPreference.setOnPreferenceClickListener(preference -> {
            final boolean isChecked = ((RestrictedSwitchPreference) preference).isChecked();
            mMetricsFeatureProvider.action(context, SettingsEnums.ACTION_SCREEN_ATTENTION_CHANGED,
                    isChecked);
            Settings.Secure.putInt(context.getContentResolver(),
                    Settings.Secure.ADAPTIVE_SLEEP, isChecked ? 1 : DEFAULT_VALUE);
            return true;
        });
        mPackageManager = context.getPackageManager();
    }

@@ -87,7 +103,8 @@ public class AdaptiveSleepPreferenceController {
        if (enforcedAdmin != null) {
            mPreference.setDisabledByAdmin(enforcedAdmin);
        } else {
            mPreference.setEnabled(hasSufficientPermission(mPackageManager) && !isCameraLocked());
            mPreference.setEnabled(hasSufficientPermission(mPackageManager) && !isCameraLocked()
                    && !isPowerSaveMode());
        }
    }

@@ -114,7 +131,7 @@ public class AdaptiveSleepPreferenceController {
    @VisibleForTesting
    boolean isChecked() {
        return hasSufficientPermission(mContext.getPackageManager()) && !isCameraLocked()
                && Settings.Secure.getInt(mContext.getContentResolver(),
                && !isPowerSaveMode() && Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.ADAPTIVE_SLEEP, DEFAULT_VALUE)
                != DEFAULT_VALUE;
    }
@@ -128,6 +145,11 @@ public class AdaptiveSleepPreferenceController {
        return mPrivacyManager.isSensorPrivacyEnabled(CAMERA);
    }

    @VisibleForTesting
    boolean isPowerSaveMode() {
        return mPowerManager.isPowerSaveMode();
    }

    public static int isControllerAvailable(Context context) {
        return context.getResources().getBoolean(
                com.android.internal.R.bool.config_adaptive_sleep_available)
+30 −0
Original line number Diff line number Diff line
@@ -21,10 +21,14 @@ import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;

import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.hardware.SensorPrivacyManager;
import android.os.PowerManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.SpannableString;
@@ -73,6 +77,12 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
    private FooterPreference mPrivacyPreference;
    private final MetricsFeatureProvider mMetricsFeatureProvider;
    private SensorPrivacyManager mPrivacyManager;
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mAdaptiveSleepBatterySaverPreferenceController.updateVisibility();
        }
    };

    @VisibleForTesting
    Context mContext;
@@ -92,6 +102,9 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
    @VisibleForTesting
    AdaptiveSleepPreferenceController mAdaptiveSleepController;

    @VisibleForTesting
    AdaptiveSleepBatterySaverPreferenceController mAdaptiveSleepBatterySaverPreferenceController;

    public ScreenTimeoutSettings() {
        super();
        mMetricsFeatureProvider = FeatureFactory.getFactory(getContext())
@@ -109,6 +122,13 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
                context);
        mAdaptiveSleepCameraStatePreferenceController =
                new AdaptiveSleepCameraStatePreferenceController(context);
        mAdaptiveSleepBatterySaverPreferenceController =
                new AdaptiveSleepBatterySaverPreferenceController(context);
        mPrivacyPreference = new FooterPreference(context);
        mPrivacyPreference.setIcon(R.drawable.ic_privacy_shield_24dp);
        mPrivacyPreference.setTitle(R.string.adaptive_sleep_privacy);
        mPrivacyPreference.setSelectable(false);
        mPrivacyPreference.setLayoutResource(R.layout.preference_footer);
        mPrivacyManager = SensorPrivacyManager.getInstance(context);
        mPrivacyManager.addSensorPrivacyListener(CAMERA,
                (sensor, enabled) -> mAdaptiveSleepController.updatePreference());
@@ -136,7 +156,16 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
        super.onStart();
        mAdaptiveSleepPermissionController.updateVisibility();
        mAdaptiveSleepCameraStatePreferenceController.updateVisibility();
        mAdaptiveSleepBatterySaverPreferenceController.updateVisibility();
        mAdaptiveSleepController.updatePreference();
        mContext.registerReceiver(mReceiver,
                new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
    }

    @Override
    public void onStop() {
        super.onStop();
        mContext.unregisterReceiver(mReceiver);
    }

    @Override
@@ -176,6 +205,7 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
        if (isScreenAttentionAvailable(getContext())) {
            mAdaptiveSleepPermissionController.addToScreen(screen);
            mAdaptiveSleepCameraStatePreferenceController.addToScreen(screen);
            mAdaptiveSleepBatterySaverPreferenceController.addToScreen(screen);
            mAdaptiveSleepController.addToScreen(screen);
            screen.addPreference(mPrivacyPreference);
        }
+79 −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 androidx.test.core.app.ApplicationProvider.getApplicationContext;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.pm.PackageManager;

import androidx.preference.PreferenceScreen;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;

@RunWith(RobolectricTestRunner.class)
public class AdaptiveSleepBatterySaverPreferenceControllerTest {
    private Context mContext;
    private AdaptiveSleepBatterySaverPreferenceController mController;

    @Mock
    private PackageManager mPackageManager;
    @Mock
    private PreferenceScreen mScreen;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = spy(getApplicationContext());

        doReturn(mPackageManager).when(mContext).getPackageManager();
        when(mPackageManager.getAttentionServicePackageName()).thenReturn("some.package");
        when(mPackageManager.checkPermission(any(), any())).thenReturn(
                PackageManager.PERMISSION_GRANTED);

        mController = spy(new AdaptiveSleepBatterySaverPreferenceController(mContext));
        when(mController.isPowerSaveMode()).thenReturn(false);
    }

    @Test
    public void addToScreen_normalCase_hidePreference() {
        mController.addToScreen(mScreen);

        assertThat(mController.mPreference.isVisible()).isFalse();
    }

    @Test
    public void addToScreen_powerSaveEnabled_showPreference() {
        when(mController.isPowerSaveMode()).thenReturn(true);

        mController.addToScreen(mScreen);

        assertThat(mController.mPreference.isVisible()).isTrue();
    }
}
+12 −1
Original line number Diff line number Diff line
@@ -83,9 +83,10 @@ public class AdaptiveSleepPreferenceControllerTest {
        when(mRestrictionUtils.checkIfRestrictionEnforced(any(),
                eq(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT))).thenReturn(null);

        mController = new AdaptiveSleepPreferenceController(mContext, mRestrictionUtils);
        mController = spy(new AdaptiveSleepPreferenceController(mContext, mRestrictionUtils));
        mController.initializePreference();
        when(mController.isCameraLocked()).thenReturn(false);
        when(mController.isPowerSaveMode()).thenReturn(false);
    }

    @Test
@@ -174,4 +175,14 @@ public class AdaptiveSleepPreferenceControllerTest {

        assertThat(mController.mPreference.isEnabled()).isFalse();
    }

    @Test
    public void addToScreen_powerSaveEnabled_disablePreference() {
        when(mController.isPowerSaveMode()).thenReturn(true);

        mController.addToScreen(mScreen);

        assertThat(mController.mPreference.isEnabled()).isFalse();
    }

}