Add a new persistent FUSE flag in Settings

New system property settings_fuse enables user to switch persist.sys.fuse
flag on/off from Settings UI. New system property is added as the
Settings UI sets system property with a fixed prefix
(persist.sys.fflag.override.) for persistent properties and for
consistency we do not want to rename persist.sys.fuse.

The user needs to restart the device after toggling the flag from
Settings UI. When the device restarts for the first time,
persist.sys.fuse is set from settings_fuse when the
StorageManagerService starts. If the value of persist.sys.fuse is
modified, then the device reboots for it to take effect.

The 2 reboots take almost the same time as 1 reboot and the difference is
not noticeable to the user as the lock screen does not show up in
between the 2 reboots.

This change would also mean that the newly added flag
(persist.sys.fflag.override.settings_fuse) will always override
persist.sys.fuse (as it is always checked on reboot), which implies that
`adb shell setprop persist.sys.fuse [true/false] && adb reboot` will
have no effect.

Bug:144419848
Test: * Enable developer options in Settings.
      * Go to Settings->System->Advanced->Developer Options->Feature Flags.
      * Turn on (off by default) settings_fuse toggle button and
        restart.
      * After reboot run `adb shell getprop persist.sys.fuse` shows
        true.
      * Turn off settings_fuse from Settings UI and reboot
      * After reboot run `adb shell getprop persist.sys.fuse` shows
        false.
Test: Using adb command to change the fuse system property.
      * `adb shell setprop persist.sys.fflag.override.settings_fuse
         true && adb reboot`
      * After reboot run `adb shell getprop persist.sys.fuse` shows true
      * Similarly for false case.
Change-Id: I0093d2b020a9d8ffeec7fca31a44ef2e65b4dfb4
diff --git a/api/test-current.txt b/api/test-current.txt
index dacc5d6..9a46848 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4270,6 +4270,7 @@
     field public static final String PERSIST_PREFIX = "persist.sys.fflag.override.";
     field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
     field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
+    field public static final String SETTINGS_FUSE_FLAG = "settings_fuse";
     field public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
   }
 
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 7e09740..236e5ae 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -41,6 +41,7 @@
     public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
     public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
     public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
+    public static final String SETTINGS_FUSE_FLAG = "settings_fuse";
 
     private static final Map<String, String> DEFAULT_FLAGS;
 
@@ -48,6 +49,7 @@
         DEFAULT_FLAGS = new HashMap<>();
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
+        DEFAULT_FLAGS.put(SETTINGS_FUSE_FLAG, "false");
         DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
         DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d8ae1e4..7639c4d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -118,6 +118,7 @@
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.DataUnit;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
@@ -819,7 +820,6 @@
                     refreshFuseSettings();
                 });
         refreshIsolatedStorageSettings();
-        refreshFuseSettings();
     }
 
     /**
@@ -883,16 +883,25 @@
         SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
     }
 
+    /**
+     * The most recent flag change takes precedence. Change fuse Settings flag if Device Config is
+     * changed. Settings flag change will in turn change fuse system property (persist.sys.fuse)
+     * whenever the user reboots.
+     */
     private void refreshFuseSettings() {
         int isFuseEnabled = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                 FUSE_ENABLED, 0);
         if (isFuseEnabled == 1) {
-            SystemProperties.set(StorageManager.PROP_FUSE, "true");
+            Slog.d(TAG, "Device Config flag for FUSE is enabled, turn Settings fuse flag on");
+            SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
+                    + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "true");
         } else if (isFuseEnabled == -1) {
-            SystemProperties.set(StorageManager.PROP_FUSE, "false");
+            Slog.d(TAG, "Device Config flag for FUSE is disabled, turn Settings fuse flag off");
+            SystemProperties.set(FeatureFlagUtils.PERSIST_PREFIX
+                    + FeatureFlagUtils.SETTINGS_FUSE_FLAG, "false");
         }
         // else, keep the build config.
-        // This can be overridden be direct adjustment of persist.sys.prop
+        // This can be overridden by direct adjustment of persist.sys.fflag.override.settings_fuse
     }
 
     /**
@@ -1548,6 +1557,8 @@
     public StorageManagerService(Context context) {
         sSelf = this;
 
+        updateFusePropFromSettings();
+
         // Snapshot feature flag used for this boot
         SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
                 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
@@ -1609,6 +1620,23 @@
         }
     }
 
+    /**
+     *  Checks if user changed the persistent settings_fuse flag from Settings UI
+     *  and updates PROP_FUSE (reboots if changed).
+     */
+    private void updateFusePropFromSettings() {
+        Boolean settingsFuseFlag = SystemProperties.getBoolean((FeatureFlagUtils.PERSIST_PREFIX
+                + FeatureFlagUtils.SETTINGS_FUSE_FLAG), false);
+        Slog.d(TAG, "The value of Settings Fuse Flag is " + settingsFuseFlag);
+        if (SystemProperties.getBoolean(StorageManager.PROP_FUSE, false) != settingsFuseFlag) {
+            Slog.d(TAG, "Set persist.sys.fuse to " + settingsFuseFlag);
+            SystemProperties.set(StorageManager.PROP_FUSE, Boolean.toString(settingsFuseFlag));
+            // Perform hard reboot to kick policy into place
+            mContext.getSystemService(PowerManager.class).reboot("Reboot device for FUSE system"
+                    + "property change to take effect");
+        }
+    }
+
     private void start() {
         connectStoraged();
         connectVold();