Game Driver: Add SwitchBar to control GUP feature

Uncheck the global switch will hide the preference controllers and force
all apps to use system graphics driver. This change also add a content
observer to notify all the preference controllers of settings global
changes.

Bug: 119221883
Test: make RunSettingsRoboTests
Change-Id: Ice9ded17c759791a3728c552f79881e2215ac081
diff --git a/src/com/android/settings/development/gup/GameDriverContentObserver.java b/src/com/android/settings/development/gup/GameDriverContentObserver.java
new file mode 100644
index 0000000..9260213
--- /dev/null
+++ b/src/com/android/settings/development/gup/GameDriverContentObserver.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2019 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.development.gup;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings;
+
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * Helper class to observe Game Driver settings global change.
+ */
+public class GameDriverContentObserver extends ContentObserver {
+    interface OnGameDriverContentChangedListener {
+        void onGameDriverContentChanged();
+    }
+
+    @VisibleForTesting
+    OnGameDriverContentChangedListener mListener;
+
+    public GameDriverContentObserver(Handler handler, OnGameDriverContentChangedListener listener) {
+        super(handler);
+        mListener = listener;
+    }
+
+    @Override
+    public void onChange(boolean selfChange) {
+        super.onChange(selfChange);
+        mListener.onGameDriverContentChanged();
+    }
+
+    public void register(ContentResolver contentResolver) {
+        contentResolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.GUP_DEV_ALL_APPS), false, this);
+    }
+
+    public void unregister(ContentResolver contentResolver) {
+        contentResolver.unregisterContentObserver(this);
+    }
+}
diff --git a/src/com/android/settings/development/gup/GupDashboard.java b/src/com/android/settings/development/gup/GupDashboard.java
index 0ab57e6..ed389af 100644
--- a/src/com/android/settings/development/gup/GupDashboard.java
+++ b/src/com/android/settings/development/gup/GupDashboard.java
@@ -18,18 +18,25 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.os.Bundle;
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
+import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.SwitchBarController;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.search.SearchIndexable;
 
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * Dashboard for Game Driver preferences.
+ */
 @SearchIndexable
 public class GupDashboard extends DashboardFragment {
     private static final String TAG = "GupDashboard";
@@ -54,6 +61,18 @@
         return 0;
     }
 
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        final SettingsActivity activity = (SettingsActivity) getActivity();
+        final SwitchBar switchBar = activity.getSwitchBar();
+        final GupGlobalSwitchBarController switchBarController =
+                new GupGlobalSwitchBarController(activity, new SwitchBarController(switchBar));
+        getSettingsLifecycle().addObserver(switchBarController);
+        switchBar.show();
+    }
+
     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
                 @Override
diff --git a/src/com/android/settings/development/gup/GupEnableForAllAppsPreferenceController.java b/src/com/android/settings/development/gup/GupEnableForAllAppsPreferenceController.java
index 43a28b6..ac460b2 100644
--- a/src/com/android/settings/development/gup/GupEnableForAllAppsPreferenceController.java
+++ b/src/com/android/settings/development/gup/GupEnableForAllAppsPreferenceController.java
@@ -18,54 +18,92 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
 import android.provider.Settings;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 
-public class GupEnableForAllAppsPreferenceController
-        extends BasePreferenceController implements Preference.OnPreferenceChangeListener {
+/**
+ * Controller of global switch to enable Game Driver for all Apps.
+ */
+public class GupEnableForAllAppsPreferenceController extends BasePreferenceController
+        implements Preference.OnPreferenceChangeListener,
+                   GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
+                   OnStart, OnStop {
     public static final int GUP_DEFAULT = 0;
     public static final int GUP_ALL_APPS = 1;
+    public static final int GUP_OFF = 2;
 
+    private final Context mContext;
     private final ContentResolver mContentResolver;
+    @VisibleForTesting
+    GameDriverContentObserver mGameDriverContentObserver;
+
+    private SwitchPreference mPreference;
 
     public GupEnableForAllAppsPreferenceController(Context context, String key) {
         super(context, key);
+        mContext = context;
         mContentResolver = context.getContentResolver();
+        mGameDriverContentObserver =
+                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
     }
 
     @Override
     public int getAvailabilityStatus() {
         return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)
+                        && (Settings.Global.getInt(
+                                    mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
+                                != GUP_OFF)
                 ? AVAILABLE
-                : DISABLED_DEPENDENT_SETTING;
+                : CONDITIONALLY_UNAVAILABLE;
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        final SwitchPreference switchPreference = screen.findPreference(getPreferenceKey());
-        if (switchPreference == null) {
-            return;
-        }
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
 
+    @Override
+    public void onStart() {
+        mGameDriverContentObserver.register(mContentResolver);
+    }
+
+    @Override
+    public void onStop() {
+        mGameDriverContentObserver.unregister(mContentResolver);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final SwitchPreference switchPreference = (SwitchPreference) preference;
+        switchPreference.setVisible(isAvailable());
         switchPreference.setChecked(Settings.Global.getInt(mContentResolver,
                                             Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
                 == GUP_ALL_APPS);
-        switchPreference.setOnPreferenceChangeListener(this);
     }
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        // When developer option is present, always overwrite GUP_DEV_ALL_APPS.
         Settings.Global.putInt(mContentResolver, Settings.Global.GUP_DEV_ALL_APPS,
                 (boolean) newValue ? GUP_ALL_APPS : GUP_DEFAULT);
 
         return true;
     }
+
+    @Override
+    public void onGameDriverContentChanged() {
+        updateState(mPreference);
+    }
 }
diff --git a/src/com/android/settings/development/gup/GupGlobalSwitchBarController.java b/src/com/android/settings/development/gup/GupGlobalSwitchBarController.java
new file mode 100644
index 0000000..c6bdf9d
--- /dev/null
+++ b/src/com/android/settings/development/gup/GupGlobalSwitchBarController.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019 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.development.gup;
+
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_ALL_APPS;
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_DEFAULT;
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_OFF;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.widget.SwitchWidgetController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
+
+/**
+ * Controller of global switch bar used to fully turn off Game Driver.
+ */
+public class GupGlobalSwitchBarController
+        implements SwitchWidgetController.OnSwitchChangeListener,
+                   GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
+                   OnStart, OnStop {
+    private final Context mContext;
+    private final ContentResolver mContentResolver;
+    @VisibleForTesting
+    SwitchWidgetController mSwitchWidgetController;
+    @VisibleForTesting
+    GameDriverContentObserver mGameDriverContentObserver;
+
+    GupGlobalSwitchBarController(Context context, SwitchWidgetController switchWidgetController) {
+        mContext = context;
+        mContentResolver = context.getContentResolver();
+        mGameDriverContentObserver =
+                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
+        mSwitchWidgetController = switchWidgetController;
+        mSwitchWidgetController.setEnabled(
+                DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context));
+        mSwitchWidgetController.setChecked(Settings.Global.getInt(mContentResolver,
+                                                   Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
+                != GUP_OFF);
+        mSwitchWidgetController.setListener(this);
+    }
+
+    @Override
+    public void onStart() {
+        mSwitchWidgetController.startListening();
+        mGameDriverContentObserver.register(mContentResolver);
+    }
+
+    @Override
+    public void onStop() {
+        mSwitchWidgetController.stopListening();
+        mGameDriverContentObserver.unregister(mContentResolver);
+    }
+
+    @Override
+    public boolean onSwitchToggled(boolean isChecked) {
+        if (!isChecked) {
+            Settings.Global.putInt(mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_OFF);
+            return true;
+        }
+
+        if (Settings.Global.getInt(mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
+                != GUP_ALL_APPS) {
+            Settings.Global.putInt(mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
+        }
+
+        return true;
+    }
+
+    @Override
+    public void onGameDriverContentChanged() {
+        mSwitchWidgetController.setChecked(Settings.Global.getInt(mContentResolver,
+                                                   Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
+                != GUP_OFF);
+    }
+}
diff --git a/src/com/android/settings/development/gup/GupPreferenceController.java b/src/com/android/settings/development/gup/GupPreferenceController.java
index d4cd2f1..615531b5 100644
--- a/src/com/android/settings/development/gup/GupPreferenceController.java
+++ b/src/com/android/settings/development/gup/GupPreferenceController.java
@@ -16,11 +16,16 @@
 
 package com.android.settings.development.gup;
 
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_DEFAULT;
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_OFF;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.os.Handler;
+import android.os.Looper;
 import android.provider.Settings;
 
 import androidx.annotation.VisibleForTesting;
@@ -31,6 +36,9 @@
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 
 import java.text.Collator;
@@ -42,21 +50,37 @@
 import java.util.List;
 import java.util.Set;
 
-public class GupPreferenceController
-        extends BasePreferenceController implements Preference.OnPreferenceChangeListener {
+/**
+ * Controller of all the per App based list preferences.
+ */
+public class GupPreferenceController extends BasePreferenceController
+        implements Preference.OnPreferenceChangeListener,
+                   GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
+                   OnStart, OnStop {
+    private final Context mContext;
+    private final ContentResolver mContentResolver;
     private final CharSequence[] mEntryList;
     private final String mPreferenceTitle;
     private final String mPreferenceDefault;
     private final String mPreferenceGup;
     private final String mPreferenceSystem;
+    @VisibleForTesting
+    GameDriverContentObserver mGameDriverContentObserver;
 
     private final List<AppInfo> mAppInfos;
     private final Set<String> mDevOptInApps;
     private final Set<String> mDevOptOutApps;
 
+    private PreferenceGroup mPreferenceGroup;
+
     public GupPreferenceController(Context context, String key) {
         super(context, key);
 
+        mContext = context;
+        mContentResolver = context.getContentResolver();
+        mGameDriverContentObserver =
+                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
+
         final Resources resources = context.getResources();
         mEntryList = resources.getStringArray(R.array.gup_app_preference_values);
         mPreferenceTitle = resources.getString(R.string.gup_app_preference_title);
@@ -68,36 +92,50 @@
         // Update the UI when all the app infos are ready.
         mAppInfos = getAppInfos(context);
 
-        final ContentResolver contentResolver = context.getContentResolver();
         mDevOptInApps =
-                getGlobalSettingsString(contentResolver, Settings.Global.GUP_DEV_OPT_IN_APPS);
+                getGlobalSettingsString(mContentResolver, Settings.Global.GUP_DEV_OPT_IN_APPS);
         mDevOptOutApps =
-                getGlobalSettingsString(contentResolver, Settings.Global.GUP_DEV_OPT_OUT_APPS);
+                getGlobalSettingsString(mContentResolver, Settings.Global.GUP_DEV_OPT_OUT_APPS);
     }
 
     @Override
     public int getAvailabilityStatus() {
         return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)
+                        && (Settings.Global.getInt(
+                                    mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
+                                != GUP_OFF)
                 ? AVAILABLE
-                : DISABLED_DEPENDENT_SETTING;
+                : CONDITIONALLY_UNAVAILABLE;
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        final PreferenceGroup preferenceGroup =
-                (PreferenceGroup) screen.findPreference(getPreferenceKey());
-        if (preferenceGroup == null) {
-            return;
-        }
+        mPreferenceGroup = (PreferenceGroup) screen.findPreference(getPreferenceKey());
 
+        final Context context = mPreferenceGroup.getContext();
         for (AppInfo appInfo : mAppInfos) {
-            preferenceGroup.addPreference(
-                    createListPreference(appInfo.info.packageName, appInfo.label));
+            mPreferenceGroup.addPreference(
+                    createListPreference(context, appInfo.info.packageName, appInfo.label));
         }
     }
 
     @Override
+    public void onStart() {
+        mGameDriverContentObserver.register(mContentResolver);
+    }
+
+    @Override
+    public void onStop() {
+        mGameDriverContentObserver.unregister(mContentResolver);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        preference.setVisible(isAvailable());
+    }
+
+    @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         final ListPreference listPref = (ListPreference) preference;
         final String value = newValue.toString();
@@ -120,14 +158,19 @@
 
         // Push the updated Sets for opt-in and opt-out apps to
         // corresponding Settings.Global.GUP_DEV_OPT_(IN|OUT)_APPS
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.GUP_DEV_OPT_IN_APPS, String.join(",", mDevOptInApps));
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.GUP_DEV_OPT_OUT_APPS, String.join(",", mDevOptOutApps));
+        Settings.Global.putString(mContentResolver, Settings.Global.GUP_DEV_OPT_IN_APPS,
+                String.join(",", mDevOptInApps));
+        Settings.Global.putString(mContentResolver, Settings.Global.GUP_DEV_OPT_OUT_APPS,
+                String.join(",", mDevOptOutApps));
 
         return true;
     }
 
+    @Override
+    public void onGameDriverContentChanged() {
+        updateState(mPreferenceGroup);
+    }
+
     // AppInfo class to achieve loading the application label only once
     class AppInfo {
         AppInfo(PackageManager packageManager, ApplicationInfo applicationInfo) {
@@ -176,8 +219,9 @@
     };
 
     @VisibleForTesting
-    protected ListPreference createListPreference(String packageName, String appName) {
-        final ListPreference listPreference = new ListPreference(mContext);
+    protected ListPreference createListPreference(
+            Context context, String packageName, String appName) {
+        final ListPreference listPreference = new ListPreference(context);
 
         listPreference.setKey(packageName);
         listPreference.setTitle(appName);
diff --git a/tests/robotests/src/com/android/settings/development/gup/GameDriverContentObserverTest.java b/tests/robotests/src/com/android/settings/development/gup/GameDriverContentObserverTest.java
new file mode 100644
index 0000000..6939ac9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/gup/GameDriverContentObserverTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019 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.development.gup;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class GameDriverContentObserverTest {
+    @Mock
+    private ContentResolver mResolver;
+    @Mock
+    private GameDriverContentObserver.OnGameDriverContentChangedListener mListener;
+
+    private GameDriverContentObserver mGameDriverContentObserver;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mGameDriverContentObserver = spy(new GameDriverContentObserver(null, null));
+    }
+
+    @Test
+    public void onChange_shouldCallListener() {
+        mGameDriverContentObserver.mListener = mListener;
+        mGameDriverContentObserver.onChange(true);
+
+        verify(mListener).onGameDriverContentChanged();
+    }
+
+    @Test
+    public void register_shouldRegisterContentObserver() {
+        mGameDriverContentObserver.register(mResolver);
+
+        verify(mResolver).registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.GUP_DEV_ALL_APPS), false,
+                mGameDriverContentObserver);
+    }
+
+    @Test
+    public void unregister_shouldUnregisterContentObserver() {
+        mGameDriverContentObserver.unregister(mResolver);
+
+        verify(mResolver).unregisterContentObserver(mGameDriverContentObserver);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/gup/GupEnableForAllAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/gup/GupEnableForAllAppsPreferenceControllerTest.java
index b7aadc3..2338e13 100644
--- a/tests/robotests/src/com/android/settings/development/gup/GupEnableForAllAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/gup/GupEnableForAllAppsPreferenceControllerTest.java
@@ -17,11 +17,13 @@
 package com.android.settings.development.gup;
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
 import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_ALL_APPS;
 import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_DEFAULT;
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_OFF;
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -46,6 +48,8 @@
     private PreferenceScreen mScreen;
     @Mock
     private SwitchPreference mPreference;
+    @Mock
+    private GameDriverContentObserver mGameDriverContentObserver;
 
     private Context mContext;
     private ContentResolver mResolver;
@@ -58,34 +62,86 @@
         mResolver = mContext.getContentResolver();
         mController = new GupEnableForAllAppsPreferenceController(mContext, "testKey");
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        mController.displayPreference(mScreen);
+
+        Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
     }
 
     @Test
-    public void getAvailability_developmentSettingsEnabled_available() {
-        Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+    public void getAvailability_developmentSettingsEnabledAndGupSettingsOn_available() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
 
     @Test
-    public void getAvailability_developmentSettingsDisabled_disabledDependentSetting() {
+    public void getAvailability_developmentSettingsDisabled_conditionallyUnavailable() {
         Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
 
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
+    public void getAvailability_gupSettingsOff_conditionallyUnavailable() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_OFF);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
     }
 
     @Test
     public void displayPreference_shouldAddSwitchPreference() {
         Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
-        mController.displayPreference(mScreen);
+        mController.updateState(mPreference);
 
         verify(mPreference).setChecked(false);
     }
 
     @Test
+    public void onStart_shouldRegister() {
+        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.onStart();
+
+        verify(mGameDriverContentObserver).register(mResolver);
+    }
+
+    @Test
+    public void onStop_shouldUnregister() {
+        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.onStop();
+
+        verify(mGameDriverContentObserver).unregister(mResolver);
+    }
+
+    @Test
+    public void updateState_availableAndGupDefault_visibleAndUncheck() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
+        mController.updateState(mPreference);
+
+        verify(mPreference, atLeastOnce()).setVisible(true);
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void updateState_availableAndGupAllApps_visibleAndCheck() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_ALL_APPS);
+        mController.updateState(mPreference);
+
+        verify(mPreference, atLeastOnce()).setVisible(true);
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_gupSettingsOff_notVisibleAndUncheck() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_OFF);
+        mController.updateState(mPreference);
+
+        verify(mPreference).setVisible(false);
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
     public void onPreferenceChange_check_shouldUpdateSettingsGlobal() {
         Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
-        mController.displayPreference(mScreen);
         mController.onPreferenceChange(mPreference, true);
 
         assertThat(Settings.Global.getInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT))
@@ -95,7 +151,6 @@
     @Test
     public void onPreferenceChange_uncheck_shouldUpdateSettingsGlobal() {
         Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_ALL_APPS);
-        mController.displayPreference(mScreen);
         mController.onPreferenceChange(mPreference, false);
 
         assertThat(Settings.Global.getInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT))
diff --git a/tests/robotests/src/com/android/settings/development/gup/GupGlobalSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/development/gup/GupGlobalSwitchBarControllerTest.java
new file mode 100644
index 0000000..8d76f3a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/gup/GupGlobalSwitchBarControllerTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2019 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.development.gup;
+
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_DEFAULT;
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_OFF;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.SwitchBarController;
+import com.android.settings.widget.SwitchWidgetController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class GupGlobalSwitchBarControllerTest {
+    @Mock
+    private SwitchBar mSwitchBar;
+    @Mock
+    private SwitchWidgetController mSwitchWidgetController;
+    @Mock
+    private GameDriverContentObserver mGameDriverContentObserver;
+
+    private Context mContext;
+    private ContentResolver mResolver;
+    private GupGlobalSwitchBarController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mResolver = mContext.getContentResolver();
+    }
+
+    @Test
+    public void constructor_gupOn_shouldCheckSwitchBar() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
+        mController =
+                new GupGlobalSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
+
+        verify(mSwitchBar).setChecked(true);
+    }
+
+    @Test
+    public void constructor_gupOff_shouldUncheckSwitchBar() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_OFF);
+        mController =
+                new GupGlobalSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
+
+        verify(mSwitchBar).setChecked(false);
+    }
+
+    @Test
+    public void constructor_developmentSettingsEnabled_shouldEnableSwitchBar() {
+        Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+        mController =
+                new GupGlobalSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
+
+        verify(mSwitchBar).setEnabled(true);
+    }
+
+    @Test
+    public void constructor_developmentSettingsDisabled_shouldDisableSwitchBar() {
+        Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
+        mController =
+                new GupGlobalSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
+
+        verify(mSwitchBar).setEnabled(false);
+    }
+
+    @Test
+    public void onStart_shouldStartListeningAndRegister() {
+        mController =
+                new GupGlobalSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
+        mController.mSwitchWidgetController = mSwitchWidgetController;
+        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.onStart();
+
+        verify(mSwitchWidgetController).startListening();
+        verify(mGameDriverContentObserver).register(mResolver);
+    }
+
+    @Test
+    public void onStop_shouldStopListeningAndUnregister() {
+        mController =
+                new GupGlobalSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
+        mController.mSwitchWidgetController = mSwitchWidgetController;
+        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.onStop();
+
+        verify(mSwitchWidgetController).stopListening();
+        verify(mGameDriverContentObserver).unregister(mResolver);
+    }
+
+    @Test
+    public void onSwitchToggled_checked_shouldTurnOnGup() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_OFF);
+        mController =
+                new GupGlobalSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
+        mController.onSwitchToggled(true);
+
+        assertThat(Settings.Global.getInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT))
+                .isEqualTo(GUP_DEFAULT);
+    }
+
+    @Test
+    public void onSwitchToggled_unchecked_shouldTurnOffGup() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
+        mController =
+                new GupGlobalSwitchBarController(mContext, new SwitchBarController(mSwitchBar));
+        mController.onSwitchToggled(false);
+
+        assertThat(Settings.Global.getInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT))
+                .isEqualTo(GUP_OFF);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/gup/GupPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/gup/GupPreferenceControllerTest.java
index d5e7a85..7674496 100644
--- a/tests/robotests/src/com/android/settings/development/gup/GupPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/gup/GupPreferenceControllerTest.java
@@ -17,11 +17,14 @@
 package com.android.settings.development.gup;
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_DEFAULT;
+import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_OFF;
 import static com.android.settings.testutils.ApplicationTestUtils.buildInfo;
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.ContentResolver;
@@ -65,6 +68,8 @@
     private PackageManager mPackageManager;
     @Mock
     private PreferenceScreen mScreen;
+    @Mock
+    private GameDriverContentObserver mGameDriverContentObserver;
 
     private Context mContext;
     private PreferenceGroup mGroup;
@@ -84,19 +89,28 @@
     }
 
     @Test
-    public void getAvailability_developmentSettingsEnabled_available() {
+    public void getAvailability_developmentSettingsEnabledAndGupSettingsOn_available() {
         loadDefaultConfig();
         Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
 
     @Test
-    public void getAvailability_developmentSettingsDisabled_disabledDependentSetting() {
+    public void getAvailability_developmentSettingsDisabled_conditionallyUnavailable() {
         loadDefaultConfig();
         Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
 
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
+    public void getAvailability_gupSettingsOff_conditionallyUnavailable() {
+        loadDefaultConfig();
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_OFF);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
     }
 
     @Test
@@ -111,10 +125,45 @@
     }
 
     @Test
+    public void onStart_shouldRegister() {
+        loadDefaultConfig();
+        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.onStart();
+
+        verify(mGameDriverContentObserver).register(mResolver);
+    }
+
+    @Test
+    public void onStop_shouldUnregister() {
+        loadDefaultConfig();
+        mController.mGameDriverContentObserver = mGameDriverContentObserver;
+        mController.onStop();
+
+        verify(mGameDriverContentObserver).unregister(mResolver);
+    }
+
+    @Test
+    public void updateState_available_visible() {
+        Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
+        loadDefaultConfig();
+
+        assertThat(mGroup.isVisible()).isTrue();
+    }
+
+    @Test
+    public void updateState_gupSettingsOff_notVisible() {
+        Settings.Global.putInt(mResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_OFF);
+        loadDefaultConfig();
+
+        assertThat(mGroup.isVisible()).isFalse();
+    }
+
+    @Test
     public void createPreference_configDefault_shouldSetDefaultAttributes() {
         loadDefaultConfig();
         final ListPreference preference =
-                mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
+                mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME);
 
         assertThat(preference.getKey()).isEqualTo(TEST_PKG_NAME);
         assertThat(preference.getTitle()).isEqualTo(TEST_APP_NAME);
@@ -130,7 +179,7 @@
     public void createPreference_configGup_shouldSetGupAttributes() {
         loadConfig(TEST_PKG_NAME, "");
         final ListPreference preference =
-                mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
+                mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME);
 
         assertThat(preference.getKey()).isEqualTo(TEST_PKG_NAME);
         assertThat(preference.getTitle()).isEqualTo(TEST_APP_NAME);
@@ -146,7 +195,7 @@
     public void createPreference_configSystem_shouldSetSystemAttributes() {
         loadConfig("", TEST_PKG_NAME);
         final ListPreference preference =
-                mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
+                mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME);
 
         assertThat(preference.getKey()).isEqualTo(TEST_PKG_NAME);
         assertThat(preference.getTitle()).isEqualTo(TEST_APP_NAME);
@@ -162,7 +211,7 @@
     public void onPreferenceChange_selectDefault_shouldUpdateAttributesAndSettingsGlobal() {
         loadDefaultConfig();
         final ListPreference preference =
-                mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
+                mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME);
         mController.onPreferenceChange(preference, mValueList[DEFAULT]);
 
         assertThat(preference.getEntry()).isEqualTo(mValueList[DEFAULT]);
@@ -178,7 +227,7 @@
     public void onPreferenceChange_selectGup_shouldUpdateAttributesAndSettingsGlobal() {
         loadDefaultConfig();
         final ListPreference preference =
-                mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
+                mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME);
         mController.onPreferenceChange(preference, mValueList[GUP]);
 
         assertThat(preference.getEntry()).isEqualTo(mValueList[GUP]);
@@ -194,7 +243,7 @@
     public void onPreferenceChange_selectSystem_shouldUpdateAttributesAndSettingsGlobal() {
         loadDefaultConfig();
         final ListPreference preference =
-                mController.createListPreference(TEST_PKG_NAME, TEST_APP_NAME);
+                mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME);
         mController.onPreferenceChange(preference, mValueList[SYSTEM]);
 
         assertThat(preference.getEntry()).isEqualTo(mValueList[SYSTEM]);
@@ -230,6 +279,7 @@
         mController = new GupPreferenceController(mContext, "testKey");
         mGroup = spy(new PreferenceCategory(mContext));
         final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        when(mGroup.getContext()).thenReturn(mContext);
         when(mGroup.getPreferenceManager()).thenReturn(preferenceManager);
         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mGroup);
         mController.displayPreference(mScreen);