diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java index e5a12847623..363d601d0d1 100644 --- a/src/com/android/settings/SettingsPreferenceFragment.java +++ b/src/com/android/settings/SettingsPreferenceFragment.java @@ -186,7 +186,7 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF } /** Returns if catalyst is enabled on current screen. */ - protected final boolean isCatalystEnabled() { + public final boolean isCatalystEnabled() { // TODO(b/379130874): make Catalyst compatible with desktop device, such as user restriction // check. Context context = getContext(); diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt new file mode 100644 index 00000000000..0537e625159 --- /dev/null +++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt @@ -0,0 +1,116 @@ +/* + * 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.Context +import android.hardware.display.AmbientDisplayConfiguration +import android.os.SystemProperties +import android.os.UserHandle +import android.os.UserManager +import android.provider.Settings.Secure.DOZE_ALWAYS_ON +import com.android.settings.PreferenceRestrictionMixin +import com.android.settings.R +import com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController.isAodSuppressedByBedtime +import com.android.settingslib.datastore.HandlerExecutor +import com.android.settingslib.datastore.KeyValueStore +import com.android.settingslib.datastore.KeyedObservableDelegate +import com.android.settingslib.datastore.KeyedObserver +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.PreferenceSummaryProvider +import com.android.settingslib.metadata.ReadWritePermit +import com.android.settingslib.metadata.SwitchPreference + +// LINT.IfChange +class AmbientDisplayAlwaysOnPreference : + SwitchPreference(KEY, R.string.doze_always_on_title, R.string.doze_always_on_summary), + PreferenceAvailabilityProvider, + PreferenceSummaryProvider, + PreferenceLifecycleProvider, + PreferenceRestrictionMixin { + + private var keyMappingObserver: KeyedObserver? = null + + override val keywords: Int + get() = R.string.keywords_always_show_time_info + + override val restrictionKeys: Array + get() = arrayOf(UserManager.DISALLOW_AMBIENT_DISPLAY) + + override fun isEnabled(context: Context) = super.isEnabled(context) + + override fun isAvailable(context: Context) = + !SystemProperties.getBoolean(PROP_AWARE_AVAILABLE, false) && + AmbientDisplayConfiguration(context).alwaysOnAvailableForUser(UserHandle.myUserId()) + + override fun getSummary(context: Context): CharSequence? = + context.getText( + when { + isAodSuppressedByBedtime(context) -> R.string.aware_summary_when_bedtime_on + else -> R.string.doze_always_on_summary + } + ) + + 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 + + override fun onCreate(context: PreferenceLifecycleContext) { + val storage = SettingsSecureStore.get(context) + keyMappingObserver = + KeyedObserver { _, reason -> storage.notifyChange(KEY, reason) } + .also { storage.addObserver(DOZE_ALWAYS_ON, it, HandlerExecutor.main) } + } + + override fun onDestroy(context: PreferenceLifecycleContext) { + keyMappingObserver?.let { + SettingsSecureStore.get(context).removeObserver(DOZE_ALWAYS_ON, it) + } + } + + @Suppress("UNCHECKED_CAST") + class Storage( + private val context: Context, + private val settingsStore: SettingsStore = SettingsSecureStore.get(context), + ) : KeyedObservableDelegate(settingsStore), KeyValueStore { + + override fun contains(key: String) = settingsStore.contains(DOZE_ALWAYS_ON) + + override fun getDefaultValue(key: String, valueType: Class) = + context.resources.getBoolean(com.android.internal.R.bool.config_dozeAlwaysOnEnabled) + as T + + override fun getValue(key: String, valueType: Class) = + settingsStore.getValue(DOZE_ALWAYS_ON, valueType) ?: getDefaultValue(key, valueType) + + override fun setValue(key: String, valueType: Class, value: T?) = + settingsStore.setValue(DOZE_ALWAYS_ON, valueType, value) + } + + companion object { + const val KEY = "ambient_display_always_on" + private const val PROP_AWARE_AVAILABLE = "ro.vendor.aware_available" + } +} +// LINT.ThenChange(AmbientDisplayAlwaysOnPreferenceController.java) diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java index 245803493e2..17cecad0810 100644 --- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java +++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java @@ -29,6 +29,7 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +// LINT.IfChange public class AmbientDisplayAlwaysOnPreferenceController extends TogglePreferenceController { private final int ON = 1; @@ -130,3 +131,4 @@ public class AmbientDisplayAlwaysOnPreferenceController extends TogglePreference return powerManager.isAmbientDisplaySuppressedForTokenByApp(AOD_SUPPRESSED_TOKEN, uid); } } +// LINT.ThenChange(AmbientDisplayAlwaysOnPreference.kt) diff --git a/src/com/android/settings/security/LockScreenPreferenceScreen.kt b/src/com/android/settings/security/LockScreenPreferenceScreen.kt index 55c18d96ff8..3c00b428ebd 100644 --- a/src/com/android/settings/security/LockScreenPreferenceScreen.kt +++ b/src/com/android/settings/security/LockScreenPreferenceScreen.kt @@ -17,8 +17,12 @@ package com.android.settings.security import android.content.Context import com.android.settings.R +import com.android.settings.Settings.LockScreenSettingsActivity +import com.android.settings.display.AmbientDisplayAlwaysOnPreference import com.android.settings.flags.Flags import com.android.settings.notification.LockScreenNotificationPreferenceController +import com.android.settings.utils.makeLaunchIntent +import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceSummaryProvider import com.android.settingslib.metadata.ProvidePreferenceScreen import com.android.settingslib.metadata.preferenceHierarchy @@ -44,9 +48,12 @@ open class LockScreenPreferenceScreen : PreferenceScreenCreator, PreferenceSumma override fun fragmentClass() = LockscreenDashboardFragment::class.java + override fun getLaunchIntent(context: Context, metadata: PreferenceMetadata?) = + makeLaunchIntent(context, LockScreenSettingsActivity::class.java, metadata?.key) + override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) { - // add hierarchy here + +AmbientDisplayAlwaysOnPreference() } companion object { diff --git a/src/com/android/settings/security/LockscreenDashboardFragment.java b/src/com/android/settings/security/LockscreenDashboardFragment.java index 1e299a36cf5..ef4c778549c 100644 --- a/src/com/android/settings/security/LockscreenDashboardFragment.java +++ b/src/com/android/settings/security/LockscreenDashboardFragment.java @@ -56,8 +56,6 @@ import java.util.List; public class LockscreenDashboardFragment extends DashboardFragment implements OwnerInfoPreferenceController.OwnerInfoCallback { - public static final String KEY_AMBIENT_DISPLAY_ALWAYS_ON = "ambient_display_always_on"; - private static final String TAG = "LockscreenDashboardFragment"; @VisibleForTesting @@ -111,7 +109,9 @@ public class LockscreenDashboardFragment extends DashboardFragment @Override public void onAttach(Context context) { super.onAttach(context); - use(AmbientDisplayAlwaysOnPreferenceController.class).setConfig(getConfig(context)); + if (!isCatalystEnabled()) { + use(AmbientDisplayAlwaysOnPreferenceController.class).setConfig(getConfig(context)); + } use(AmbientDisplayNotificationsPreferenceController.class).setConfig(getConfig(context)); use(DoubleTapScreenPreferenceController.class).setConfig(getConfig(context)); use(PickupGesturePreferenceController.class).setConfig(getConfig(context)); diff --git a/tests/robotests/src/com/android/settings/security/LockscreenDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/security/LockscreenDashboardFragmentTest.java index bf5e9577250..5ca9f729cc4 100644 --- a/tests/robotests/src/com/android/settings/security/LockscreenDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/security/LockscreenDashboardFragmentTest.java @@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import android.content.Context; @@ -88,7 +89,11 @@ public class LockscreenDashboardFragmentTest { AmbientDisplayAlwaysOnPreferenceController.class); mTestFragment.onAttach(mContext); - verify(controller).setConfig(any()); + if (mTestFragment.isCatalystEnabled()) { + verifyNoInteractions(controller); + } else { + verify(controller).setConfig(any()); + } } @Test