Loading src/com/android/settings/display/AdaptiveSleepPreference.kt 0 → 100644 +137 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.hardware.SensorPrivacyManager import android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener import android.hardware.SensorPrivacyManager.Sensors.CAMERA import android.os.PowerManager import android.os.UserManager import android.provider.Settings import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R import com.android.settingslib.RestrictedSwitchPreference import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObservableDelegate import com.android.settingslib.datastore.SettingsSecureStore import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.TwoStatePreference import com.android.settingslib.preference.PreferenceBindingPlaceholder import com.android.settingslib.preference.SwitchPreferenceBinding // LINT.IfChange class AdaptiveSleepPreference : TwoStatePreference, SwitchPreferenceBinding, PreferenceLifecycleProvider, PreferenceBindingPlaceholder, // not needed once controller class is cleaned up PreferenceAvailabilityProvider, PreferenceRestrictionMixin { private var broadcastReceiver: BroadcastReceiver? = null private var sensorPrivacyChangedListener: OnSensorPrivacyChangedListener? = null override val key: String get() = KEY override val title: Int get() = R.string.adaptive_sleep_title override val summary: Int get() = R.string.adaptive_sleep_description override fun isIndexable(context: Context) = false override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context) && context.canBeEnabled() override val restrictionKeys: Array<String> get() = arrayOf(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT) override fun isAvailable(context: Context) = context.isAdaptiveSleepSupported() override fun createWidget(context: Context) = RestrictedSwitchPreference(context) override fun storage(context: Context): KeyValueStore = Storage(context) override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) = ReadWritePermit.ALLOW override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) = ReadWritePermit.ALLOW @Suppress("UNCHECKED_CAST") private class Storage( private val context: Context, private val settingsStore: SettingsStore = SettingsSecureStore.get(context), ) : KeyedObservableDelegate<String>(settingsStore), KeyValueStore { override fun contains(key: String) = settingsStore.contains(key) override fun <T : Any> getValue(key: String, valueType: Class<T>) = (context.canBeEnabled() && settingsStore.getBoolean(key) == true) as T override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) = settingsStore.setBoolean(key, value as Boolean?) } override fun onStart(context: PreferenceLifecycleContext) { val receiver = object : BroadcastReceiver() { override fun onReceive(receiverContext: Context, intent: Intent) { context.notifyPreferenceChange(this@AdaptiveSleepPreference) } } context.registerReceiver( receiver, IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED), ) broadcastReceiver = receiver val listener = OnSensorPrivacyChangedListener { _, _ -> context.notifyPreferenceChange(this) } SensorPrivacyManager.getInstance(context).addSensorPrivacyListener(CAMERA, listener) sensorPrivacyChangedListener = listener } override fun onStop(context: PreferenceLifecycleContext) { broadcastReceiver?.let { context.unregisterReceiver(it) } sensorPrivacyChangedListener?.let { SensorPrivacyManager.getInstance(context).removeSensorPrivacyListener(it) } } companion object { const val KEY = Settings.Secure.ADAPTIVE_SLEEP @Suppress("DEPRECATION") private fun Context.canBeEnabled() = AdaptiveSleepPreferenceController.hasSufficientPermission(packageManager) && getSystemService(PowerManager::class.java)?.isPowerSaveMode != true && !SensorPrivacyManager.getInstance(this).isSensorPrivacyEnabled(CAMERA) } } // LINT.ThenChange(AdaptiveSleepPreferenceController.java) src/com/android/settings/display/AdaptiveSleepPreferenceController.java +3 −1 Original line number Diff line number Diff line Loading @@ -42,9 +42,10 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.google.common.annotations.VisibleForTesting; // LINT.IfChange /** The controller for Screen attention switch preference. */ public class AdaptiveSleepPreferenceController { public static final String PREFERENCE_KEY = "adaptive_sleep"; public static final String PREFERENCE_KEY = Settings.Secure.ADAPTIVE_SLEEP; private static final int DEFAULT_VALUE = 0; private final SensorPrivacyManager mPrivacyManager; private final RestrictionUtils mRestrictionUtils; Loading Loading @@ -147,3 +148,4 @@ public class AdaptiveSleepPreferenceController { Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED; } } // LINT.ThenChange(AdaptiveSleepPreference.kt) src/com/android/settings/display/ScreenTimeoutScreen.kt +8 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,10 @@ package com.android.settings.display import android.content.Context import com.android.settings.R import com.android.settings.Settings.ScreenTimeoutActivity import com.android.settings.flags.Flags import com.android.settings.utils.makeLaunchIntent import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.ProvidePreferenceScreen import com.android.settingslib.metadata.preferenceHierarchy import com.android.settingslib.preference.PreferenceScreenCreator Loading @@ -39,7 +42,11 @@ class ScreenTimeoutScreen : PreferenceScreenCreator { override fun hasCompleteHierarchy() = false override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {} override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) { +AdaptiveSleepPreference() } override fun getLaunchIntent(context: Context, metadata: PreferenceMetadata?) = makeLaunchIntent(context, ScreenTimeoutActivity::class.java, metadata?.key) companion object { const val KEY = "screen_timeout" Loading src/com/android/settings/display/ScreenTimeoutSettings.java +26 −8 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; Loading Loading @@ -83,8 +84,10 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment @Override public void onReceive(Context context, Intent intent) { mAdaptiveSleepBatterySaverPreferenceController.updateVisibility(); if (!isCatalystEnabled()) { mAdaptiveSleepController.updatePreference(); } } }; private DevicePolicyManager mDevicePolicyManager; Loading Loading @@ -126,7 +129,6 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class); mInitialEntries = getResources().getStringArray(R.array.screen_timeout_entries); mInitialValues = getResources().getStringArray(R.array.screen_timeout_values); mAdaptiveSleepController = new AdaptiveSleepPreferenceController(context); mAdaptiveSleepPermissionController = new AdaptiveSleepPermissionPreferenceController(context); mAdaptiveSleepCameraStatePreferenceController = Loading @@ -139,8 +141,12 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment mPrivacyPreference.setSelectable(false); mPrivacyPreference.setLayoutResource( com.android.settingslib.widget.preference.footer.R.layout.preference_footer); if (!isCatalystEnabled()) { mPrivacyManager = SensorPrivacyManager.getInstance(context); mPrivacyChangedListener = (sensor, enabled) -> mAdaptiveSleepController.updatePreference(); mAdaptiveSleepController = new AdaptiveSleepPreferenceController(context); mPrivacyChangedListener = (sensor, enabled) -> mAdaptiveSleepController.updatePreference(); } mAdditionalTogglePreferenceController = FeatureFactory.getFeatureFactory() .getDisplayFeatureProvider().createAdditionalPreference(context); } Loading Loading @@ -169,10 +175,12 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment mAdaptiveSleepPermissionController.updateVisibility(); mAdaptiveSleepCameraStatePreferenceController.updateVisibility(); mAdaptiveSleepBatterySaverPreferenceController.updateVisibility(); mAdaptiveSleepController.updatePreference(); mContext.registerReceiver( mReceiver, new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); if (!isCatalystEnabled()) { mAdaptiveSleepController.updatePreference(); mPrivacyManager.addSensorPrivacyListener(CAMERA, mPrivacyChangedListener); } mIsUserAuthenticated = false; FeatureFactory.getFeatureFactory().getDisplayFeatureProvider().updatePreference( mAdditionalTogglePreferenceController); Loading @@ -182,13 +190,17 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment public void onStop() { super.onStop(); mContext.unregisterReceiver(mReceiver); if (!isCatalystEnabled()) { mPrivacyManager.removeSensorPrivacyListener(CAMERA, mPrivacyChangedListener); } } @Override public void updateCandidates() { final String defaultKey = getDefaultKey(); final PreferenceScreen screen = getPreferenceScreen(); // Adaptive sleep preference is added to the screen when catalyst is enabled Preference adaptiveSleepPreference = screen.findPreference(AdaptiveSleepPreference.KEY); screen.removeAll(); final List<? extends CandidateInfo> candidateList = getCandidates(); Loading Loading @@ -228,7 +240,13 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment if (isAdaptiveSleepSupported(getContext())) { mAdaptiveSleepPermissionController.addToScreen(screen); mAdaptiveSleepCameraStatePreferenceController.addToScreen(screen); if (adaptiveSleepPreference != null) { // reset order for appending adaptiveSleepPreference.setOrder(Preference.DEFAULT_ORDER); screen.addPreference(adaptiveSleepPreference); } else { mAdaptiveSleepController.addToScreen(screen); } mAdaptiveSleepBatterySaverPreferenceController.addToScreen(screen); screen.addPreference(mPrivacyPreference); } Loading Loading
src/com/android/settings/display/AdaptiveSleepPreference.kt 0 → 100644 +137 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.hardware.SensorPrivacyManager import android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener import android.hardware.SensorPrivacyManager.Sensors.CAMERA import android.os.PowerManager import android.os.UserManager import android.provider.Settings import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R import com.android.settingslib.RestrictedSwitchPreference import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObservableDelegate import com.android.settingslib.datastore.SettingsSecureStore import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.TwoStatePreference import com.android.settingslib.preference.PreferenceBindingPlaceholder import com.android.settingslib.preference.SwitchPreferenceBinding // LINT.IfChange class AdaptiveSleepPreference : TwoStatePreference, SwitchPreferenceBinding, PreferenceLifecycleProvider, PreferenceBindingPlaceholder, // not needed once controller class is cleaned up PreferenceAvailabilityProvider, PreferenceRestrictionMixin { private var broadcastReceiver: BroadcastReceiver? = null private var sensorPrivacyChangedListener: OnSensorPrivacyChangedListener? = null override val key: String get() = KEY override val title: Int get() = R.string.adaptive_sleep_title override val summary: Int get() = R.string.adaptive_sleep_description override fun isIndexable(context: Context) = false override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context) && context.canBeEnabled() override val restrictionKeys: Array<String> get() = arrayOf(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT) override fun isAvailable(context: Context) = context.isAdaptiveSleepSupported() override fun createWidget(context: Context) = RestrictedSwitchPreference(context) override fun storage(context: Context): KeyValueStore = Storage(context) override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) = ReadWritePermit.ALLOW override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) = ReadWritePermit.ALLOW @Suppress("UNCHECKED_CAST") private class Storage( private val context: Context, private val settingsStore: SettingsStore = SettingsSecureStore.get(context), ) : KeyedObservableDelegate<String>(settingsStore), KeyValueStore { override fun contains(key: String) = settingsStore.contains(key) override fun <T : Any> getValue(key: String, valueType: Class<T>) = (context.canBeEnabled() && settingsStore.getBoolean(key) == true) as T override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) = settingsStore.setBoolean(key, value as Boolean?) } override fun onStart(context: PreferenceLifecycleContext) { val receiver = object : BroadcastReceiver() { override fun onReceive(receiverContext: Context, intent: Intent) { context.notifyPreferenceChange(this@AdaptiveSleepPreference) } } context.registerReceiver( receiver, IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED), ) broadcastReceiver = receiver val listener = OnSensorPrivacyChangedListener { _, _ -> context.notifyPreferenceChange(this) } SensorPrivacyManager.getInstance(context).addSensorPrivacyListener(CAMERA, listener) sensorPrivacyChangedListener = listener } override fun onStop(context: PreferenceLifecycleContext) { broadcastReceiver?.let { context.unregisterReceiver(it) } sensorPrivacyChangedListener?.let { SensorPrivacyManager.getInstance(context).removeSensorPrivacyListener(it) } } companion object { const val KEY = Settings.Secure.ADAPTIVE_SLEEP @Suppress("DEPRECATION") private fun Context.canBeEnabled() = AdaptiveSleepPreferenceController.hasSufficientPermission(packageManager) && getSystemService(PowerManager::class.java)?.isPowerSaveMode != true && !SensorPrivacyManager.getInstance(this).isSensorPrivacyEnabled(CAMERA) } } // LINT.ThenChange(AdaptiveSleepPreferenceController.java)
src/com/android/settings/display/AdaptiveSleepPreferenceController.java +3 −1 Original line number Diff line number Diff line Loading @@ -42,9 +42,10 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.google.common.annotations.VisibleForTesting; // LINT.IfChange /** The controller for Screen attention switch preference. */ public class AdaptiveSleepPreferenceController { public static final String PREFERENCE_KEY = "adaptive_sleep"; public static final String PREFERENCE_KEY = Settings.Secure.ADAPTIVE_SLEEP; private static final int DEFAULT_VALUE = 0; private final SensorPrivacyManager mPrivacyManager; private final RestrictionUtils mRestrictionUtils; Loading Loading @@ -147,3 +148,4 @@ public class AdaptiveSleepPreferenceController { Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED; } } // LINT.ThenChange(AdaptiveSleepPreference.kt)
src/com/android/settings/display/ScreenTimeoutScreen.kt +8 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,10 @@ package com.android.settings.display import android.content.Context import com.android.settings.R import com.android.settings.Settings.ScreenTimeoutActivity import com.android.settings.flags.Flags import com.android.settings.utils.makeLaunchIntent import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.ProvidePreferenceScreen import com.android.settingslib.metadata.preferenceHierarchy import com.android.settingslib.preference.PreferenceScreenCreator Loading @@ -39,7 +42,11 @@ class ScreenTimeoutScreen : PreferenceScreenCreator { override fun hasCompleteHierarchy() = false override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {} override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) { +AdaptiveSleepPreference() } override fun getLaunchIntent(context: Context, metadata: PreferenceMetadata?) = makeLaunchIntent(context, ScreenTimeoutActivity::class.java, metadata?.key) companion object { const val KEY = "screen_timeout" Loading
src/com/android/settings/display/ScreenTimeoutSettings.java +26 −8 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; Loading Loading @@ -83,8 +84,10 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment @Override public void onReceive(Context context, Intent intent) { mAdaptiveSleepBatterySaverPreferenceController.updateVisibility(); if (!isCatalystEnabled()) { mAdaptiveSleepController.updatePreference(); } } }; private DevicePolicyManager mDevicePolicyManager; Loading Loading @@ -126,7 +129,6 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class); mInitialEntries = getResources().getStringArray(R.array.screen_timeout_entries); mInitialValues = getResources().getStringArray(R.array.screen_timeout_values); mAdaptiveSleepController = new AdaptiveSleepPreferenceController(context); mAdaptiveSleepPermissionController = new AdaptiveSleepPermissionPreferenceController(context); mAdaptiveSleepCameraStatePreferenceController = Loading @@ -139,8 +141,12 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment mPrivacyPreference.setSelectable(false); mPrivacyPreference.setLayoutResource( com.android.settingslib.widget.preference.footer.R.layout.preference_footer); if (!isCatalystEnabled()) { mPrivacyManager = SensorPrivacyManager.getInstance(context); mPrivacyChangedListener = (sensor, enabled) -> mAdaptiveSleepController.updatePreference(); mAdaptiveSleepController = new AdaptiveSleepPreferenceController(context); mPrivacyChangedListener = (sensor, enabled) -> mAdaptiveSleepController.updatePreference(); } mAdditionalTogglePreferenceController = FeatureFactory.getFeatureFactory() .getDisplayFeatureProvider().createAdditionalPreference(context); } Loading Loading @@ -169,10 +175,12 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment mAdaptiveSleepPermissionController.updateVisibility(); mAdaptiveSleepCameraStatePreferenceController.updateVisibility(); mAdaptiveSleepBatterySaverPreferenceController.updateVisibility(); mAdaptiveSleepController.updatePreference(); mContext.registerReceiver( mReceiver, new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); if (!isCatalystEnabled()) { mAdaptiveSleepController.updatePreference(); mPrivacyManager.addSensorPrivacyListener(CAMERA, mPrivacyChangedListener); } mIsUserAuthenticated = false; FeatureFactory.getFeatureFactory().getDisplayFeatureProvider().updatePreference( mAdditionalTogglePreferenceController); Loading @@ -182,13 +190,17 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment public void onStop() { super.onStop(); mContext.unregisterReceiver(mReceiver); if (!isCatalystEnabled()) { mPrivacyManager.removeSensorPrivacyListener(CAMERA, mPrivacyChangedListener); } } @Override public void updateCandidates() { final String defaultKey = getDefaultKey(); final PreferenceScreen screen = getPreferenceScreen(); // Adaptive sleep preference is added to the screen when catalyst is enabled Preference adaptiveSleepPreference = screen.findPreference(AdaptiveSleepPreference.KEY); screen.removeAll(); final List<? extends CandidateInfo> candidateList = getCandidates(); Loading Loading @@ -228,7 +240,13 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment if (isAdaptiveSleepSupported(getContext())) { mAdaptiveSleepPermissionController.addToScreen(screen); mAdaptiveSleepCameraStatePreferenceController.addToScreen(screen); if (adaptiveSleepPreference != null) { // reset order for appending adaptiveSleepPreference.setOrder(Preference.DEFAULT_ORDER); screen.addPreference(adaptiveSleepPreference); } else { mAdaptiveSleepController.addToScreen(screen); } mAdaptiveSleepBatterySaverPreferenceController.addToScreen(screen); screen.addPreference(mPrivacyPreference); } Loading