Fixing notification dots settings not updated properly

Also avoiding settings cache reset whenever someone registers
a new listener

Bug: 184200027
Test: Manual
Change-Id: I0c8b7084b6b4656102e9041b779b80a98624ddd8
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index ccc023a..4754558 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -116,7 +116,7 @@
         mNotificationSettingsChangedListener = this::onNotificationSettingsChanged;
         mSettingsCache.register(NOTIFICATION_BADGING_URI,
                 mNotificationSettingsChangedListener);
-        mSettingsCache.dispatchOnChange(NOTIFICATION_BADGING_URI);
+        onNotificationSettingsChanged(mSettingsCache.getValue(NOTIFICATION_BADGING_URI));
     }
 
     public LauncherAppState(Context context, @Nullable String iconCacheFileName) {
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 2905dc3..e58f5fa 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -16,9 +16,9 @@
 
 package com.android.launcher3.notification;
 
-import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
 
 import android.annotation.TargetApi;
 import android.app.Notification;
@@ -37,8 +37,8 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
 
-import com.android.launcher3.util.SettingsCache;
 import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.util.SettingsCache;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -213,7 +213,7 @@
         mNotificationSettingsChangedListener = this::onNotificationSettingsChanged;
         mSettingsCache.register(NOTIFICATION_BADGING_URI,
                 mNotificationSettingsChangedListener);
-        mSettingsCache.dispatchOnChange(NOTIFICATION_BADGING_URI);
+        onNotificationSettingsChanged(mSettingsCache.getValue(NOTIFICATION_BADGING_URI));
 
         onNotificationFullRefresh();
     }
diff --git a/src/com/android/launcher3/settings/NotificationDotsPreference.java b/src/com/android/launcher3/settings/NotificationDotsPreference.java
index a354169..afcf882 100644
--- a/src/com/android/launcher3/settings/NotificationDotsPreference.java
+++ b/src/com/android/launcher3/settings/NotificationDotsPreference.java
@@ -17,6 +17,8 @@
 
 import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
 import static com.android.launcher3.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGS;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -24,6 +26,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.database.ContentObserver;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.util.AttributeSet;
@@ -49,6 +52,14 @@
     /** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
     private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners";
 
+    private final ContentObserver mListenerListObserver =
+            new ContentObserver(MAIN_EXECUTOR.getHandler()) {
+        @Override
+        public void onChange(boolean selfChange) {
+            updateUI();
+        }
+    };
+
     public NotificationDotsPreference(
             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
@@ -66,6 +77,29 @@
         super(context);
     }
 
+    @Override
+    public void onAttached() {
+        super.onAttached();
+        SettingsCache.INSTANCE.get(getContext()).register(NOTIFICATION_BADGING_URI, this);
+        getContext().getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(NOTIFICATION_ENABLED_LISTENERS),
+                false, mListenerListObserver);
+        updateUI();
+    }
+
+    private void updateUI() {
+        onSettingsChanged(SettingsCache.INSTANCE.get(getContext())
+                .getValue(NOTIFICATION_BADGING_URI));
+    }
+
+    @Override
+    public void onDetached() {
+        super.onDetached();
+        SettingsCache.INSTANCE.get(getContext()).unregister(NOTIFICATION_BADGING_URI, this);
+        getContext().getContentResolver().unregisterContentObserver(mListenerListObserver);
+
+    }
+
     private void setWidgetFrameVisible(boolean isVisible) {
         if (mWidgetFrameVisible != isVisible) {
             mWidgetFrameVisible = isVisible;
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index f03065c..5b42ac7 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -18,8 +18,6 @@
 
 import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
 
-import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
-import static com.android.launcher3.util.SettingsCache.NOTIFICATION_ENABLED_LISTENERS;
 import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
 import static com.android.launcher3.states.RotationHelper.getAllowRotationDefaultValue;
 
@@ -45,7 +43,6 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.WidgetsModel;
-import com.android.launcher3.util.SettingsCache;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
 
 /**
@@ -124,11 +121,8 @@
      */
     public static class LauncherSettingsFragment extends PreferenceFragmentCompat {
 
-        private SettingsCache mSettingsCache;
-
         private String mHighLightKey;
         private boolean mPreferenceHighlighted = false;
-        private NotificationDotsPreference mNotificationSettingsChangedListener;
         private Preference mDeveloperOptionPref;
 
         @Override
@@ -172,22 +166,7 @@
         protected boolean initPreference(Preference preference) {
             switch (preference.getKey()) {
                 case NOTIFICATION_DOTS_PREFERENCE_KEY:
-                    if (WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS) {
-                        return false;
-                    }
-
-                    // Listen to system notification dot settings while this UI is active.
-                    mSettingsCache = SettingsCache.INSTANCE.get(getActivity());
-                    mNotificationSettingsChangedListener =
-                            ((NotificationDotsPreference) preference);
-                    mSettingsCache.register(NOTIFICATION_BADGING_URI,
-                            (NotificationDotsPreference) mNotificationSettingsChangedListener);
-                    // Also listen if notification permission changes
-                    mSettingsCache.register(NOTIFICATION_ENABLED_LISTENERS,
-                            mNotificationSettingsChangedListener);
-                    mSettingsCache.dispatchOnChange(NOTIFICATION_BADGING_URI);
-                    mSettingsCache.dispatchOnChange(NOTIFICATION_ENABLED_LISTENERS);
-                    return true;
+                    return !WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS;
 
                 case ALLOW_ROTATION_PREFERENCE_KEY:
                     if (getResources().getBoolean(R.bool.allow_rotation)) {
@@ -269,16 +248,5 @@
                 }
             });
         }
-
-        @Override
-        public void onDestroy() {
-            if (mSettingsCache != null) {
-                mSettingsCache.unregister(NOTIFICATION_BADGING_URI,
-                        mNotificationSettingsChangedListener);
-                mSettingsCache.unregister(NOTIFICATION_ENABLED_LISTENERS,
-                        mNotificationSettingsChangedListener);
-            }
-            super.onDestroy();
-        }
     }
 }
diff --git a/src/com/android/launcher3/util/SettingsCache.java b/src/com/android/launcher3/util/SettingsCache.java
index 22b4d38..10611c7 100644
--- a/src/com/android/launcher3/util/SettingsCache.java
+++ b/src/com/android/launcher3/util/SettingsCache.java
@@ -39,12 +39,11 @@
  * {@link #unregister(Uri, OnChangeListener)} methods.
  *
  * This can be used as a normal cache without any listeners as well via the
- * {@link #getValue(Uri, int)} and {@link #dispatchOnChange(Uri)} to update (and subsequently call
+ * {@link #getValue(Uri, int)} and {@link #onChange)} to update (and subsequently call
  * get)
  *
  * The cache will be invalidated/updated through the normal
  * {@link ContentObserver#onChange(boolean)} calls
- * or can be force updated by calling {@link #dispatchOnChange(Uri)}.
  *
  * Cache will also be updated if a key queried is missing (even if it has no listeners registered).
  */
@@ -58,9 +57,6 @@
     /** Hidden field Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED */
     public static final String ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED =
             "swipe_bottom_to_notification_enabled";
-    /** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
-    public static final Uri NOTIFICATION_ENABLED_LISTENERS =
-            Settings.Secure.getUriFor("enabled_notification_listeners");
     public static final Uri ROTATION_SETTING_URI =
             Settings.System.getUriFor(ACCELEROMETER_ROTATION);
 
@@ -103,6 +99,14 @@
      * Returns the value for this classes key from the cache. If not in cache, will call
      * {@link #updateValue(Uri, int)} to fetch.
      */
+    public boolean getValue(Uri keySetting) {
+        return getValue(keySetting, 1);
+    }
+
+    /**
+     * Returns the value for this classes key from the cache. If not in cache, will call
+     * {@link #updateValue(Uri, int)} to fetch.
+     */
     public boolean getValue(Uri keySetting, int defaultValue) {
         if (mKeyCache.containsKey(keySetting)) {
             return mKeyCache.get(keySetting);
@@ -140,14 +144,6 @@
     }
 
     /**
-     * Force update a change for a given URI and have all listeners for that URI receive callbacks
-     * even if the value is unchanged.
-     */
-    public void dispatchOnChange(Uri uri) {
-        onChange(true, uri);
-    }
-
-    /**
      * Call to stop receiving updates on the given {@param listener}.
      * This Uri/Listener pair must correspond to the same pair called with for
      * {@link #register(Uri, OnChangeListener)}