Merge "Introduce LocalBackupPasswordPreferenceController"
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/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/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/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/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 014d53c..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) {
@@ -246,15 +254,15 @@
         // 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));
@@ -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
         controllers.add(new AllowAppsOnExternalPreferenceController(context));
-        // force activities to be resizable
+        controllers.add(new ResizableActivityPreferenceController(context));
         // reset shortcutmanager rate-limiting
         return controllers;
     }
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/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/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/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/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/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));
+    }
 }
+