Merge "Fix logic error / possible NPE in AuthenticationSidecar"
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index dec5482..a49cfff 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -467,6 +467,11 @@
             android:title="@string/force_resizable_activities"
             android:summary="@string/force_resizable_activities_summary"/>
 
+        <SwitchPreference
+                android:key="enable_freeform_support"
+                android:title="@string/enable_freeform_support"
+                android:summary="@string/enable_freeform_support_summary"/>
+
         <Preference
             android:key="reset_shortcut_manager_throttling"
             android:title="@string/reset_shortcut_manager_throttling" />
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 2f44d3e..ccd91fd 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -982,11 +982,9 @@
             } else {
                 mMetricsFeatureProvider.action(
                         getActivity(),
-                        mAppEntry.info.enabled
-                                ? MetricsEvent.ACTION_SETTINGS_DISABLE_APP
-                                : MetricsEvent.ACTION_SETTINGS_ENABLE_APP);
+                        MetricsEvent.ACTION_SETTINGS_ENABLE_APP);
                 new DisableChanger(this, mAppEntry.info,
-                        PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
+                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
                         .execute((Object) null);
             }
         } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
diff --git a/src/com/android/settings/applications/UsageAccessDetails.java b/src/com/android/settings/applications/UsageAccessDetails.java
index 253ddfd..c10fb55 100644
--- a/src/com/android/settings/applications/UsageAccessDetails.java
+++ b/src/com/android/settings/applications/UsageAccessDetails.java
@@ -137,9 +137,13 @@
 
     @Override
     protected boolean refreshUi() {
-        if (mPackageInfo == null) {
+        retrieveAppEntry();
+        if (mAppEntry == null) {
             return false;
         }
+        if (mPackageInfo == null) {
+            return false; // onCreate must have failed, make sure to exit
+        }
         mUsageState = mUsageBridge.getUsageInfo(mPackageName,
                 mPackageInfo.applicationInfo.uid);
 
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index 600b23b..9c61873 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -601,6 +601,9 @@
         }
 
         public Drawable getIcon(Icon icon) {
+            if (icon == null) {
+                return null;
+            }
             Drawable drawable = mMap.get(icon);
             if (drawable == null) {
                 drawable = icon.loadDrawable(mContext);
diff --git a/src/com/android/settings/dashboard/suggestions/EventStore.java b/src/com/android/settings/dashboard/suggestions/EventStore.java
index 43ed65b..cc3872e 100644
--- a/src/com/android/settings/dashboard/suggestions/EventStore.java
+++ b/src/com/android/settings/dashboard/suggestions/EventStore.java
@@ -82,7 +82,7 @@
     }
 
     private void writePref(String prefKey, long value) {
-        mSharedPrefs.edit().putLong(prefKey, value).commit();
+        mSharedPrefs.edit().putLong(prefKey, value).apply();
     }
 
     private long readPref(String prefKey, Long defaultValue) {
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java
index 38b9d28..de266e1 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java
@@ -96,8 +96,7 @@
         //                  itemView));
         //        } else
         {
-            // TODO: Add icon field in Suggestion, and enable this.
-            //            holder.icon.setImageDrawable(mCache.getIcon(suggestion.icon));
+            holder.icon.setImageDrawable(mCache.getIcon(suggestion.getIcon()));
             holder.title.setText(suggestion.getTitle());
             final CharSequence summary = suggestion.getSummary();
             if (!TextUtils.isEmpty(summary)) {
diff --git a/src/com/android/settings/development/AdbClearKeysDialogHost.java b/src/com/android/settings/development/AdbClearKeysDialogHost.java
new file mode 100644
index 0000000..7f69f76
--- /dev/null
+++ b/src/com/android/settings/development/AdbClearKeysDialogHost.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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;
+
+/**
+ * Interface for AdbClearKeysDialogFragment callbacks.
+ */
+public interface AdbClearKeysDialogHost {
+
+    /**
+     * Called when the user presses ok on the warning dialog.
+     */
+    void onAdbClearKeysDialogConfirmed();
+}
diff --git a/src/com/android/settings/development/AllowAppsOnExternalPreferenceController.java b/src/com/android/settings/development/AllowAppsOnExternalPreferenceController.java
new file mode 100644
index 0000000..fb69455
--- /dev/null
+++ b/src/com/android/settings/development/AllowAppsOnExternalPreferenceController.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+public class AllowAppsOnExternalPreferenceController extends
+        DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener {
+
+    private static final String FORCE_ALLOW_ON_EXTERNAL_KEY = "force_allow_on_external";
+
+    @VisibleForTesting
+    static final int SETTING_VALUE_OFF = 0;
+    @VisibleForTesting
+    static final int SETTING_VALUE_ON = 1;
+
+    private SwitchPreference mPreference;
+
+    public AllowAppsOnExternalPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return FORCE_ALLOW_ON_EXTERNAL_KEY;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+
+        mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean isEnabled = (Boolean) newValue;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
+                isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.FORCE_ALLOW_ON_EXTERNAL, SETTING_VALUE_OFF);
+
+        mPreference.setChecked(mode != SETTING_VALUE_OFF);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchEnabled() {
+        mPreference.setEnabled(true);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.FORCE_ALLOW_ON_EXTERNAL, SETTING_VALUE_OFF);
+        mPreference.setEnabled(false);
+        mPreference.setChecked(false);
+    }
+}
diff --git a/src/com/android/settings/development/BugReportInPowerPreferenceController.java b/src/com/android/settings/development/BugReportInPowerPreferenceController.java
index 4032826..2c448f5 100644
--- a/src/com/android/settings/development/BugReportInPowerPreferenceController.java
+++ b/src/com/android/settings/development/BugReportInPowerPreferenceController.java
@@ -28,6 +28,10 @@
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.core.AbstractPreferenceController;
 
+/**
+ * deprecated in favor of {@link BugReportInPowerPreferenceControllerV2}
+ */
+@Deprecated
 public class BugReportInPowerPreferenceController extends AbstractPreferenceController
         implements PreferenceControllerMixin {
 
@@ -46,8 +50,8 @@
         if (KEY_BUGREPORT_IN_POWER.equals(preference.getKey())) {
             final SwitchPreference switchPreference = (SwitchPreference) preference;
             Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Global.BUGREPORT_IN_POWER_MENU,
-                switchPreference.isChecked() ? 1 : 0);
+                    Settings.Global.BUGREPORT_IN_POWER_MENU,
+                    switchPreference.isChecked() ? 1 : 0);
             setBugreportStorageProviderStatus();
             return true;
         }
@@ -95,7 +99,7 @@
             return false;
         }
         final boolean enabled = Settings.Secure.getInt(
-            mContext.getContentResolver(), Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0;
+                mContext.getContentResolver(), Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0;
         mPreference.setChecked(enabled);
         return enabled;
     }
@@ -110,12 +114,12 @@
 
     private void setBugreportStorageProviderStatus() {
         final ComponentName componentName = new ComponentName("com.android.shell",
-            "com.android.shell.BugreportStorageProvider");
+                "com.android.shell.BugreportStorageProvider");
         final boolean enabled = mPreference.isChecked();
         mContext.getPackageManager().setComponentEnabledSetting(componentName,
-            enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-                : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
-            0);
+                enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                        : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
+                0);
     }
 
 }
diff --git a/src/com/android/settings/development/BugReportInPowerPreferenceControllerV2.java b/src/com/android/settings/development/BugReportInPowerPreferenceControllerV2.java
new file mode 100644
index 0000000..34a95a6
--- /dev/null
+++ b/src/com/android/settings/development/BugReportInPowerPreferenceControllerV2.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settingslib.wrapper.PackageManagerWrapper;
+
+public class BugReportInPowerPreferenceControllerV2 extends
+        DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener {
+
+    private static final String KEY_BUGREPORT_IN_POWER = "bugreport_in_power";
+
+    @VisibleForTesting
+    static final ComponentName COMPONENT_NAME = new ComponentName("com.android.shell",
+            "com.android.shell.BugreportStorageProvider");
+    @VisibleForTesting
+    static int SETTING_VALUE_ON = 1;
+    @VisibleForTesting
+    static int SETTING_VALUE_OFF = 0;
+
+    private final PackageManagerWrapper mPackageManager;
+    private final UserManager mUserManager;
+    private SwitchPreference mPreference;
+
+    public BugReportInPowerPreferenceControllerV2(Context context) {
+        super(context);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mPackageManager = new PackageManagerWrapper(context.getPackageManager());
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return !mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_BUGREPORT_IN_POWER;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+
+        mPreference = (SwitchPreference) screen.findPreference(KEY_BUGREPORT_IN_POWER);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean isEnabled = (Boolean) newValue;
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU,
+                isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
+        setBugreportStorageProviderStatus(isEnabled);
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final int mode = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU, SETTING_VALUE_OFF);
+        mPreference.setChecked(mode != SETTING_VALUE_OFF);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchEnabled() {
+        // no-op because this preference can never be disabled
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU, SETTING_VALUE_OFF);
+        setBugreportStorageProviderStatus(false);
+        mPreference.setChecked(false);
+    }
+
+    private void setBugreportStorageProviderStatus(boolean isEnabled) {
+        mPackageManager.setComponentEnabledSetting(COMPONENT_NAME,
+                isEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                        : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
+    }
+}
diff --git a/src/com/android/settings/development/ClearAdbKeysPreferenceController.java b/src/com/android/settings/development/ClearAdbKeysPreferenceController.java
new file mode 100644
index 0000000..9c93280
--- /dev/null
+++ b/src/com/android/settings/development/ClearAdbKeysPreferenceController.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.Context;
+import android.hardware.usb.IUsbManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.util.Log;
+
+public class ClearAdbKeysPreferenceController extends DeveloperOptionsPreferenceController {
+
+    private static final String TAG = "ClearAdbPrefCtrl";
+    private static final String CLEAR_ADB_KEYS = "clear_adb_keys";
+
+    @VisibleForTesting
+    static final String RO_ADB_SECURE_PROPERTY_KEY = "ro.adb.secure";
+
+    private final IUsbManager mUsbManager;
+    private final DevelopmentSettingsDashboardFragment mFragment;
+
+    private Preference mPreference;
+
+    public ClearAdbKeysPreferenceController(Context context,
+            DevelopmentSettingsDashboardFragment fragment) {
+        super(context);
+
+        mFragment = fragment;
+        mUsbManager = IUsbManager.Stub.asInterface(ServiceManager.getService(Context.USB_SERVICE));
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return SystemProperties.getBoolean(RO_ADB_SECURE_PROPERTY_KEY, false /* default */);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return CLEAR_ADB_KEYS;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+
+        mPreference = screen.findPreference(getPreferenceKey());
+        if (mPreference != null && !isAdminUser()) {
+            mPreference.setEnabled(false);
+        }
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            ClearAdbKeysWarningDialog.show(mFragment);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchEnabled() {
+        if (isAdminUser()) {
+            mPreference.setEnabled(true);
+        }
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        mPreference.setEnabled(false);
+    }
+
+    public void onClearAdbKeysConfirmed() {
+        try {
+            mUsbManager.clearUsbDebuggingKeys();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to clear adb keys", e);
+        }
+    }
+
+    @VisibleForTesting
+    boolean isAdminUser() {
+        return ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).isAdminUser();
+    }
+}
diff --git a/src/com/android/settings/development/ClearAdbKeysWarningDialog.java b/src/com/android/settings/development/ClearAdbKeysWarningDialog.java
new file mode 100644
index 0000000..61b55a0
--- /dev/null
+++ b/src/com/android/settings/development/ClearAdbKeysWarningDialog.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class ClearAdbKeysWarningDialog extends InstrumentedDialogFragment implements
+        DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+
+    public static final String TAG = "ClearAdbKeysDlg";
+
+    public static void show(Fragment host) {
+        final FragmentManager manager = host.getActivity().getFragmentManager();
+        if (manager.findFragmentByTag(TAG) == null) {
+            final ClearAdbKeysWarningDialog dialog =
+                    new ClearAdbKeysWarningDialog();
+            dialog.setTargetFragment(host, 0 /* requestCode */);
+            dialog.show(manager, TAG);
+        }
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.DIALOG_CLEAR_ADB_KEYS;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        return new AlertDialog.Builder(getActivity())
+                .setMessage(R.string.adb_keys_warning_message)
+                .setPositiveButton(android.R.string.ok, this /* onClickListener */)
+                .setNegativeButton(android.R.string.cancel, null /* onClickListener */)
+                .create();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        final AdbClearKeysDialogHost host = (AdbClearKeysDialogHost) getTargetFragment();
+        if (host == null) {
+            return;
+        }
+        host.onAdbClearKeysDialogConfirmed();
+    }
+}
diff --git a/src/com/android/settings/development/DevelopmentSettings.java b/src/com/android/settings/development/DevelopmentSettings.java
index bd3f33b..980d976 100644
--- a/src/com/android/settings/development/DevelopmentSettings.java
+++ b/src/com/android/settings/development/DevelopmentSettings.java
@@ -167,6 +167,7 @@
     private static final String TETHERING_HARDWARE_OFFLOAD = "tethering_hardware_offload";
     private static final String KEY_COLOR_MODE = "picture_color_mode";
     private static final String FORCE_RESIZABLE_KEY = "force_resizable_activities";
+    private static final String ENABLE_FREEFORM_SUPPORT_KEY = "enable_freeform_support";
     private static final String COLOR_TEMPERATURE_KEY = "color_temperature";
 
     private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_KEY =
@@ -312,6 +313,8 @@
 
     private SwitchPreference mForceResizable;
 
+    private SwitchPreference mEnableFreeformSupport;
+
     private SwitchPreference mColorTemperaturePreference;
 
     private final ArrayList<Preference> mAllPrefs = new ArrayList<>();
@@ -495,6 +498,8 @@
         mSimulateColorSpace = addListPreference(SIMULATE_COLOR_SPACE);
         mUSBAudio = findAndInitSwitchPref(USB_AUDIO_KEY);
         mForceResizable = findAndInitSwitchPref(FORCE_RESIZABLE_KEY);
+        mEnableFreeformSupport = findAndInitSwitchPref(ENABLE_FREEFORM_SUPPORT_KEY);
+        removePreferenceForProduction(mEnableFreeformSupport);
 
         mImmediatelyDestroyActivities = (SwitchPreference) findPreference(
                 IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
@@ -612,7 +617,16 @@
     }
 
     private void removePreference(Preference preference) {
-        getPreferenceScreen().removePreference(preference);
+        if (preference == null) {
+            return;
+        }
+
+        final PreferenceGroup parent = preference.getParent();
+
+        if (parent != null) {
+            parent.removePreference(preference);
+        }
+
         mAllPrefs.remove(preference);
         mResetSwitchPrefs.remove(preference);
     }
@@ -823,6 +837,7 @@
         updateSimulateColorSpace();
         updateUSBAudioOptions();
         updateForceResizableOptions();
+        updateEnableFreeformWindowsSupportOptions();
         Preference webViewAppPref = findPreference(mWebViewAppPrefController.getPreferenceKey());
         mWebViewAppPrefController.updateState(webViewAppPref);
         updateOemUnlockOptions();
@@ -1421,6 +1436,17 @@
                 mForceResizable.isChecked() ? 1 : 0);
     }
 
+    private void updateEnableFreeformWindowsSupportOptions() {
+        updateSwitchPreference(mEnableFreeformSupport, Settings.Global.getInt(getContentResolver(),
+                Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0);
+    }
+
+    private void writeEnableFreeformWindowsSupportOptions() {
+        Settings.Global.putInt(getContentResolver(),
+                Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT,
+                mEnableFreeformSupport.isChecked() ? 1 : 0);
+    }
+
     private void updateForceRtlOptions() {
         updateSwitchPreference(mForceRtlLayout,
                 Settings.Global.getInt(getActivity().getContentResolver(),
@@ -2329,6 +2355,8 @@
             writeUSBAudioOptions();
         } else if (preference == mForceResizable) {
             writeForceResizableOptions();
+        } else if (preference == mEnableFreeformSupport){
+            writeEnableFreeformWindowsSupportOptions();
         } else if (preference == mBluetoothShowDevicesWithoutNames) {
             writeBluetoothShowDevicesWithoutUserFriendlyNameOptions();
         } else if (preference == mBluetoothDisableAbsVolume) {
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 96bd4c1..2d9c5f3 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -50,7 +50,8 @@
 import java.util.List;
 
 public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment
-        implements SwitchBar.OnSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost {
+        implements SwitchBar.OnSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost,
+        AdbClearKeysDialogHost {
 
     private static final String TAG = "DevSettingsDashboard";
 
@@ -171,6 +172,13 @@
     }
 
     @Override
+    public void onAdbClearKeysDialogConfirmed() {
+        final ClearAdbKeysPreferenceController controller = getDevelopmentOptionsController(
+                ClearAdbKeysPreferenceController.class);
+        controller.onClearAdbKeysConfirmed();
+    }
+
+    @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         boolean handledResult = false;
         for (AbstractPreferenceController controller : mPreferenceControllers) {
@@ -238,7 +246,7 @@
             Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         // take bug report
-        // desktop backup password
+        controllers.add(new LocalBackupPasswordPreferenceController(context));
         controllers.add(new StayAwakePreferenceController(context, lifecycle));
         // hdcp checking
         controllers.add(new BluetoothSnoopLogPreferenceController(context));
@@ -246,20 +254,20 @@
         // running services
         // convert to file encryption
         controllers.add(new PictureColorModePreferenceController(context, lifecycle));
-        // webview implementation
+        controllers.add(new WebViewAppPreferenceControllerV2(context));
         controllers.add(new CoolColorTemperaturePreferenceController(context));
         controllers.add(new DisableAutomaticUpdatesPreferenceController(context));
         // system ui demo mode
         // quick settings developer tiles
         controllers.add(new AdbPreferenceController(context, fragment));
-        // revoke usb debugging authorizations
+        controllers.add(new ClearAdbKeysPreferenceController(context, fragment));
         controllers.add(new LocalTerminalPreferenceController(context));
-        // bug report shortcut
+        controllers.add(new BugReportInPowerPreferenceControllerV2(context));
         // select mock location app
         controllers.add(new DebugViewAttributesPreferenceController(context));
         controllers.add(new SelectDebugAppPreferenceController(context, fragment));
         controllers.add(new WaitForDebuggerPreferenceController(context));
-        // verify apps over usb
+        controllers.add(new VerifyAppsOverUsbPreferenceControllerV2(context));
         // logger buffer sizes
         // store logger data persistently on device
         controllers.add(new ConnectivityMonitorPreferenceControllerV2(context));
@@ -308,10 +316,10 @@
         // background process limit
         // background check
         controllers.add(new AppsNotRespondingPreferenceController(context));
-        // show notification channel warnings
+        controllers.add(new NotificationChannelWarningsPreferenceController(context));
         // inactive apps
-        // force allow apps on external
-        // force activities to be resizable
+        controllers.add(new AllowAppsOnExternalPreferenceController(context));
+        controllers.add(new ResizableActivityPreferenceController(context));
         // reset shortcutmanager rate-limiting
         return controllers;
     }
diff --git a/src/com/android/settings/development/LocalBackupPasswordPreferenceController.java b/src/com/android/settings/development/LocalBackupPasswordPreferenceController.java
new file mode 100644
index 0000000..b509448
--- /dev/null
+++ b/src/com/android/settings/development/LocalBackupPasswordPreferenceController.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.app.backup.IBackupManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+
+public class LocalBackupPasswordPreferenceController extends DeveloperOptionsPreferenceController {
+
+    private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
+
+    private final UserManager mUserManager;
+    private final IBackupManager mBackupManager;
+
+    public LocalBackupPasswordPreferenceController(Context context) {
+        super(context);
+
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mBackupManager = IBackupManager.Stub.asInterface(
+                ServiceManager.getService(Context.BACKUP_SERVICE));
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return LOCAL_BACKUP_PASSWORD;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        updatePasswordSummary(preference);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchEnabled() {
+        // intentional no-op
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        // intentional no-op
+    }
+
+    private void updatePasswordSummary(Preference preference) {
+        preference.setEnabled(isAdminUser() && mBackupManager != null);
+        if (mBackupManager == null) {
+            return;
+        }
+        try {
+            if (mBackupManager.hasBackupPassword()) {
+                preference.setSummary(R.string.local_backup_password_summary_change);
+            } else {
+                preference.setSummary(R.string.local_backup_password_summary_none);
+            }
+        } catch (RemoteException e) {
+            // Not much we can do here
+        }
+    }
+
+    @VisibleForTesting
+    boolean isAdminUser() {
+        return mUserManager.isAdminUser();
+    }
+}
diff --git a/src/com/android/settings/development/NotificationChannelWarningsPreferenceController.java b/src/com/android/settings/development/NotificationChannelWarningsPreferenceController.java
new file mode 100644
index 0000000..c0382f2
--- /dev/null
+++ b/src/com/android/settings/development/NotificationChannelWarningsPreferenceController.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.Context;
+import android.os.Build;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+public class NotificationChannelWarningsPreferenceController extends
+        DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener {
+
+    private static final String SHOW_NOTIFICATION_CHANNEL_WARNINGS_KEY =
+            "show_notification_channel_warnings";
+
+    private SwitchPreference mPreference;
+
+    @VisibleForTesting
+    final static int SETTING_VALUE_ON = 1;
+    @VisibleForTesting
+    final static int SETTING_VALUE_OFF = 0;
+    @VisibleForTesting
+    final static int DEBUGGING_ENABLED = 1;
+    @VisibleForTesting
+    final static int DEBUGGING_DISABLED = 0;
+
+    public NotificationChannelWarningsPreferenceController(Context context) {
+        super(context);
+    }
+
+
+    @Override
+    public String getPreferenceKey() {
+        return SHOW_NOTIFICATION_CHANNEL_WARNINGS_KEY;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+
+        mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean isEnabled = (Boolean) newValue;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
+                isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final int defaultWarningEnabled = isDebuggable() ? DEBUGGING_ENABLED : DEBUGGING_DISABLED;
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled);
+        mPreference.setChecked(mode != SETTING_VALUE_OFF);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchEnabled() {
+        mPreference.setEnabled(true);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, SETTING_VALUE_OFF);
+        mPreference.setEnabled(false);
+        mPreference.setChecked(false);
+    }
+
+    @VisibleForTesting
+    boolean isDebuggable() {
+        return Build.IS_DEBUGGABLE;
+    }
+}
diff --git a/src/com/android/settings/development/ResizableActivityPreferenceController.java b/src/com/android/settings/development/ResizableActivityPreferenceController.java
new file mode 100644
index 0000000..70be4b6
--- /dev/null
+++ b/src/com/android/settings/development/ResizableActivityPreferenceController.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+public class ResizableActivityPreferenceController extends
+        DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener {
+
+    private static final String FORCE_RESIZABLE_KEY = "force_resizable_activities";
+
+    @VisibleForTesting
+    final static int SETTING_VALUE_ON = 1;
+    @VisibleForTesting
+    final static int SETTING_VALUE_OFF = 0;
+
+    private SwitchPreference mPreference;
+
+    public ResizableActivityPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return FORCE_RESIZABLE_KEY;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+
+        mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean isEnabled = (Boolean) newValue;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
+                isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, SETTING_VALUE_OFF);
+        mPreference.setChecked(mode != SETTING_VALUE_OFF);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchEnabled() {
+        mPreference.setEnabled(true);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, SETTING_VALUE_OFF);
+        mPreference.setChecked(false);
+        mPreference.setEnabled(false);
+    }
+}
diff --git a/src/com/android/settings/development/VerifyAppsOverUsbPreferenceController.java b/src/com/android/settings/development/VerifyAppsOverUsbPreferenceController.java
index d7891c7..4fd7fbc 100644
--- a/src/com/android/settings/development/VerifyAppsOverUsbPreferenceController.java
+++ b/src/com/android/settings/development/VerifyAppsOverUsbPreferenceController.java
@@ -37,7 +37,10 @@
 
 /**
  * Controller to manage the state of "Verify apps over USB" toggle.
+ *
+ * deprecated in favor of {@link VerifyAppsOverUsbPreferenceControllerV2}
  */
+@Deprecated
 public class VerifyAppsOverUsbPreferenceController extends AbstractPreferenceController implements
         PreferenceControllerMixin {
     private static final String VERIFY_APPS_OVER_USB_KEY = "verify_apps_over_usb";
diff --git a/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerV2.java b/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerV2.java
new file mode 100644
index 0000000..76c8669
--- /dev/null
+++ b/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerV2.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.wrapper.PackageManagerWrapper;
+
+import java.util.List;
+
+/**
+ * Controller to manage the state of "Verify apps over USB" toggle.
+ */
+public class VerifyAppsOverUsbPreferenceControllerV2 extends
+        DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
+        AdbOnChangeListener {
+    private static final String VERIFY_APPS_OVER_USB_KEY = "verify_apps_over_usb";
+    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+
+    private RestrictedSwitchPreference mPreference;
+
+    @VisibleForTesting
+    static final int SETTING_VALUE_ON = 1;
+    @VisibleForTesting
+    static final int SETTING_VALUE_OFF = 0;
+
+    /**
+     * Class for indirection of RestrictedLockUtils for testing purposes. It would be nice to mock
+     * the appropriate methods in UserManager instead but they aren't accessible.
+     */
+    @VisibleForTesting
+    class RestrictedLockUtilsDelegate {
+        public EnforcedAdmin checkIfRestrictionEnforced(
+                Context context, String userRestriction, int userId) {
+            return RestrictedLockUtils.checkIfRestrictionEnforced(context, userRestriction, userId);
+        }
+    }
+
+    // NB: This field is accessed using reflection in the test, please keep name in sync.
+    private final RestrictedLockUtilsDelegate mRestrictedLockUtils =
+            new RestrictedLockUtilsDelegate();
+
+    // This field is accessed using reflection in the test, please keep name in sync.
+    private final PackageManagerWrapper mPackageManager;
+
+    public VerifyAppsOverUsbPreferenceControllerV2(Context context) {
+        super(context);
+
+        mPackageManager = new PackageManagerWrapper(context.getPackageManager());
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1 /* default */) > 0;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return VERIFY_APPS_OVER_USB_KEY;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = (RestrictedSwitchPreference) screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean isEnabled = (Boolean) newValue;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
+                isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        if (!shouldBeEnabled()) {
+            mPreference.setChecked(false);
+            mPreference.setDisabledByAdmin(null);
+            mPreference.setEnabled(false);
+            return;
+        }
+
+        final EnforcedAdmin enforcingAdmin = mRestrictedLockUtils.checkIfRestrictionEnforced(
+                mContext, UserManager.ENSURE_VERIFY_APPS, UserHandle.myUserId());
+        if (enforcingAdmin != null) {
+            mPreference.setChecked(true);
+            mPreference.setDisabledByAdmin(enforcingAdmin);
+            return;
+        }
+
+        mPreference.setEnabled(true);
+        final boolean checked = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, SETTING_VALUE_ON)
+                != SETTING_VALUE_OFF;
+        mPreference.setChecked(checked);
+    }
+
+    @Override
+    public void onAdbSettingChanged() {
+        if (isAvailable()) {
+            updateState(mPreference);
+        }
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchEnabled() {
+        updateState(mPreference);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        // intentional no-op
+        // We can rely on onAdbSettingChanged() to update this controller.
+    }
+
+    /**
+     * Checks whether the toggle should be enabled depending on whether verify apps over USB is
+     * possible currently. If ADB is disabled or if package verifier does not exist, the toggle
+     * should be disabled.
+     */
+    private boolean shouldBeEnabled() {
+        final ContentResolver cr = mContext.getContentResolver();
+        if (Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED,
+                AdbPreferenceController.ADB_SETTING_OFF)
+                == AdbPreferenceController.ADB_SETTING_OFF) {
+            return false;
+        }
+        if (Settings.Global.getInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, SETTING_VALUE_ON)
+                == SETTING_VALUE_OFF) {
+            return false;
+        } else {
+            final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+            verification.setType(PACKAGE_MIME_TYPE);
+            verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            final List<ResolveInfo> receivers = mPackageManager.queryBroadcastReceivers(
+                    verification, 0 /* flags */);
+            if (receivers.size() == 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/settings/development/WebViewAppPreferenceControllerV2.java b/src/com/android/settings/development/WebViewAppPreferenceControllerV2.java
new file mode 100644
index 0000000..61a98aa
--- /dev/null
+++ b/src/com/android/settings/development/WebViewAppPreferenceControllerV2.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.applications.defaultapps.DefaultAppInfo;
+import com.android.settings.webview.WebViewUpdateServiceWrapper;
+import com.android.settingslib.wrapper.PackageManagerWrapper;
+
+public class WebViewAppPreferenceControllerV2 extends DeveloperOptionsPreferenceController {
+
+    private static final String TAG = "WebViewAppPrefCtrl";
+    private static final String WEBVIEW_APP_KEY = "select_webview_provider";
+
+    private final PackageManagerWrapper mPackageManager;
+    private final WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
+
+    private Preference mPreference;
+
+    public WebViewAppPreferenceControllerV2(Context context) {
+        super(context);
+
+        mPackageManager = new PackageManagerWrapper(context.getPackageManager());
+        mWebViewUpdateServiceWrapper = new WebViewUpdateServiceWrapper();
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return WEBVIEW_APP_KEY;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final CharSequence defaultAppLabel = getDefaultAppLabel();
+        if (!TextUtils.isEmpty(defaultAppLabel)) {
+            mPreference.setSummary(defaultAppLabel);
+            mPreference.setIcon(getDefaultAppIcon());
+        } else {
+            Log.d(TAG, "No default app");
+            mPreference.setSummary(R.string.app_list_preference_none);
+            mPreference.setIcon(null);
+        }
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchEnabled() {
+        mPreference.setEnabled(true);
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        mPreference.setEnabled(false);
+    }
+
+    @VisibleForTesting
+    DefaultAppInfo getDefaultAppInfo() {
+        final PackageInfo currentPackage = mWebViewUpdateServiceWrapper.getCurrentWebViewPackage();
+        return new DefaultAppInfo(mPackageManager,
+                currentPackage == null ? null : currentPackage.applicationInfo);
+    }
+
+    private Drawable getDefaultAppIcon() {
+        final DefaultAppInfo app = getDefaultAppInfo();
+        return app.loadIcon();
+    }
+
+    private CharSequence getDefaultAppLabel() {
+        final DefaultAppInfo app = getDefaultAppInfo();
+        return app.loadLabel();
+    }
+}
diff --git a/src/com/android/settings/webview/WebViewAppPreferenceController.java b/src/com/android/settings/webview/WebViewAppPreferenceController.java
index c774093..96db801 100644
--- a/src/com/android/settings/webview/WebViewAppPreferenceController.java
+++ b/src/com/android/settings/webview/WebViewAppPreferenceController.java
@@ -22,6 +22,10 @@
 import com.android.settings.applications.defaultapps.DefaultAppInfo;
 import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
 
+/**
+ * Deprecated in favor of {@link com.android.settings.development.WebViewAppPreferenceControllerV2}
+ */
+@Deprecated
 public class WebViewAppPreferenceController extends DefaultAppPreferenceController {
 
     private static final String WEBVIEW_APP_KEY = "select_webview_provider";
diff --git a/src/com/android/settings/webview/WebViewUpdateServiceWrapper.java b/src/com/android/settings/webview/WebViewUpdateServiceWrapper.java
index e4eb0fc..fa1cd3d 100644
--- a/src/com/android/settings/webview/WebViewUpdateServiceWrapper.java
+++ b/src/com/android/settings/webview/WebViewUpdateServiceWrapper.java
@@ -34,7 +34,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-class WebViewUpdateServiceWrapper {
+public class WebViewUpdateServiceWrapper {
     private static final String TAG = "WVUSWrapper";
 
     public WebViewUpdateServiceWrapper() {}
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index d163616..9f52159 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -17,6 +17,7 @@
 package com.android.settings.wifi;
 
 import android.annotation.Nullable;
+import android.app.Activity;
 import android.app.Dialog;
 import android.content.Context;
 import android.icu.text.Collator;
@@ -28,6 +29,7 @@
 import android.support.v7.preference.PreferenceScreen;
 import android.util.Log;
 
+import android.widget.Toast;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
@@ -88,6 +90,22 @@
         }
     };
 
+    private final WifiManager.ActionListener mSaveListener = new WifiManager.ActionListener() {
+        @Override
+        public void onSuccess() {
+            postUpdatePreference();
+        }
+        @Override
+        public void onFailure(int reason) {
+            Activity activity = getActivity();
+            if (activity != null) {
+                Toast.makeText(activity,
+                    R.string.wifi_failed_save_message,
+                    Toast.LENGTH_SHORT).show();
+            }
+        }
+    };
+
     private WifiDialog mDialog;
     private WifiManagerWrapper mWifiManager;
     private AccessPoint mDlgAccessPoint;
@@ -267,7 +285,7 @@
 
     @Override
     public void onSubmit(WifiDialog dialog) {
-        // Ignored
+        mWifiManager.save(dialog.getController().getConfig(), mSaveListener);
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index b143f58..98af552 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -37,9 +37,7 @@
 import android.net.wifi.WpsInfo;
 import android.nfc.NfcAdapter;
 import android.os.Bundle;
-import android.os.HandlerThread;
 import android.os.PowerManager;
-import android.os.Process;
 import android.provider.Settings;
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
@@ -162,8 +160,6 @@
     private WifiTracker mWifiTracker;
     private String mOpenSsid;
 
-    private HandlerThread mBgThread;
-
     private AccessPointPreference.UserBadgeCache mUserBadgeCache;
 
     private PreferenceCategory mConnectedAccessPointPreferenceCategory;
@@ -211,9 +207,6 @@
         addPreferences();
 
         mIsRestricted = isUiRestricted();
-
-        mBgThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
-        mBgThread.start();
     }
 
     private void addPreferences() {
@@ -238,17 +231,11 @@
     }
 
     @Override
-    public void onDestroy() {
-        mBgThread.quit();
-        super.onDestroy();
-    }
-
-    @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
         mWifiTracker = WifiTrackerFactory.create(
-                getActivity(), this, mBgThread.getLooper(), true, true, false);
+                getActivity(), this, getLifecycle(), true, true);
         mWifiManager = mWifiTracker.getManager();
 
         mConnectListener = new WifiManager.ActionListener() {
@@ -350,8 +337,6 @@
         // On/off switch is hidden for Setup Wizard (returns null)
         mWifiEnabler = createWifiEnabler();
 
-        mWifiTracker.startTracking();
-
         if (mIsRestricted) {
             restrictUi();
             return;
@@ -430,7 +415,6 @@
 
     @Override
     public void onStop() {
-        mWifiTracker.stopTracking();
         getView().removeCallbacks(mUpdateAccessPointsRunnable);
         getView().removeCallbacks(mHideProgressBarRunnable);
         super.onStop();
@@ -1137,7 +1121,7 @@
 
                 // Add saved Wi-Fi access points
                 final List<AccessPoint> accessPoints =
-                        WifiTracker.getCurrentAccessPoints(context, true, false, false);
+                        WifiTracker.getCurrentAccessPoints(context, true, false);
                 for (AccessPoint accessPoint : accessPoints) {
                     data = new SearchIndexableRaw(context);
                     data.title = accessPoint.getSsidStr();
diff --git a/src/com/android/settings/wrapper/WifiManagerWrapper.java b/src/com/android/settings/wrapper/WifiManagerWrapper.java
index 4202691..c788995 100644
--- a/src/com/android/settings/wrapper/WifiManagerWrapper.java
+++ b/src/com/android/settings/wrapper/WifiManagerWrapper.java
@@ -1,5 +1,6 @@
 package com.android.settings.wrapper;
 
+import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 
 /**
@@ -37,9 +38,16 @@
     }
 
     /**
-     * {@link WifiManager#removePasspointConfiguration}
+     * {@link WifiManager#forget}
      */
     public void forget(int netId, WifiManager.ActionListener listener) {
         mWifiManager.forget(netId, listener);
     }
+
+    /**
+     * {@link WifiManager#save}
+     */
+    public void save(WifiConfiguration config, WifiManager.ActionListener listener) {
+        mWifiManager.save(config, listener);
+    }
 }
diff --git a/tests/robotests/src/android/service/settings/suggestions/Suggestion.java b/tests/robotests/src/android/service/settings/suggestions/Suggestion.java
index 2bb6192..750bc05 100644
--- a/tests/robotests/src/android/service/settings/suggestions/Suggestion.java
+++ b/tests/robotests/src/android/service/settings/suggestions/Suggestion.java
@@ -17,13 +17,16 @@
 package android.service.settings.suggestions;
 
 import android.app.PendingIntent;
+import android.graphics.drawable.Icon;
 import android.os.Parcel;
 import android.text.TextUtils;
+import android.widget.RemoteViews;
 
 public class Suggestion {
     private final String mId;
     private final CharSequence mTitle;
     private final CharSequence mSummary;
+    private final Icon mIcon;
     private final PendingIntent mPendingIntent;
 
     /**
@@ -48,6 +51,13 @@
     }
 
     /**
+     * Optional icon for this suggestion.
+     */
+    public Icon getIcon() {
+        return mIcon;
+    }
+
+    /**
      * The Intent to launch when the suggestion is activated.
      */
     public PendingIntent getPendingIntent() {
@@ -57,17 +67,11 @@
     private Suggestion(Builder builder) {
         mTitle = builder.mTitle;
         mSummary = builder.mSummary;
+        mIcon = builder.mIcon;
         mPendingIntent = builder.mPendingIntent;
         mId = builder.mId;
     }
 
-    private Suggestion(Parcel in) {
-        mId = in.readString();
-        mTitle = in.readCharSequence();
-        mSummary = in.readCharSequence();
-        mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader());
-    }
-
     /**
      * Builder class for {@link Suggestion}.
      */
@@ -75,6 +79,7 @@
         private final String mId;
         private CharSequence mTitle;
         private CharSequence mSummary;
+        private Icon mIcon;
         private PendingIntent mPendingIntent;
 
         public Builder(String id) {
@@ -102,6 +107,14 @@
         }
 
         /**
+         * Sets icon for the suggestion.
+         */
+        public Builder setIcon(Icon icon) {
+            mIcon = icon;
+            return this;
+        }
+
+        /**
          * Sets suggestion intent
          */
         public Builder setPendingIntent(PendingIntent pendingIntent) {
diff --git a/tests/robotests/src/com/android/settings/applications/UsageAccessDetailsTest.java b/tests/robotests/src/com/android/settings/applications/UsageAccessDetailsTest.java
index 07acb13..1a3aeb5 100644
--- a/tests/robotests/src/com/android/settings/applications/UsageAccessDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/UsageAccessDetailsTest.java
@@ -16,17 +16,20 @@
 
 package com.android.settings.applications;
 
+import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import android.os.RemoteException;
+import android.os.Bundle;
 
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.ApplicationsState;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -68,9 +71,12 @@
     }
 
     @Test
-    public void refreshUi_nullPackageInfo_shouldNotCrash() throws RemoteException {
-        mFragment.mPackageInfo = null;
-        mFragment.refreshUi();
-        // should not crash
+    public void refreshUi_hasNoAppEntry_shouldReturnFalse() {
+        mFragment.mState = mock(ApplicationsState.class);
+        mFragment.setArguments(new Bundle());
+
+        assertThat(mFragment.refreshUi()).isFalse();
+        assertThat(mFragment.mAppEntry).isNull();
+        assertThat(mFragment.mPackageInfo).isNull();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/AllowAppsOnExternalPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AllowAppsOnExternalPreferenceControllerTest.java
new file mode 100644
index 0000000..e23c4cc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/AllowAppsOnExternalPreferenceControllerTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2017 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;
+
+
+import static com.android.settings.development.AllowAppsOnExternalPreferenceController
+        .SETTING_VALUE_OFF;
+import static com.android.settings.development.AllowAppsOnExternalPreferenceController
+        .SETTING_VALUE_ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AllowAppsOnExternalPreferenceControllerTest {
+
+    @Mock
+    private SwitchPreference mPreference;
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+
+    private Context mContext;
+    private AllowAppsOnExternalPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = new AllowAppsOnExternalPreferenceController(mContext);
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
+                mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void onPreferenceChange_settingEnabled_allowAppsOnExternalShouldBeOn() {
+        mController.onPreferenceChange(mPreference, true /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.FORCE_ALLOW_ON_EXTERNAL, -1 /* default */);
+
+        assertThat(mode).isEqualTo(SETTING_VALUE_ON);
+    }
+
+    @Test
+    public void onPreferenceChange_settingDisabled_allowAppsOnExternalShouldBeOff() {
+        mController.onPreferenceChange(mPreference, false /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.FORCE_ALLOW_ON_EXTERNAL, -1 /* default */);
+
+        assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
+    }
+
+    @Test
+    public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.FORCE_ALLOW_ON_EXTERNAL, SETTING_VALUE_OFF);
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void updateState_settingEnabled_preferenceShouldBeChecked() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.FORCE_ALLOW_ON_EXTERNAL, SETTING_VALUE_ON);
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
+        mController.onDeveloperOptionsSwitchDisabled();
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.FORCE_ALLOW_ON_EXTERNAL, -1 /* default */);
+
+        assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
+        verify(mPreference).setChecked(false);
+        verify(mPreference).setEnabled(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchEnabled_shouldEnablePreference() {
+        mController.onDeveloperOptionsSwitchEnabled();
+
+        verify(mPreference).setEnabled(true);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerTest.java
index f703b26..c61dfc6 100644
--- a/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerTest.java
@@ -47,6 +47,10 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+/**
+ * deprecated in favor of {@link BugReportInPowerPreferenceControllerV2}
+ */
+@Deprecated
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class BugReportInPowerPreferenceControllerTest {
diff --git a/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerV2Test.java
new file mode 100644
index 0000000..6fa1400
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BugReportInPowerPreferenceControllerV2Test.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2016 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;
+
+import static com.android.settings.development
+        .BugReportInPowerPreferenceControllerV2.COMPONENT_NAME;
+import static com.android.settings.development
+        .BugReportInPowerPreferenceControllerV2.SETTING_VALUE_OFF;
+import static com.android.settings.development
+        .BugReportInPowerPreferenceControllerV2.SETTING_VALUE_ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.wrapper.PackageManagerWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BugReportInPowerPreferenceControllerV2Test {
+
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private PackageManagerWrapper mPackageManager;
+    @Mock
+    private Context mContext;
+    @Mock
+    private SwitchPreference mPreference;
+
+    private ContentResolver mContentResolver;
+    private BugReportInPowerPreferenceControllerV2 mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContentResolver = RuntimeEnvironment.application.getContentResolver();
+        when(mContext.getContentResolver()).thenReturn(mContentResolver);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        mController = new BugReportInPowerPreferenceControllerV2(mContext);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
+    }
+
+    @Test
+    public void isAvailable_hasDebugRestriction_shouldReturnFalse() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(true);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_noDebugRestriction_shouldReturnTrue() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_preferenceShouldNotBeChecked() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mController.displayPreference(mScreen);
+
+        mController.onDeveloperOptionsSwitchDisabled();
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void onPreferenceChanged_settingDisabled_shouldDisableBugReportInPowerSetting() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mController.displayPreference(mScreen);
+
+        mController.onPreferenceChange(mPreference, false /* new value */);
+        int mode = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU, -1 /* default */);
+
+        assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
+        verify(mPackageManager).setComponentEnabledSetting(COMPONENT_NAME,
+                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
+    }
+
+    @Test
+    public void onPreferenceChanged_settingEnabled_shouldEnableBugReportInPowerSetting() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mController.displayPreference(mScreen);
+
+        mController.onPreferenceChange(mPreference, true /* new value */);
+        int mode = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU, -1 /* default */);
+
+        assertThat(mode).isEqualTo(SETTING_VALUE_ON);
+        verify(mPackageManager).setComponentEnabledSetting(COMPONENT_NAME,
+                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0 /* flags */);
+    }
+
+
+    @Test
+    public void updateState_settingsOn_preferenceShouldBeChecked() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU, SETTING_VALUE_ON);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_settingsOff_preferenceShouldNotBeChecked() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU, SETTING_VALUE_OFF);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_shouldTurnOffPreference() {
+        when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+        mController.displayPreference(mScreen);
+
+        mController.onDeveloperOptionsSwitchDisabled();
+        int mode = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Global.BUGREPORT_IN_POWER_MENU, -1 /* default */);
+
+        assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
+        verify(mPreference).setChecked(false);
+        verify(mPackageManager).setComponentEnabledSetting(COMPONENT_NAME,
+                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/ClearAdbKeysPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/ClearAdbKeysPreferenceControllerTest.java
new file mode 100644
index 0000000..4bcdb98
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/ClearAdbKeysPreferenceControllerTest.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static com.android.settings.development.ClearAdbKeysPreferenceController
+        .RO_ADB_SECURE_PROPERTY_KEY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.hardware.usb.IUsbManager;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowSystemProperties;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = {SettingsShadowSystemProperties.class})
+public class ClearAdbKeysPreferenceControllerTest {
+
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private SwitchPreference mPreference;
+    @Mock
+    private IUsbManager mUsbManager;
+    @Mock
+    private DevelopmentSettingsDashboardFragment mFragment;
+
+    private Context mContext;
+
+    private ClearAdbKeysPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = spy(new ClearAdbKeysPreferenceController(mContext, mFragment));
+        ReflectionHelpers.setField(mController, "mUsbManager", mUsbManager);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowClearAdbKeysWarningDialog.resetDialog();
+        SettingsShadowSystemProperties.clear();
+    }
+
+    @Test
+    public void isAvailable_roAdbSecureEnabled_shouldBeTrue() {
+        SystemProperties.set(RO_ADB_SECURE_PROPERTY_KEY, Boolean.toString(true));
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_roAdbSecureDisabled_shouldBeFalse() {
+        SystemProperties.set(RO_ADB_SECURE_PROPERTY_KEY, Boolean.toString(false));
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void displayPreference_isNotAdminUser_preferenceShouldBeDisabled() {
+        SystemProperties.set(RO_ADB_SECURE_PROPERTY_KEY, Boolean.toString(true));
+        doReturn(false).when(mController).isAdminUser();
+
+        mController.displayPreference(mScreen);
+
+        verify(mPreference).setEnabled(false);
+    }
+
+    @Test
+    @Config(shadows = {
+            ShadowClearAdbKeysWarningDialog.class
+    })
+    public void handlePreferenceTreeClick_clearAdbKeysPreference_shouldShowWarningDialog() {
+        SystemProperties.set(RO_ADB_SECURE_PROPERTY_KEY, Boolean.toString(true));
+        doReturn(true).when(mController).isAdminUser();
+        mController.displayPreference(mScreen);
+        final String preferenceKey = mController.getPreferenceKey();
+        when(mPreference.getKey()).thenReturn(preferenceKey);
+        final boolean isHandled = mController.handlePreferenceTreeClick(mPreference);
+
+        assertThat(ShadowClearAdbKeysWarningDialog.sIsShowing).isTrue();
+        assertThat(isHandled).isTrue();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_notClearAdbKeysPreference_shouldReturnFalse() {
+        SystemProperties.set(RO_ADB_SECURE_PROPERTY_KEY, Boolean.toString(true));
+        doReturn(true).when(mController).isAdminUser();
+        mController.displayPreference(mScreen);
+        when(mPreference.getKey()).thenReturn("Some random key!!!");
+        final boolean isHandled = mController.handlePreferenceTreeClick(mPreference);
+
+        assertThat(isHandled).isFalse();
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchEnabled_isAdminUser_shouldEnablePreference() {
+        SystemProperties.set(RO_ADB_SECURE_PROPERTY_KEY, Boolean.toString(true));
+        doReturn(true).when(mController).isAdminUser();
+        mController.displayPreference(mScreen);
+        mController.onDeveloperOptionsSwitchEnabled();
+
+        verify(mPreference).setEnabled(true);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchEnabled_isNotAdminUser_shouldNotEnablePreference() {
+        SystemProperties.set(RO_ADB_SECURE_PROPERTY_KEY, Boolean.toString(true));
+        doReturn(false).when(mController).isAdminUser();
+        mController.displayPreference(mScreen);
+        mController.onDeveloperOptionsSwitchEnabled();
+
+        verify(mPreference, never()).setEnabled(true);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
+        SystemProperties.set(RO_ADB_SECURE_PROPERTY_KEY, Boolean.toString(true));
+        doReturn(true).when(mController).isAdminUser();
+        mController.displayPreference(mScreen);
+        mController.onDeveloperOptionsSwitchDisabled();
+
+        verify(mPreference).setEnabled(false);
+    }
+
+    @Test
+    public void onClearAdbKeysConfirmed_shouldClearKeys() throws RemoteException {
+        mController.onClearAdbKeysConfirmed();
+
+        verify(mUsbManager).clearUsbDebuggingKeys();
+    }
+
+    @Implements(ClearAdbKeysWarningDialog.class)
+    public static class ShadowClearAdbKeysWarningDialog {
+
+        public static boolean sIsShowing;
+
+        @Implementation
+        public static void show(Fragment host) {
+            sIsShowing = true;
+        }
+
+        public static void resetDialog() {
+            sIsShowing = false;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
index 2787fc1..ddf5365 100644
--- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
@@ -17,7 +17,6 @@
 package com.android.settings.development;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -51,11 +50,7 @@
 import java.util.List;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
-        shadows = {
-                SettingsShadowResources.class,
-                SettingsShadowResources.SettingsShadowTheme.class
-        })
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class DevelopmentSettingsDashboardFragmentTest {
 
     private SwitchBar mSwitchBar;
@@ -100,6 +95,10 @@
     }
 
     @Test
+    @Config(shadows = {
+            SettingsShadowResources.class,
+            SettingsShadowResources.SettingsShadowTheme.class
+    })
     public void searchIndex_pageDisabled_shouldAddAllKeysToNonIndexable() {
         final Context appContext = RuntimeEnvironment.application;
         DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, false);
@@ -115,7 +114,8 @@
     @Config(shadows = {
             ShadowPictureColorModePreferenceController.class,
             ShadowAdbPreferenceController.class,
-            ShadowBluetoothInbandRingingPreferenceController.class
+            ShadowBluetoothInbandRingingPreferenceController.class,
+            ShadowClearAdbKeysPreferenceController.class
     })
     public void searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable() {
         final Context appContext = RuntimeEnvironment.application;
@@ -208,6 +208,17 @@
         verify(controller).onAdbDialogDismissed();
     }
 
+    @Test
+    public void onAdbClearKeysDialogConfirmed_shouldCallControllerDialogConfirmed() {
+        final ClearAdbKeysPreferenceController controller = mock(
+                ClearAdbKeysPreferenceController.class);
+        doReturn(controller).when(mDashboard).getDevelopmentOptionsController(
+                ClearAdbKeysPreferenceController.class);
+        mDashboard.onAdbClearKeysDialogConfirmed();
+
+        verify(controller).onClearAdbKeysConfirmed();
+    }
+
     @Implements(EnableDevelopmentSettingWarningDialog.class)
     public static class ShadowEnableDevelopmentSettingWarningDialog {
 
@@ -248,4 +259,13 @@
             return true;
         }
     }
+
+    @Implements(ClearAdbKeysPreferenceController.class)
+    public static class ShadowClearAdbKeysPreferenceController {
+
+        @Implementation
+        public boolean isAvailable() {
+            return true;
+        }
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/development/LocalBackupPasswordPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/LocalBackupPasswordPreferenceControllerTest.java
new file mode 100644
index 0000000..c698313
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/LocalBackupPasswordPreferenceControllerTest.java
@@ -0,0 +1,120 @@
+package com.android.settings.development;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.backup.IBackupManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class LocalBackupPasswordPreferenceControllerTest {
+
+    @Mock
+    private Preference mPreference;
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private IBackupManager mBackupManager;
+
+    private Context mContext;
+    private LocalBackupPasswordPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = spy(new LocalBackupPasswordPreferenceController(mContext));
+        ReflectionHelpers.setField(mController, "mUserManager", mUserManager);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(
+                mPreference);
+    }
+
+    @Test
+    public void updateState_hasBackupPassword_preferenceShouldHavePasswordSetSummary()
+            throws RemoteException {
+        ReflectionHelpers.setField(mController, "mBackupManager", mBackupManager);
+        doReturn(true).when(mController).isAdminUser();
+        when(mBackupManager.hasBackupPassword()).thenReturn(true);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary(R.string.local_backup_password_summary_change);
+    }
+
+    @Test
+    public void updateState_noBackupPassword_preferenceShouldHaveNoPasswordSetSummary()
+            throws RemoteException {
+        ReflectionHelpers.setField(mController, "mBackupManager", mBackupManager);
+        doReturn(true).when(mController).isAdminUser();
+        when(mBackupManager.hasBackupPassword()).thenReturn(false);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary(R.string.local_backup_password_summary_none);
+    }
+
+    @Test
+    public void updateState_backupManagerIsNull_shouldDisablePreference() throws RemoteException {
+        ReflectionHelpers.setField(mController, "mBackupManager", null);
+        doReturn(true).when(mController).isAdminUser();
+        when(mBackupManager.hasBackupPassword()).thenReturn(true);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setEnabled(false);
+        verify(mPreference, never()).setSummary(any());
+    }
+
+    @Test
+    public void updateState_backupManagerIsNotNullAndNotAdminUser_shouldDisablePreference()
+            throws RemoteException {
+        ReflectionHelpers.setField(mController, "mBackupManager", mBackupManager);
+        doReturn(false).when(mController).isAdminUser();
+        when(mBackupManager.hasBackupPassword()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setEnabled(false);
+        verify(mPreference, never()).setSummary(any());
+    }
+
+    @Test
+    public void updateState_backupManagerIsNotNullAndAdminUser_shouldEnablePreference()
+            throws RemoteException {
+        ReflectionHelpers.setField(mController, "mBackupManager", mBackupManager);
+        doReturn(true).when(mController).isAdminUser();
+        when(mBackupManager.hasBackupPassword()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setEnabled(true);
+        verify(mPreference, never()).setSummary(any());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/NotificationChannelWarningsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/NotificationChannelWarningsPreferenceControllerTest.java
new file mode 100644
index 0000000..5ad0329
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/NotificationChannelWarningsPreferenceControllerTest.java
@@ -0,0 +1,151 @@
+package com.android.settings.development;
+
+/*
+ * Copyright (C) 2017 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.
+ */
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class NotificationChannelWarningsPreferenceControllerTest {
+
+    @Mock
+    private SwitchPreference mPreference;
+    @Mock
+    private PreferenceScreen mScreen;
+
+
+    private Context mContext;
+    private NotificationChannelWarningsPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = new NotificationChannelWarningsPreferenceController(mContext);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        mController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void onPreferenceChange_settingEnabled_shouldEnableNotificationChannelWarnings() {
+        mController.onPreferenceChange(mPreference, true /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, -1 /* default */);
+
+        assertThat(mode).isEqualTo(
+                NotificationChannelWarningsPreferenceController.SETTING_VALUE_ON);
+    }
+
+    @Test
+    public void onPreferenceChange_settingDisabled_shouldDisableNotificationChannelWarnings() {
+        mController.onPreferenceChange(mPreference, false /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, -1 /* default */);
+
+        assertThat(mode).isEqualTo(
+                NotificationChannelWarningsPreferenceController.SETTING_VALUE_OFF);
+    }
+
+    @Test
+    public void updateState_settingEnabled_preferenceShouldBeChecked() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
+                NotificationChannelWarningsPreferenceController.SETTING_VALUE_ON);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
+                NotificationChannelWarningsPreferenceController.SETTING_VALUE_OFF);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void updateState_settingUndefinedDebuggingEnabled_preferenceShouldBeChecked() {
+        mController = spy(mController);
+        doReturn(true).when(mController).isDebuggable();
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, "NotAnInteger");
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_settingUndefinedDebuggingDisabled_preferenceShouldNotBeChecked() {
+        mController = spy(mController);
+        doReturn(false).when(mController).isDebuggable();
+        Settings.Global.putString(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, "NotAnInteger");
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_preferenceShouldBeDisabled() {
+        mController.onDeveloperOptionsSwitchDisabled();
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, -1 /* default */);
+
+        assertThat(mode).isEqualTo(
+                NotificationChannelWarningsPreferenceController.SETTING_VALUE_OFF);
+        verify(mPreference).setChecked(false);
+        verify(mPreference).setEnabled(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchEnabled_preferenceShouldBeEnabled() {
+        mController.onDeveloperOptionsSwitchEnabled();
+
+        verify(mPreference).setEnabled(true);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/ResizableActivityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/ResizableActivityPreferenceControllerTest.java
new file mode 100644
index 0000000..1289aec
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/ResizableActivityPreferenceControllerTest.java
@@ -0,0 +1,124 @@
+package com.android.settings.development;
+
+/*
+ * Copyright (C) 2017 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.
+ */
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ResizableActivityPreferenceControllerTest {
+
+    @Mock
+    private SwitchPreference mPreference;
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private Context mContext;
+    private ResizableActivityPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = new ResizableActivityPreferenceController(mContext);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        mController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void onPreferenceChange_settingEnabled_shouldEnableResizableActivities() {
+        mController.onPreferenceChange(mPreference, true /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, -1 /* default */);
+
+        assertThat(mode).isEqualTo(
+                ResizableActivityPreferenceController.SETTING_VALUE_ON);
+    }
+
+    @Test
+    public void onPreferenceChange_settingDisabled_shouldDisableResizableActivities() {
+        mController.onPreferenceChange(mPreference, false /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, -1 /* default */);
+
+        assertThat(mode).isEqualTo(
+                ResizableActivityPreferenceController.SETTING_VALUE_OFF);
+    }
+
+    @Test
+    public void updateState_settingEnabled_preferenceShouldBeChecked() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
+                ResizableActivityPreferenceController.SETTING_VALUE_ON);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
+                ResizableActivityPreferenceController.SETTING_VALUE_OFF);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_preferenceShouldBeDisabled() {
+        mController.onDeveloperOptionsSwitchDisabled();
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, -1 /* default */);
+
+        assertThat(mode).isEqualTo(
+                ResizableActivityPreferenceController.SETTING_VALUE_OFF);
+        verify(mPreference).setChecked(false);
+        verify(mPreference).setEnabled(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchEnabled_preferenceShouldBeEnabled() {
+        mController.onDeveloperOptionsSwitchEnabled();
+
+        verify(mPreference).setEnabled(true);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerTest.java
index 45e457b..cea3d89 100644
--- a/tests/robotests/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerTest.java
@@ -47,6 +47,10 @@
 import java.util.Collections;
 import java.util.List;
 
+/**
+ * deprecated in favor of {@link VerifyAppsOverUsbPreferenceControllerV2}
+ */
+@Deprecated
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class VerifyAppsOverUsbPreferenceControllerTest {
diff --git a/tests/robotests/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerV2Test.java
new file mode 100644
index 0000000..9e60295
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/VerifyAppsOverUsbPreferenceControllerV2Test.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.wrapper.PackageManagerWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class VerifyAppsOverUsbPreferenceControllerV2Test {
+
+    @Mock
+    private PackageManagerWrapper mPackageManager;
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private RestrictedSwitchPreference mPreference;
+
+    @Mock
+    private VerifyAppsOverUsbPreferenceControllerV2.RestrictedLockUtilsDelegate
+            mRestrictedLockUtilsDelegate;
+
+    private Context mContext;
+    private VerifyAppsOverUsbPreferenceControllerV2 mController;
+
+    /** Convenience class for setting global int settings. */
+    class GlobalSetter {
+        public GlobalSetter set(String setting, int value) {
+            Global.putInt(mContext.getContentResolver(), setting, value);
+            return this;
+        }
+    }
+
+    private final GlobalSetter mGlobals = new GlobalSetter();
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+        mController = new VerifyAppsOverUsbPreferenceControllerV2(mContext);
+        ReflectionHelpers.setField(
+                mController, "mRestrictedLockUtils", mRestrictedLockUtilsDelegate);
+        ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
+        mController.displayPreference(mScreen);
+    }
+
+    private void setupVerifyBroadcastReceivers(boolean nonEmpty) {
+        final List<ResolveInfo> resolveInfos = nonEmpty
+                ? Collections.singletonList(mock(ResolveInfo.class))
+                : Collections.<ResolveInfo>emptyList();
+        when(mPackageManager.queryBroadcastReceivers((Intent) any(), anyInt()))
+                .thenReturn(resolveInfos);
+    }
+
+    private void setupEnforcedAdmin(EnforcedAdmin result) {
+        when(mRestrictedLockUtilsDelegate.checkIfRestrictionEnforced(
+                (Context) any(), anyString(), anyInt())).thenReturn(result);
+    }
+
+    @Test
+    public void updateState_settingEnabled_preferenceShouldBeChecked() {
+        setupVerifyBroadcastReceivers(true);
+        setupEnforcedAdmin(null);
+        mGlobals.set(Global.ADB_ENABLED, 1 /* setting enabled */)
+                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1 /* setting enabled */);
+        mController.updateState(mPreference);
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
+        setupVerifyBroadcastReceivers(true);
+        setupEnforcedAdmin(null);
+        mGlobals.set(Global.ADB_ENABLED, 1 /* setting enabled */)
+                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 0 /* setting disabled */);
+        mController.updateState(mPreference);
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void updateState_adbDisabled_preferenceShouldNotBeChecked() {
+        setupVerifyBroadcastReceivers(true);
+        setupEnforcedAdmin(null);
+        mGlobals.set(Global.ADB_ENABLED, 0 /* setting disabled */)
+                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1 /* setting enabled */);
+        mController.updateState(mPreference);
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void updateState_verifierOff_preferenceShouldNotBeChecked() {
+        setupVerifyBroadcastReceivers(true);
+        setupEnforcedAdmin(null);
+        mGlobals.set(Global.ADB_ENABLED, 1 /* setting enabled */)
+                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1 /* setting enabled */)
+                .set(Global.PACKAGE_VERIFIER_ENABLE, 0 /* setting disabled */);
+        mController.updateState(mPreference);
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void updateState_noBroadcastReceivers_preferenceShouldNotBeChecked() {
+        setupVerifyBroadcastReceivers(false);
+        setupEnforcedAdmin(null);
+        mGlobals.set(Global.ADB_ENABLED, 1 /* setting enabled */)
+                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1 /* setting enabled */);
+        mController.updateState(mPreference);
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    public void updateState_restrictedByAdmin_preferenceShouldBeDisabled() {
+        setupVerifyBroadcastReceivers(true);
+        final EnforcedAdmin admin = new EnforcedAdmin();
+        setupEnforcedAdmin(admin);
+        mGlobals.set(Global.ADB_ENABLED, 1 /* setting enabled */)
+                .set(Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1 /* setting enabled */);
+        mController.updateState(mPreference);
+        verify(mPreference).setDisabledByAdmin(admin);
+    }
+
+    @Test
+    public void isAvailable_verifierNotVisible_shouldReturnFalse() {
+        setupVerifyBroadcastReceivers(true);
+        mGlobals.set(Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 0 /* setting disabled */);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_verifierVisible_shouldReturnTrue() {
+        setupVerifyBroadcastReceivers(true);
+        mGlobals.set(Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1 /* setting enabled */);
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void onPreferenceChange_settingEnabled_shouldEnableUsbVerify() {
+        mController.onPreferenceChange(mPreference, true /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, -1 /* default */);
+
+        assertThat(mode).isEqualTo(VerifyAppsOverUsbPreferenceControllerV2.SETTING_VALUE_ON);
+    }
+
+    @Test
+    public void onPreferenceChange_settingDisabled_shouldDisableUsbVerify() {
+        mController.onPreferenceChange(mPreference, false /* new value */);
+
+        final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, -1 /* default */);
+
+        assertThat(mode).isEqualTo(VerifyAppsOverUsbPreferenceControllerV2.SETTING_VALUE_OFF);
+    }
+
+    @Test
+    public void onDeveloperOptionsEnabled_shouldUpdateState() {
+        mController = spy(mController);
+        mController.onDeveloperOptionsSwitchEnabled();
+
+        verify(mController).updateState(mPreference);
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/development/WebViewAppPreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/development/WebViewAppPreferenceControllerV2Test.java
new file mode 100644
index 0000000..faeda87
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/WebViewAppPreferenceControllerV2Test.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.defaultapps.DefaultAppInfo;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.webview.WebViewUpdateServiceWrapper;
+import com.android.settingslib.wrapper.PackageManagerWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class WebViewAppPreferenceControllerV2Test {
+
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+    @Mock
+    private PackageManagerWrapper mPackageManager;
+    @Mock
+    private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
+    @Mock
+    private Preference mPreference;
+    @Mock
+    private DefaultAppInfo mAppInfo;
+    @Mock
+    private Drawable mDrawable;
+
+    private Context mContext;
+    private WebViewAppPreferenceControllerV2 mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = spy(new WebViewAppPreferenceControllerV2(mContext));
+        ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
+        ReflectionHelpers.setField(mController, "mWebViewUpdateServiceWrapper",
+                mWebViewUpdateServiceWrapper);
+        doReturn(mAppInfo).when(mController).getDefaultAppInfo();
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
+                mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void updateState_hasAppLabel_shouldSetAppLabelAndIcon() {
+        final String appLabel = "SomeRandomAppLabel!!!";
+        when(mAppInfo.loadLabel()).thenReturn(appLabel);
+        when(mAppInfo.loadIcon()).thenReturn(mDrawable);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary(appLabel);
+        verify(mPreference).setIcon(mDrawable);
+    }
+
+    @Test
+    public void updateState_noAppLabel_shouldSetAppDefaultLabelAndNullIcon() {
+        final String appLabel = null;
+        when(mAppInfo.loadLabel()).thenReturn(appLabel);
+        when(mAppInfo.loadIcon()).thenReturn(mDrawable);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary(R.string.app_list_preference_none);
+        verify(mPreference).setIcon(null);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchDisabled_preferenceShouldBeDisabled() {
+        mController.onDeveloperOptionsSwitchDisabled();
+
+        verify(mPreference).setEnabled(false);
+    }
+
+    @Test
+    public void onDeveloperOptionsSwitchEnabled_preferenceShouldBeEnabled() {
+        mController.onDeveloperOptionsSwitchEnabled();
+
+        verify(mPreference).setEnabled(true);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/webview/WebViewAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/webview/WebViewAppPreferenceControllerTest.java
index 5ce21e8..08ecc9b 100644
--- a/tests/robotests/src/com/android/settings/webview/WebViewAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/webview/WebViewAppPreferenceControllerTest.java
@@ -30,6 +30,10 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 
+/**
+ * Deprecated in favor of {@link com.android.settings.development.WebViewAppPreferenceControllerV2}
+ */
+@Deprecated
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class WebViewAppPreferenceControllerTest {
diff --git a/tests/robotests/src/com/android/settings/wifi/SavedAccessPointsWifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/SavedAccessPointsWifiSettingsTest.java
index f9eb328..ec406cd 100644
--- a/tests/robotests/src/com/android/settings/wifi/SavedAccessPointsWifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/SavedAccessPointsWifiSettingsTest.java
@@ -16,31 +16,36 @@
 
 package com.android.settings.wifi;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager.ActionListener;
 import android.os.Handler;
-
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.wrapper.WifiManagerWrapper;
 import com.android.settingslib.wifi.AccessPoint;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.*;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SavedAccessPointsWifiSettingsTest {
 
-    @Mock
-    private Handler mHandler;
+    @Mock private WifiManagerWrapper mockWifiManager;
+    @Mock private WifiDialog mockWifiDialog;
+    @Mock private WifiConfigController mockConfigController;
+    @Mock private WifiConfiguration mockWifiConfiguration;
+    @Mock private AccessPoint mockAccessPoint;
+    @Mock private Handler mHandler;
 
     private SavedAccessPointsWifiSettings mSettings;
 
@@ -49,6 +54,10 @@
         MockitoAnnotations.initMocks(this);
         mSettings = new SavedAccessPointsWifiSettings();
         ReflectionHelpers.setField(mSettings, "mHandler", mHandler);
+        ReflectionHelpers.setField(mSettings, "mWifiManager", mockWifiManager);
+
+        when(mockWifiDialog.getController()).thenReturn(mockConfigController);
+        when(mockConfigController.getConfig()).thenReturn(mockWifiConfiguration);
     }
 
     @Test
@@ -56,7 +65,6 @@
         final AccessPoint accessPoint = mock(AccessPoint.class);
         when(accessPoint.isPasspointConfig()).thenReturn(true);
         ReflectionHelpers.setField(mSettings, "mSelectedAccessPoint", accessPoint);
-        ReflectionHelpers.setField(mSettings, "mWifiManager", mock(WifiManagerWrapper.class));
 
         mSettings.onForget(null);
 
@@ -76,4 +84,18 @@
 
         verify(mHandler).sendEmptyMessage(mSettings.MSG_UPDATE_PREFERENCES);
     }
+
+    @Test
+    public void onSubmit_shouldInvokeSaveApi() {
+        mSettings.onSubmit(mockWifiDialog);
+        verify(mockWifiManager).save(eq(mockWifiConfiguration), any(ActionListener.class));
+    }
+    @Test
+    public void onForget_shouldInvokeForgetApi() {
+        ReflectionHelpers.setField(mSettings, "mSelectedAccessPoint", mockAccessPoint);
+        when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfiguration);
+        mSettings.onForget(mockWifiDialog);
+        verify(mockWifiManager).forget(eq(mockWifiConfiguration.networkId), any(ActionListener.class));
+    }
 }
+