1 /* 2 * Copyright (C) 2024 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.notification; 18 19 import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS; 20 21 import android.content.ContentResolver; 22 import android.content.Context; 23 import android.database.ContentObserver; 24 import android.net.Uri; 25 import android.os.Handler; 26 import android.os.Looper; 27 import android.provider.Settings; 28 29 import androidx.annotation.NonNull; 30 import androidx.annotation.Nullable; 31 import androidx.lifecycle.Lifecycle; 32 import androidx.lifecycle.LifecycleEventObserver; 33 import androidx.lifecycle.LifecycleOwner; 34 import androidx.preference.Preference; 35 import androidx.preference.PreferenceScreen; 36 37 import com.android.server.notification.Flags; 38 import com.android.settings.core.TogglePreferenceController; 39 40 /** 41 * Controls the toggle that determines whether to hide seen notifications from the lock screen. 42 * Toggle for setting: Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS 43 */ 44 public class LockScreenNotificationShowSeenController extends TogglePreferenceController 45 implements LifecycleEventObserver { 46 47 // 0 is the default value for phones, we treat 0 as off as usage 48 private static final int UNSET_OFF = 0; 49 static final int ON = 1; 50 static final int OFF = 2; 51 @Nullable private Preference mPreference; 52 private final ContentResolver mContentResolver; 53 54 final ContentObserver mContentObserver = new ContentObserver( 55 new Handler(Looper.getMainLooper())) { 56 @Override 57 public void onChange(boolean selfChange, @Nullable Uri uri) { 58 if (mPreference == null) return; 59 updateState(mPreference); 60 } 61 }; 62 LockScreenNotificationShowSeenController(@onNull Context context, @NonNull String preferenceKey)63 public LockScreenNotificationShowSeenController(@NonNull Context context, 64 @NonNull String preferenceKey) { 65 super(context, preferenceKey); 66 mContentResolver = context.getContentResolver(); 67 } 68 69 @Override displayPreference(@onNull PreferenceScreen screen)70 public void displayPreference(@NonNull PreferenceScreen screen) { 71 super.displayPreference(screen); 72 mPreference = screen.findPreference(getPreferenceKey()); 73 } 74 75 @Override onStateChanged(@onNull LifecycleOwner lifecycleOwner, @NonNull Lifecycle.Event event)76 public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, 77 @NonNull Lifecycle.Event event) { 78 if (event == Lifecycle.Event.ON_RESUME) { 79 mContentResolver.registerContentObserver( 80 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), 81 /* notifyForDescendants= */ false, mContentObserver); 82 mContentResolver.registerContentObserver( 83 Settings.Secure.getUriFor( 84 Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS), 85 /* notifyForDescendants= */ false, 86 mContentObserver 87 ); 88 } else if (event == Lifecycle.Event.ON_PAUSE) { 89 mContentResolver.unregisterContentObserver(mContentObserver); 90 } 91 } 92 93 @Override updateState(@onNull Preference preference)94 public void updateState(@NonNull Preference preference) { 95 super.updateState(preference); 96 setChecked(lockScreenShowSeenNotifications()); 97 preference.setVisible(isAvailable()); 98 } 99 100 @Override getAvailabilityStatus()101 public int getAvailabilityStatus() { 102 if (Flags.notificationMinimalism()) { 103 if (!lockScreenShowNotification()) { 104 return CONDITIONALLY_UNAVAILABLE; 105 } 106 // We want to show the switch when the lock screen notification minimalism flag is on. 107 return AVAILABLE; 108 } 109 110 int setting = Settings.Secure.getInt(mContext.getContentResolver(), 111 LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, UNSET_OFF); 112 if (setting == UNSET_OFF) { 113 // hide the setting if the minimalism flag is off, and the device is phone 114 // UNSET_OFF is the default value for phones 115 return CONDITIONALLY_UNAVAILABLE; 116 } else { 117 return AVAILABLE; 118 } 119 } 120 121 /** 122 * @return Whether showing notifications on the lockscreen is enabled. 123 */ lockScreenShowNotification()124 private boolean lockScreenShowNotification() { 125 return Settings.Secure.getInt(mContext.getContentResolver(), 126 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, OFF) == ON; 127 } 128 129 @Override isChecked()130 public boolean isChecked() { 131 return lockScreenShowSeenNotifications(); 132 } 133 134 /** 135 * @return whether to show seen notifications on lockscreen 136 */ lockScreenShowSeenNotifications()137 private boolean lockScreenShowSeenNotifications() { 138 // UNSET_OFF is the default value for phone, which is equivalent to off in effect 139 // (show seen notification) 140 return Settings.Secure.getInt(mContext.getContentResolver(), 141 Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, UNSET_OFF) != ON; 142 } 143 144 @Override setChecked(boolean isChecked)145 public boolean setChecked(boolean isChecked) { 146 return Settings.Secure.putInt(mContext.getContentResolver(), 147 Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, (isChecked ? OFF : ON)); 148 } 149 150 @Override getSliceHighlightMenuRes()151 public int getSliceHighlightMenuRes() { 152 // not needed because Sliceable is deprecated 153 return NO_RES; 154 } 155 } 156