[Settings] Support master switch of inline toggle of Settings Injection v2

Allow developers to inject MasterSwitchPreference, a switch
preference with two tap targets, to Settings page.

Developers should declare keyhint and switch_uri for the activity
in AndroidManifest,and then implement a SwitchesProvider.

Bug: 132808482
Test: robotest
Change-Id: I64cdf18268be0cfcd38aab2c059144536dd79b32
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 4e541cb..282cdb9 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -60,6 +60,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.dashboard.profileselector.ProfileSelectDialog;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.MasterSwitchPreference;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.drawer.ActivityTile;
 import com.android.settingslib.drawer.DashboardCategory;
@@ -303,7 +304,7 @@
         setSwitchEnabled(pref, false);
         ThreadUtils.postOnBackgroundThread(() -> {
             final Map<String, IContentProvider> providerMap = new ArrayMap<>();
-            final Bundle result = TileUtils.putBooleanToUri(mContext, uri, providerMap,
+            final Bundle result = TileUtils.putBooleanToUriAndGetResult(mContext, uri, providerMap,
                     EXTRA_SWITCH_CHECKED_STATE, checked);
 
             ThreadUtils.postOnMainThread(() -> {
@@ -335,13 +336,19 @@
     }
 
     private void setSwitchChecked(Preference pref, boolean checked) {
-        if (pref instanceof SwitchPreference) {
+        if (pref instanceof MasterSwitchPreference) {
+            ((MasterSwitchPreference) pref).setChecked(checked);
+        } else if (pref instanceof SwitchPreference) {
             ((SwitchPreference) pref).setChecked(checked);
         }
     }
 
     private void setSwitchEnabled(Preference pref, boolean enabled) {
-        pref.setEnabled(enabled);
+        if (pref instanceof MasterSwitchPreference) {
+            ((MasterSwitchPreference) pref).setSwitchEnabled(enabled);
+        } else {
+            pref.setEnabled(enabled);
+        }
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 30d6df3..50630fe 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -38,6 +38,7 @@
 import com.android.settings.core.PreferenceControllerListHelper;
 import com.android.settings.core.SettingsBaseActivity;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.MasterSwitchPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -453,7 +454,9 @@
     Preference createPreference(Tile tile) {
         return tile instanceof ProviderTile
                 ? new SwitchPreference(getPrefContext())
-                : new Preference(getPrefContext());
+                : tile.hasSwitch()
+                        ? new MasterSwitchPreference(getPrefContext())
+                        : new Preference(getPrefContext());
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/widget/MasterSwitchPreference.java b/src/com/android/settings/widget/MasterSwitchPreference.java
index eb9301c..ad35cb0 100644
--- a/src/com/android/settings/widget/MasterSwitchPreference.java
+++ b/src/com/android/settings/widget/MasterSwitchPreference.java
@@ -36,6 +36,7 @@
 
     private Switch mSwitch;
     private boolean mChecked;
+    private boolean mCheckedSet;
     private boolean mEnableSwitch = true;
 
     public MasterSwitchPreference(Context context, AttributeSet attrs,
@@ -94,9 +95,14 @@
     }
 
     public void setChecked(boolean checked) {
-        mChecked = checked;
-        if (mSwitch != null) {
-            mSwitch.setChecked(checked);
+        // Always set checked the first time; don't assume the field's default of false.
+        final boolean changed = mChecked != checked;
+        if (changed || !mCheckedSet) {
+            mChecked = checked;
+            mCheckedSet = true;
+            if (mSwitch != null) {
+                mSwitch.setChecked(checked);
+            }
         }
     }
 
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
index 146b37a..42b600a 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -48,6 +48,7 @@
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.slices.BlockingSlicePrefController;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.widget.MasterSwitchPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
@@ -323,6 +324,15 @@
         assertThat(pref).isInstanceOf(SwitchPreference.class);
     }
 
+    @Test
+    public void createPreference_isActivityTileAndHasSwitch_returnMasterSwitchPreference() {
+        mActivityTile.getMetaData().putString(META_DATA_PREFERENCE_SWITCH_URI, "uri");
+
+        final Preference pref = mTestFragment.createPreference(mActivityTile);
+
+        assertThat(pref).isInstanceOf(MasterSwitchPreference.class);
+    }
+
     private static class TestPreferenceController extends AbstractPreferenceController
             implements PreferenceControllerMixin {
 
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowTileUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowTileUtils.java
index e1b815e..45a9dd6 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowTileUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowTileUtils.java
@@ -58,7 +58,7 @@
     }
 
     @Implementation
-    public static Bundle putBooleanToUri(Context context, Uri uri,
+    public static Bundle putBooleanToUriAndGetResult(Context context, Uri uri,
             Map<String, IContentProvider> providerMap, String key, boolean value) {
         sChecked = value;
         return sResult;