1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.display; 18 19 import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; 20 21 import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; 22 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; 23 import static com.android.settings.display.UtilsKt.isAdaptiveSleepSupported; 24 25 import android.Manifest; 26 import android.app.settings.SettingsEnums; 27 import android.content.Context; 28 import android.content.pm.PackageManager; 29 import android.hardware.SensorPrivacyManager; 30 import android.os.PowerManager; 31 import android.os.UserManager; 32 import android.provider.Settings; 33 34 import androidx.preference.PreferenceScreen; 35 36 import com.android.settings.R; 37 import com.android.settings.bluetooth.RestrictionUtils; 38 import com.android.settings.overlay.FeatureFactory; 39 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 40 import com.android.settingslib.RestrictedSwitchPreference; 41 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 42 43 import com.google.common.annotations.VisibleForTesting; 44 45 // LINT.IfChange 46 /** The controller for Screen attention switch preference. */ 47 public class AdaptiveSleepPreferenceController { 48 public static final String PREFERENCE_KEY = Settings.Secure.ADAPTIVE_SLEEP; 49 private static final int DEFAULT_VALUE = 0; 50 private final SensorPrivacyManager mPrivacyManager; 51 private final RestrictionUtils mRestrictionUtils; 52 private final PackageManager mPackageManager; 53 private final Context mContext; 54 private final MetricsFeatureProvider mMetricsFeatureProvider; 55 private final PowerManager mPowerManager; 56 57 @VisibleForTesting 58 RestrictedSwitchPreference mPreference; 59 AdaptiveSleepPreferenceController(Context context, RestrictionUtils restrictionUtils)60 public AdaptiveSleepPreferenceController(Context context, RestrictionUtils restrictionUtils) { 61 mContext = context; 62 mRestrictionUtils = restrictionUtils; 63 mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); 64 mPrivacyManager = SensorPrivacyManager.getInstance(context); 65 mPowerManager = context.getSystemService(PowerManager.class); 66 mPackageManager = context.getPackageManager(); 67 } 68 AdaptiveSleepPreferenceController(Context context)69 public AdaptiveSleepPreferenceController(Context context) { 70 this(context, new RestrictionUtils()); 71 } 72 73 /** 74 * Adds the controlled preference to the provided preference screen. 75 */ addToScreen(PreferenceScreen screen)76 public void addToScreen(PreferenceScreen screen) { 77 updatePreference(); 78 screen.addPreference(mPreference); 79 } 80 81 /** 82 * Updates the appearance of the preference. 83 */ updatePreference()84 public void updatePreference() { 85 initializePreference(); 86 final EnforcedAdmin enforcedAdmin = mRestrictionUtils.checkIfRestrictionEnforced(mContext, 87 UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT); 88 if (enforcedAdmin != null) { 89 mPreference.setDisabledByAdmin(enforcedAdmin); 90 } else { 91 mPreference.setChecked(isChecked()); 92 mPreference.setEnabled(hasSufficientPermission(mPackageManager) && !isCameraLocked() 93 && !isPowerSaveMode()); 94 } 95 } 96 97 @VisibleForTesting initializePreference()98 void initializePreference() { 99 if (mPreference == null) { 100 mPreference = new RestrictedSwitchPreference(mContext); 101 mPreference.setTitle(R.string.adaptive_sleep_title); 102 mPreference.setSummary(R.string.adaptive_sleep_description); 103 mPreference.setChecked(isChecked()); 104 mPreference.setKey(PREFERENCE_KEY); 105 mPreference.setOnPreferenceClickListener(preference -> { 106 final boolean isChecked = ((RestrictedSwitchPreference) preference).isChecked(); 107 mMetricsFeatureProvider.action(mContext, 108 SettingsEnums.ACTION_SCREEN_ATTENTION_CHANGED, 109 isChecked); 110 Settings.Secure.putInt(mContext.getContentResolver(), 111 Settings.Secure.ADAPTIVE_SLEEP, isChecked ? 1 : DEFAULT_VALUE); 112 return true; 113 }); 114 } 115 } 116 117 @VisibleForTesting isChecked()118 boolean isChecked() { 119 return hasSufficientPermission(mContext.getPackageManager()) && !isCameraLocked() 120 && !isPowerSaveMode() && Settings.Secure.getInt(mContext.getContentResolver(), 121 Settings.Secure.ADAPTIVE_SLEEP, DEFAULT_VALUE) 122 != DEFAULT_VALUE; 123 } 124 125 /** 126 * Need this because all controller tests use RoboElectric. No easy way to mock this service, 127 * so we mock the call we need 128 */ 129 @VisibleForTesting isCameraLocked()130 boolean isCameraLocked() { 131 return mPrivacyManager.isSensorPrivacyEnabled(CAMERA); 132 } 133 134 @VisibleForTesting isPowerSaveMode()135 boolean isPowerSaveMode() { 136 return mPowerManager.isPowerSaveMode(); 137 } 138 isControllerAvailable(Context context)139 public static int isControllerAvailable(Context context) { 140 return isAdaptiveSleepSupported(context) 141 ? AVAILABLE_UNSEARCHABLE 142 : UNSUPPORTED_ON_DEVICE; 143 } 144 hasSufficientPermission(PackageManager packageManager)145 static boolean hasSufficientPermission(PackageManager packageManager) { 146 final String attentionPackage = packageManager.getAttentionServicePackageName(); 147 return attentionPackage != null && packageManager.checkPermission( 148 Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED; 149 } 150 } 151 // LINT.ThenChange(AdaptiveSleepPreference.kt) 152