Merge "Add a no-op activity to handle development setting intent." into oc-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8d5c400..8e3fbe2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6515,6 +6515,9 @@
     <!-- Configure Notifications: Work profile section header [CHAR LIMIT=30] -->
     <string name="profile_section_header">Work notifications</string>
 
+    <!-- Configure Notifications: Title for the notification badging option. [CHAR LIMIT=30] -->
+    <string name="notification_badging_title">Allow icon badges</string>
+
     <!-- Configure Notifications: Title for the pulse notification light option. [CHAR LIMIT=30] -->
     <string name="notification_pulse_title">Blink light</string>
 
@@ -6576,6 +6579,12 @@
     <!-- [CHAR LIMIT=100] Notification Importance: blocked importance level description -->
     <string name="notification_importance_blocked">Never show notifications</string>
 
+    <!-- [CHAR LIMIT=100] Notification Importance template for the channel importance summary -->
+    <string name="notification_importance_divider" translatable="false"><xliff:g id="importance_title">%1$s</xliff:g>: <xliff:g id="importance_summary">%2$s</xliff:g></string>
+
+    <!-- Importance title strings for the Importance page. Also the second part of the importance
+     summary on the channel page-->
+
     <!-- [CHAR LIMIT=100] Notification Importance: min importance level description -->
     <string name="notification_importance_min">No sound or visual interruption</string>
 
@@ -6588,6 +6597,9 @@
     <!-- [CHAR LIMIT=100] Notification Importance: high importance level description -->
     <string name="notification_importance_high">Make sound and pop on screen</string>
 
+    <!-- Importance title strings for the Importance page. Also the first part of the importance
+     summary on the channel page-->
+
     <!-- [CHAR LIMIT=100] Notification Importance title: min importance level title -->
     <string name="notification_importance_min_title">Low</string>
 
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index a6ffff4..bed3aa6 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -22,6 +22,11 @@
         android:key="dashboard_tile_placeholder"
         android:order="1"/>
 
+    <!-- Notification badging -->
+    <SwitchPreference
+        android:key="notification_badging"
+        android:title="@string/notification_badging_title"/>
+
     <!-- Pulse notification light -->
     <SwitchPreference
         android:key="notification_pulse"
@@ -31,7 +36,7 @@
     <com.android.settings.notification.RestrictedDropDownPreference
         android:key="lock_screen_notifications"
         android:title="@string/lock_screen_notifications_title"
-        android:summary="%s"/>
+        android:summary="@string/summary_placeholder"/>
 
     <SwitchPreference
         android:key="gesture_swipe_down_fingerprint"
@@ -45,7 +50,7 @@
         <com.android.settings.notification.RestrictedDropDownPreference
             android:key="lock_screen_notifications_profile"
             android:title="@string/lock_screen_notifications_title"
-            android:summary="%s"/>
+            android:summary="@string/summary_placeholder"/>
 
     </PreferenceCategory>
 
diff --git a/res/xml/legacy_channel_notification_settings.xml b/res/xml/legacy_channel_notification_settings.xml
index 4e341a9..e271705 100644
--- a/res/xml/legacy_channel_notification_settings.xml
+++ b/res/xml/legacy_channel_notification_settings.xml
@@ -17,6 +17,12 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                   xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" >
 
+    <!-- Show badge -->
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="badge"
+        android:title="@string/notification_badge_title"
+        settings:useAdditionalSummary="true"
+        settings:restrictedSwitchSummary="@string/enabled_by_admin" />
 
     <!-- Importance toggle -->
     <com.android.settingslib.RestrictedSwitchPreference
diff --git a/res/xml/app_notification_settings.xml b/res/xml/notification_settings.xml
similarity index 67%
copy from res/xml/app_notification_settings.xml
copy to res/xml/notification_settings.xml
index 483b4a0..b2f1d3d 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/notification_settings.xml
@@ -15,15 +15,6 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
-        android:title="@string/app_notifications_title"
-        android:key="app_notification_settings">
-
-    <!-- Show badge -->
-    <com.android.settingslib.RestrictedSwitchPreference
-        android:key="badge"
-        android:title="@string/notification_badge_title"
-        settings:useAdditionalSummary="true"
-        settings:restrictedSwitchSummary="@string/enabled_by_admin" />
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
 
 </PreferenceScreen>
diff --git a/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index e151b2b..2a4416e 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -21,7 +21,7 @@
         <com.android.settings.notification.RestrictedDropDownPreference
             android:key="lock_screen_notifications"
             android:title="@string/lock_screen_notifications_title"
-            android:summary="%s"/>
+            android:summary="@string/summary_placeholder"/>
 
         <com.android.settingslib.RestrictedSwitchPreference
             android:key="add_users_when_locked"
diff --git a/res/xml/app_notification_settings.xml b/res/xml/upgraded_app_notification_settings.xml
similarity index 85%
rename from res/xml/app_notification_settings.xml
rename to res/xml/upgraded_app_notification_settings.xml
index 483b4a0..f9a3304 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/upgraded_app_notification_settings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- 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.
@@ -15,9 +15,7 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
-        android:title="@string/app_notifications_title"
-        android:key="app_notification_settings">
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
 
     <!-- Show badge -->
     <com.android.settingslib.RestrictedSwitchPreference
diff --git a/res/xml/channel_notification_settings.xml b/res/xml/upgraded_channel_notification_settings.xml
similarity index 100%
rename from res/xml/channel_notification_settings.xml
rename to res/xml/upgraded_channel_notification_settings.xml
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
index 14990a5..ac992d7 100644
--- a/res/xml/wifi_configure_settings.xml
+++ b/res/xml/wifi_configure_settings.xml
@@ -31,10 +31,11 @@
         android:title="@string/use_open_wifi_automatically_title"
         android:summary="@string/use_open_wifi_automatically_summary" />
 
-    <Preference
+    <SwitchPreference
             android:key="notify_open_networks"
             android:title="@string/wifi_notify_open_networks"
-            android:icon="@drawable/ic_open_wifi_notifications"/>
+            android:icon="@drawable/ic_open_wifi_notifications"
+            android:summary="@string/wifi_notify_open_networks_summary" />
 
     <SwitchPreference
         android:key="wifi_cellular_data_fallback"
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index f6f980a..0142ea2 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -103,6 +103,8 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.UserIcons;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.password.FingerprintManagerWrapper;
+import com.android.settings.password.IFingerprintManager;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -1197,6 +1199,15 @@
         }
     }
 
+    public static IFingerprintManager getFingerprintManagerWrapperOrNull(Context context) {
+        FingerprintManager fingerprintManager = getFingerprintManagerOrNull(context);
+        if (fingerprintManager != null) {
+            return new FingerprintManagerWrapper(fingerprintManager);
+        } else {
+            return null;
+        }
+    }
+
     /**
      * Launches an intent which may optionally have a user id defined.
      * @param fragment Fragment to use to launch the activity.
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index caac95f..edf2b75 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -271,6 +271,7 @@
             Settings.PrintSettingsActivity.class.getName(),
             // Home page > Apps & Notifications
             Settings.UserSettingsActivity.class.getName(),
+            Settings.ConfigureNotificationSettingsActivity.class.getName(),
             Settings.ManageApplicationsActivity.class.getName(),
             Settings.PaymentSettingsActivity.class.getName(),
             // Home page > Security & screen lock
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
index 510e953..107838c 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
@@ -82,9 +82,7 @@
             @Override
             public void onEnrollmentProgressChange(int steps, int remaining) {
                 mNextClicked = true;
-                if (!mSidecar.cancelEnrollment()) {
-                    proceedToEnrolling();
-                }
+                proceedToEnrolling(true /* cancelEnrollment */);
             }
 
             @Override
@@ -95,7 +93,7 @@
             public void onEnrollmentError(int errMsgId, CharSequence errString) {
                 if (mNextClicked && errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
                     mNextClicked = false;
-                    proceedToEnrolling();
+                    proceedToEnrolling(false /* cancelEnrollment */);
                 }
             }
         });
@@ -123,15 +121,23 @@
     @Override
     protected void onNextButtonClick() {
         mNextClicked = true;
-        if (mSidecar == null || (mSidecar != null && !mSidecar.cancelEnrollment())) {
-            proceedToEnrolling();
-        }
+        proceedToEnrolling(true /* cancelEnrollment */);
     }
 
-    private void proceedToEnrolling() {
-        getFragmentManager().beginTransaction().remove(mSidecar).commit();
-        mSidecar = null;
-        startActivityForResult(getEnrollingIntent(), ENROLLING);
+    private void proceedToEnrolling(boolean cancelEnrollment) {
+        if (mSidecar != null) {
+            if (cancelEnrollment) {
+                if (mSidecar.cancelEnrollment()) {
+                    // Enrollment cancel requested. When the cancellation is successful,
+                    // onEnrollmentError will be called with FINGERPRINT_ERROR_CANCELED, calling
+                    // this again.
+                    return;
+                }
+            }
+            getFragmentManager().beginTransaction().remove(mSidecar).commit();
+            mSidecar = null;
+            startActivityForResult(getEnrollingIntent(), ENROLLING);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
index e0c5d65..7fc7a04 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
@@ -28,12 +28,13 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.ChooseLockSettingsHelper;
 import com.android.settings.Utils;
-import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.password.IFingerprintManager;
 
 /**
  * Sidecar fragment to handle the state around fingerprint enrollment.
  */
-public class FingerprintEnrollSidecar extends InstrumentedPreferenceFragment {
+public class FingerprintEnrollSidecar extends InstrumentedFragment {
 
     private int mEnrollmentSteps = -1;
     private int mEnrollmentRemaining = 0;
@@ -44,7 +45,7 @@
     private byte[] mToken;
     private boolean mDone;
     private int mUserId;
-    private FingerprintManager mFingerprintManager;
+    private IFingerprintManager mFingerprintManager;
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -55,7 +56,7 @@
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
-        mFingerprintManager = Utils.getFingerprintManagerOrNull(activity);
+        mFingerprintManager = Utils.getFingerprintManagerWrapperOrNull(activity);
         mToken = activity.getIntent().getByteArrayExtra(
                 ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
         mUserId = activity.getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
diff --git a/src/com/android/settings/fuelgauge/BatteryMeterView.java b/src/com/android/settings/fuelgauge/BatteryMeterView.java
index c450b90..969f886 100644
--- a/src/com/android/settings/fuelgauge/BatteryMeterView.java
+++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java
@@ -38,6 +38,8 @@
     @VisibleForTesting
     ColorFilter mAccentColorFilter;
 
+    private int mLevel;
+
     public BatteryMeterView(Context context) {
         this(context, null, 0);
     }
@@ -64,6 +66,7 @@
     }
 
     public void setBatteryLevel(int level) {
+        mLevel = level;
         mDrawable.setBatteryLevel(level);
         if (level < mDrawable.getCriticalLevel()) {
             mDrawable.setBatteryColorFilter(mErrorColorFilter);
@@ -72,6 +75,10 @@
         }
     }
 
+    public int getBatteryLevel() {
+        return mLevel;
+    }
+
     public void setCharging(boolean charging) {
         mDrawable.setCharging(charging);
     }
diff --git a/src/com/android/settings/fuelgauge/FakeUid.java b/src/com/android/settings/fuelgauge/FakeUid.java
index 51ab73f..6f92b3d 100644
--- a/src/com/android/settings/fuelgauge/FakeUid.java
+++ b/src/com/android/settings/fuelgauge/FakeUid.java
@@ -305,4 +305,14 @@
     public long getMobileRadioApWakeupCount(int which) {
         return 0;
     }
+
+    @Override
+    public long[] getCpuFreqTimes(int which) {
+        return null;
+    }
+
+    @Override
+    public long[] getScreenOffCpuFreqTimes(int which) {
+        return null;
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index bcf830b..0309296 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.fuelgauge;
 
+import android.animation.Animator;
+import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -41,6 +43,7 @@
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.view.animation.AnimationUtils;
 import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -84,6 +87,10 @@
     private static final String KEY_BATTERY_HEADER = "battery_header";
     private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
     private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
+    private static final int BATTERY_ANIMATION_DURATION_MS_PER_LEVEL = 30;
+
+    @VisibleForTesting
+    static final String ARG_BATTERY_LEVEL = "key_battery_level";
 
     private static final String KEY_SCREEN_USAGE = "screen_usage";
     private static final String KEY_TIME_SINCE_LAST_FULL_CHARGE = "last_full_charge";
@@ -105,6 +112,8 @@
             new FooterPreferenceMixin(this, getLifecycle());
 
     @VisibleForTesting
+    int mBatteryLevel;
+    @VisibleForTesting
     boolean mShowAllApps = false;
     @VisibleForTesting
     PowerGaugePreference mScreenUsagePref;
@@ -124,6 +133,8 @@
         super.onCreate(icicle);
         setAnimationAllowed(true);
 
+        mBatteryLevel = getContext().getResources().getInteger(
+                com.android.internal.R.integer.config_criticalBatteryWarningLevel) + 1;
         mBatteryLayoutPref = (LayoutPreference) findPreference(KEY_BATTERY_HEADER);
         mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
         mScreenUsagePref = (PowerGaugePreference) findPreference(KEY_SCREEN_USAGE);
@@ -137,6 +148,14 @@
     }
 
     @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        if (savedInstanceState != null) {
+            mBatteryLevel = savedInstanceState.getInt(ARG_BATTERY_LEVEL);
+        }
+    }
+
+    @Override
     public int getMetricsCategory() {
         return MetricsEvent.FUELGAUGE_POWER_USAGE_SUMMARY;
     }
@@ -144,6 +163,8 @@
     @Override
     public void onResume() {
         super.onResume();
+
+        initHeaderPreference();
     }
 
     @Override
@@ -162,6 +183,12 @@
     }
 
     @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt(ARG_BATTERY_LEVEL, mBatteryLevel);
+    }
+
+    @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (KEY_BATTERY_HEADER.equals(preference.getKey())) {
             performBatteryHeaderClick();
@@ -569,15 +596,46 @@
                 .findViewById(R.id.battery_header_icon);
         final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.battery_percent);
         final TextView summary1 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary1);
-        timeText.setText(Utils.formatPercentage(info.batteryLevel));
         if (info.remainingLabel == null ) {
             summary1.setText(info.statusLabel);
         } else {
             summary1.setText(info.remainingLabel);
         }
-
-        batteryView.setBatteryLevel(info.batteryLevel);
         batteryView.setCharging(!info.discharging);
+        startBatteryHeaderAnimationIfNecessary(batteryView, timeText, mBatteryLevel,
+                info.batteryLevel);
+    }
+
+    @VisibleForTesting
+    void initHeaderPreference() {
+        final BatteryMeterView batteryView = (BatteryMeterView) mBatteryLayoutPref
+                .findViewById(R.id.battery_header_icon);
+        final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.battery_percent);
+
+        batteryView.setBatteryLevel(mBatteryLevel);
+        timeText.setText(Utils.formatPercentage(mBatteryLevel));
+    }
+
+    @VisibleForTesting
+    void startBatteryHeaderAnimationIfNecessary(BatteryMeterView batteryView, TextView timeTextView,
+            int prevLevel, int currentLevel) {
+        mBatteryLevel = currentLevel;
+        final int diff = Math.abs(prevLevel - currentLevel);
+        if (diff != 0) {
+            final ValueAnimator animator = ValueAnimator.ofInt(prevLevel, currentLevel);
+            animator.setDuration(BATTERY_ANIMATION_DURATION_MS_PER_LEVEL * diff);
+            animator.setInterpolator(AnimationUtils.loadInterpolator(getContext(),
+                    android.R.interpolator.fast_out_slow_in));
+            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    final Integer level = (Integer) animation.getAnimatedValue();
+                    batteryView.setBatteryLevel(level);
+                    timeTextView.setText(Utils.formatPercentage(level));
+                }
+            });
+            animator.start();
+        }
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 2048384..2035cd2 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.notification;
 
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
@@ -63,16 +62,12 @@
     private static final String TAG = "AppNotificationSettings";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private static final String KEY_IMPORTANCE = "allow_sound";
+    private static String KEY_GENERAL_CATEGORY = "categories";
+    private static String KEY_DELETED = "deleted";
 
     private List<NotificationChannelGroup> mChannelGroupList;
     private List<PreferenceCategory> mChannelGroups = new ArrayList();
-    private RestrictedSwitchPreference mImportanceToggle;
-    private LayoutPreference mBlockBar;
     private FooterPreference mDeletedChannels;
-    private SwitchBar mSwitchBar;
-
-    private boolean mShowLegacyChannelConfig = false;
 
     @Override
     public int getMetricsCategory() {
@@ -92,38 +87,50 @@
         if (getPreferenceScreen() != null) {
             getPreferenceScreen().removeAll();
             mChannelGroups.clear();
+            mDeletedChannels = null;
             mShowLegacyChannelConfig = false;
         }
 
-        addPreferencesFromResource(R.xml.app_notification_settings);
+        addPreferencesFromResource(R.xml.notification_settings);
         getPreferenceScreen().setOrderingAsAdded(true);
-
-        mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE);
-        mBlockedDesc = (FooterPreference) getPreferenceScreen().findPreference(KEY_BLOCKED_DESC);
-
         setupBlock();
-        setupBadge();
-        // load settings intent
+        addHeaderPref();
+        addAppLinkPref();
+
+        mShowLegacyChannelConfig = mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid);
+        if (mShowLegacyChannelConfig) {
+            mChannel = mBackend.getChannel(
+                    mAppRow.pkg, mAppRow.uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+            populateDefaultChannelPrefs();
+        } else {
+            addPreferencesFromResource(R.xml.upgraded_app_notification_settings);
+            setupBadge();
+            // Load channel settings
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... unused) {
+                    mChannelGroupList = mBackend.getChannelGroups(mPkg, mUid).getList();
+                    Collections.sort(mChannelGroupList, mChannelGroupComparator);
+                    return null;
+                }
+
+                @Override
+                protected void onPostExecute(Void unused) {
+                    if (getHost() == null) {
+                        return;
+                    }
+                    populateChannelList();
+                }
+            }.execute();
+        }
+
+        updateDependents(mAppRow.banned);
+    }
+
+    private void addHeaderPref() {
         ArrayMap<String, AppRow> rows = new ArrayMap<String, AppRow>();
         rows.put(mAppRow.pkg, mAppRow);
         collectConfigActivities(rows);
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... unused) {
-                mChannelGroupList = mBackend.getChannelGroups(mPkg, mUid).getList();
-                Collections.sort(mChannelGroupList, mChannelGroupComparator);
-                return null;
-            }
-
-            @Override
-            protected void onPostExecute(Void unused) {
-                if (getHost() == null) {
-                    return;
-                }
-                populateChannelList();
-            }
-        }.execute();
-
         final Activity activity = getActivity();
         final Preference pref = FeatureFactory.getFactory(activity)
                 .getApplicationFeatureProvider(activity)
@@ -135,15 +142,15 @@
                 .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
                         AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
                 .done(activity, getPrefContext());
+        pref.setKey(KEY_HEADER);
         getPreferenceScreen().addPreference(pref);
-
-        updateDependents(mAppRow.banned);
     }
 
     private void populateChannelList() {
         if (mChannelGroupList.isEmpty()) {
             PreferenceCategory groupCategory = new PreferenceCategory(getPrefContext());
             groupCategory.setTitle(R.string.notification_channels);
+            groupCategory.setKey(KEY_GENERAL_CATEGORY);
             getPreferenceScreen().addPreference(groupCategory);
             mChannelGroups.add(groupCategory);
 
@@ -151,15 +158,6 @@
             empty.setTitle(R.string.no_channels);
             empty.setEnabled(false);
             groupCategory.addPreference(empty);
-
-        } else if (mChannelGroupList.size() == 1 &&
-                mChannelGroupList.get(0).getChannels().get(0).getId()
-                        .equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-            // Legacy app using only default channel. Hoist default channel settings to main panel.
-            mShowLegacyChannelConfig = true;
-            mChannel = mChannelGroupList.get(0).getChannels().get(0);
-            populateDefaultChannelPrefs();
-
         } else {
             for (NotificationChannelGroup group : mChannelGroupList) {
                 PreferenceCategory groupCategory = new PreferenceCategory(getPrefContext());
@@ -167,10 +165,11 @@
                     groupCategory.setTitle(mChannelGroupList.size() > 1
                             ? R.string.notification_channels_other
                             : R.string.notification_channels);
+                    groupCategory.setKey(KEY_GENERAL_CATEGORY);
                 } else {
                     groupCategory.setTitle(group.getName());
+                    groupCategory.setKey(group.getId());
                 }
-                groupCategory.setKey(group.getId());
                 groupCategory.setOrderingAsAdded(true);
                 getPreferenceScreen().addPreference(groupCategory);
                 mChannelGroups.add(groupCategory);
@@ -184,13 +183,6 @@
                 }
             }
 
-            if (mAppRow.settingsIntent != null) {
-                Preference intentPref = new Preference(getPrefContext());
-                intentPref.setIntent(mAppRow.settingsIntent);
-                intentPref.setTitle(mContext.getString(R.string.app_settings_link));
-                getPreferenceScreen().addPreference(intentPref);
-            }
-
             int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid);
             if (deletedChannelCount > 0) {
                 mDeletedChannels = new FooterPreference(getPrefContext());
@@ -198,9 +190,12 @@
                 mDeletedChannels.setTitle(getResources().getQuantityString(
                         R.plurals.deleted_channels, deletedChannelCount, deletedChannelCount));
                 mDeletedChannels.setEnabled(false);
+                mDeletedChannels.setKey(KEY_DELETED);
+                mDeletedChannels.setOrder(ORDER_LAST);
                 getPreferenceScreen().addPreference(mDeletedChannels);
             }
         }
+
         updateDependents(mAppRow.banned);
     }
 
@@ -212,7 +207,7 @@
         channelPref.setKey(channel.getId());
         channelPref.setTitle(channel.getName());
         channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
-        channelPref.setSummary(getImportanceSummary(channel.getImportance()));
+        channelPref.setSummary(getImportanceSummary(channel));
         Bundle channelArgs = new Bundle();
         channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
         channelArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
@@ -234,7 +229,7 @@
                         channel.setImportance(importance);
                         channel.lockFields(
                                 NotificationChannel.USER_LOCKED_IMPORTANCE);
-                        channelPref.setSummary(getImportanceSummary(channel.getImportance()));
+                        channelPref.setSummary(getImportanceSummary(channel));
                         mBackend.updateChannel(mPkg, mUid, channel);
 
                         return true;
@@ -243,36 +238,25 @@
         groupCategory.addPreference(channelPref);
     }
 
-    private void populateDefaultChannelPrefs() {
-        addPreferencesFromResource(R.xml.legacy_channel_notification_settings);
-        mPriority = (RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
-        mVisibilityOverride =
-                (RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE);
-        mImportanceToggle = (RestrictedSwitchPreference) findPreference(KEY_IMPORTANCE);
-
-        if (mPkgInfo != null && mChannel != null) {
-            setupPriorityPref(mChannel.canBypassDnd());
-            setupVisOverridePref(mChannel.getLockscreenVisibility());
-            setupImportanceToggle();
+    void setupBadge() {
+        mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE);
+        mBadge.setDisabledByAdmin(mSuspendedAppsAdmin);
+        if (mChannel == null) {
+            mBadge.setChecked(mAppRow.showBadge);
+        } else {
+            mBadge.setChecked(mChannel.canShowBadge());
         }
-        mSwitchBar.setChecked(!mAppRow.banned
-                && mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
-    }
-
-    // 'allow sound'
-    private void setupImportanceToggle() {
-        mImportanceToggle.setDisabledByAdmin(mSuspendedAppsAdmin);
-        mImportanceToggle.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT
-                || mChannel.getImportance() == IMPORTANCE_UNSPECIFIED);
-        mImportanceToggle.setOnPreferenceChangeListener(
-                new Preference.OnPreferenceChangeListener() {
+        mBadge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
             @Override
             public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final int importance =
-                        ((Boolean) newValue ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_LOW);
-                mChannel.setImportance(importance);
-                mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
-                mBackend.updateChannel(mPkg, mUid, mChannel);
+                final boolean value = (Boolean) newValue;
+                if (mChannel == null) {
+                    mBackend.setShowBadge(mPkg, mUid, value);
+                } else {
+                    mChannel.setShowBadge(value);
+                    mChannel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
+                    mBackend.updateChannel(mPkg, mUid, mChannel);
+                }
                 return true;
             }
         });
@@ -296,12 +280,13 @@
                     mBackend.updateChannel(mPkg, mUid, mChannel);
                 }
                 mBackend.setNotificationsEnabledForPackage(mPkgInfo.packageName, mUid, isChecked);
+                mAppRow.banned = true;
                 updateDependents(!isChecked);
             }
         });
 
         mBlockBar = new LayoutPreference(getPrefContext(), switchBarContainer);
-        mBlockBar.setOrder(-500);
+        mBlockBar.setOrder(ORDER_FIRST);
         mBlockBar.setKey(KEY_BLOCK);
         getPreferenceScreen().addPreference(mBlockBar);
 
@@ -312,20 +297,7 @@
         setupBlockDesc(R.string.app_notifications_off_desc);
     }
 
-    private void setupBadge() {
-        mBadge.setDisabledByAdmin(mSuspendedAppsAdmin);
-        mBadge.setChecked(mAppRow.showBadge);
-        mBadge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final boolean value = (Boolean) newValue;
-                mBackend.setShowBadge(mPkg, mUid, value);
-                return true;
-            }
-        });
-    }
-
-    private void updateDependents(boolean banned) {
+    protected void updateDependents(boolean banned) {
         for (PreferenceCategory category : mChannelGroups) {
             setVisible(category, !banned);
         }
@@ -336,17 +308,42 @@
         setVisible(mBadge, !banned);
         if (mShowLegacyChannelConfig) {
             setVisible(mImportanceToggle, !banned);
-            setVisible(mPriority, !banned);
-            setVisible(mVisibilityOverride, !banned);
+            setVisible(mPriority, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
+                    || (checkCanBeVisible(NotificationManager.IMPORTANCE_LOW)
+                    && mDndVisualEffectsSuppressed));
+            setVisible(mVisibilityOverride, !banned &&
+                    checkCanBeVisible(NotificationManager.IMPORTANCE_LOW) && isLockScreenSecure());
+        }
+        if (mAppLink != null) {
+            setVisible(mAppLink, !banned);
         }
         if (mAppRow.systemApp && !mAppRow.banned) {
             setVisible(mBlockBar, false);
         }
     }
 
+    private String getImportanceSummary(NotificationChannel channel) {
+        switch (channel.getImportance()) {
+            case NotificationManager.IMPORTANCE_UNSPECIFIED:
+                return getContext().getString(R.string.notification_importance_unspecified);
+            case NotificationManager.IMPORTANCE_NONE:
+                return getContext().getString(R.string.notification_toggle_off);
+            case NotificationManager.IMPORTANCE_MIN:
+                return getContext().getString(R.string.notification_importance_min_title);
+            case NotificationManager.IMPORTANCE_LOW:
+                return getContext().getString(R.string.notification_importance_low_title);
+            case NotificationManager.IMPORTANCE_DEFAULT:
+                return getContext().getString(R.string.notification_importance_default_title);
+            case NotificationManager.IMPORTANCE_HIGH:
+            case NotificationManager.IMPORTANCE_MAX:
+            default:
+                return getContext().getString(R.string.notification_importance_high_title);
+        }
+
+    }
+
     private Comparator<NotificationChannel> mChannelComparator =
             new Comparator<NotificationChannel>() {
-        private final Collator sCollator = Collator.getInstance();
 
         @Override
         public int compare(NotificationChannel left, NotificationChannel right) {
@@ -359,7 +356,6 @@
 
     private Comparator<NotificationChannelGroup> mChannelGroupComparator =
             new Comparator<NotificationChannelGroup>() {
-                private final Collator sCollator = Collator.getInstance();
 
                 @Override
                 public int compare(NotificationChannelGroup left, NotificationChannelGroup right) {
diff --git a/src/com/android/settings/notification/BadgingNotificationPreferenceController.java b/src/com/android/settings/notification/BadgingNotificationPreferenceController.java
new file mode 100644
index 0000000..225ede5
--- /dev/null
+++ b/src/com/android/settings/notification/BadgingNotificationPreferenceController.java
@@ -0,0 +1,126 @@
+/*
+ * 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.notification;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+import android.util.Log;
+
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
+
+import static android.provider.Settings.Secure.NOTIFICATION_BADGING;
+
+public class BadgingNotificationPreferenceController extends PreferenceController implements
+        Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
+
+    private static final String TAG = "BadgeNotifPrefContr";
+    private static final String KEY_NOTIFICATION_BADGING = "notification_badging";
+    private static final int DEFAULT_VALUE = 1;
+
+    private SettingObserver mSettingObserver;
+
+    public BadgingNotificationPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        Preference preference = screen.findPreference(NOTIFICATION_BADGING);
+        if (preference != null) {
+            mSettingObserver = new SettingObserver(preference);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        if (mSettingObserver != null) {
+            mSettingObserver.register(mContext.getContentResolver(), true /* register */);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mSettingObserver != null) {
+            mSettingObserver.register(mContext.getContentResolver(), false /* register */);
+        }
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_NOTIFICATION_BADGING;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mContext.getResources()
+                .getBoolean(com.android.internal.R.bool.config_notificationBadging);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final boolean checked = Settings.Secure.getInt(mContext.getContentResolver(),
+                NOTIFICATION_BADGING, DEFAULT_VALUE) == 1;
+        ((TwoStatePreference) preference).setChecked(checked);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean val = (Boolean) newValue;
+        return Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_BADGING, val ? 1 : 0);
+    }
+
+    class SettingObserver extends ContentObserver {
+
+        private final Uri NOTIFICATION_BADGING_URI =
+                Settings.Secure.getUriFor(NOTIFICATION_BADGING);
+
+        private final Preference mPreference;
+
+        public SettingObserver(Preference preference) {
+            super(new Handler());
+            mPreference = preference;
+        }
+
+        public void register(ContentResolver cr, boolean register) {
+            if (register) {
+                cr.registerContentObserver(NOTIFICATION_BADGING_URI, false, this);
+            } else {
+                cr.unregisterContentObserver(this);
+            }
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            super.onChange(selfChange, uri);
+            if (NOTIFICATION_BADGING_URI.equals(uri)) {
+                updateState(mPreference);
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/notification/ChannelImportanceSettings.java b/src/com/android/settings/notification/ChannelImportanceSettings.java
index b396b20..26dd57f 100644
--- a/src/com/android/settings/notification/ChannelImportanceSettings.java
+++ b/src/com/android/settings/notification/ChannelImportanceSettings.java
@@ -67,6 +67,12 @@
     }
 
     @Override
+    void setupBadge() {}
+
+    @Override
+    void updateDependents(boolean banned) {}
+
+    @Override
     public void onPause() {
         super.onPause();
     }
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index 0fb42d2..27e60c7 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -18,6 +18,7 @@
 
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
 import android.app.Activity;
 import android.app.NotificationChannel;
@@ -53,16 +54,16 @@
 public class ChannelNotificationSettings extends NotificationSettingsBase {
     private static final String TAG = "ChannelSettings";
 
-    protected static final String KEY_LIGHTS = "lights";
-    protected static final String KEY_VIBRATE = "vibrate";
-    protected static final String KEY_RINGTONE = "ringtone";
+    private static final String KEY_LIGHTS = "lights";
+    private static final String KEY_VIBRATE = "vibrate";
+    private static final String KEY_RINGTONE = "ringtone";
+    private static final String KEY_IMPORTANCE = "importance";
 
-    protected Preference mImportance;
-    protected RestrictedSwitchPreference mLights;
-    protected RestrictedSwitchPreference mVibrate;
-    protected NotificationSoundPreference mRingtone;
-
-    protected LayoutPreference mBlockBar;
+    private Preference mImportance;
+    private RestrictedSwitchPreference mLights;
+    private RestrictedSwitchPreference mVibrate;
+    private NotificationSoundPreference mRingtone;
+    private FooterPreference mFooter;
 
     @Override
     public int getMetricsCategory() {
@@ -81,34 +82,37 @@
         if (getPreferenceScreen() != null) {
             getPreferenceScreen().removeAll();
         }
-        addPreferencesFromResource(R.xml.channel_notification_settings);
+        addPreferencesFromResource(R.xml.notification_settings);
+        setupBlock();
+        addHeaderPref();
+        addAppLinkPref();
+        addFooterPref();
 
-        // load settings intent
-        ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<String, NotificationBackend.AppRow>();
-        rows.put(mAppRow.pkg, mAppRow);
-        collectConfigActivities(rows);
+        if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
+            populateDefaultChannelPrefs();
+            mShowLegacyChannelConfig = true;
+        } else {
+            populateUpgradedChannelPrefs();
+        }
 
-        mBlockedDesc = (FooterPreference) getPreferenceScreen().findPreference(KEY_BLOCKED_DESC);
-        mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE);
-        mImportance = findPreference(KEY_IMPORTANCE);
-        mPriority = (RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
-        mVisibilityOverride =
-                (RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE);
-        mLights = (RestrictedSwitchPreference) findPreference(KEY_LIGHTS);
-        mVibrate = (RestrictedSwitchPreference) findPreference(KEY_VIBRATE);
-        mRingtone = (NotificationSoundPreference) findPreference(KEY_RINGTONE);
+        updateDependents(mChannel.getImportance() == IMPORTANCE_NONE);
+    }
 
-
+    private void populateUpgradedChannelPrefs() {
+        addPreferencesFromResource(R.xml.upgraded_channel_notification_settings);
+        setupBadge();
         setupPriorityPref(mChannel.canBypassDnd());
         setupVisOverridePref(mChannel.getLockscreenVisibility());
         setupLights();
         setupVibrate();
         setupRingtone();
-        setupBadge();
-        setupBlock();
         setupImportance();
-        updateDependents();
+    }
 
+    private void addHeaderPref() {
+        ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<String, NotificationBackend.AppRow>();
+        rows.put(mAppRow.pkg, mAppRow);
+        collectConfigActivities(rows);
         final Activity activity = getActivity();
         final Preference pref = FeatureFactory.getFactory(activity)
                 .getApplicationFeatureProvider(activity)
@@ -122,25 +126,38 @@
                         AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
                 .done(activity, getPrefContext());
         getPreferenceScreen().addPreference(pref);
+    }
 
-        if (mAppRow.settingsIntent != null) {
-            Preference intentPref = new Preference(getPrefContext());
-            intentPref.setIntent(mAppRow.settingsIntent);
-            intentPref.setTitle(mContext.getString(R.string.app_settings_link));
-            getPreferenceScreen().addPreference(intentPref);
-        }
-
+    private void addFooterPref() {
         if (!TextUtils.isEmpty(mChannel.getDescription())) {
             FooterPreference descPref = new FooterPreference(getPrefContext());
+            descPref.setOrder(ORDER_LAST);
             descPref.setSelectable(false);
-            descPref.setSummary(mChannel.getDescription());
-            descPref.setEnabled(false);
+            descPref.setTitle(mChannel.getDescription());
             getPreferenceScreen().addPreference(descPref);
         }
+    }
 
+    protected void setupBadge() {
+        mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE);
+        mBadge.setDisabledByAdmin(mSuspendedAppsAdmin);
+        mBadge.setEnabled(mAppRow.showBadge);
+        mBadge.setChecked(mChannel.canShowBadge());
+
+        mBadge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+            @Override
+            public boolean onPreferenceChange(Preference preference, Object newValue) {
+                final boolean value = (Boolean) newValue;
+                mChannel.setShowBadge(value);
+                mChannel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
+                mBackend.updateChannel(mPkg, mUid, mChannel);
+                return true;
+            }
+        });
     }
 
     private void setupLights() {
+        mLights = (RestrictedSwitchPreference) findPreference(KEY_LIGHTS);
         mLights.setDisabledByAdmin(mSuspendedAppsAdmin);
         mLights.setChecked(mChannel.shouldShowLights());
         mLights.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@@ -156,6 +173,7 @@
     }
 
     private void setupVibrate() {
+        mVibrate = (RestrictedSwitchPreference) findPreference(KEY_VIBRATE);
         mVibrate.setDisabledByAdmin(mSuspendedAppsAdmin);
         mVibrate.setChecked(mChannel.shouldVibrate());
         mVibrate.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@@ -171,6 +189,7 @@
     }
 
     private void setupRingtone() {
+        mRingtone = (NotificationSoundPreference) findPreference(KEY_RINGTONE);
         mRingtone.setRingtone(mChannel.getSound());
         mRingtone.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
             @Override
@@ -183,27 +202,33 @@
         });
     }
 
-    protected void setupBlock() {
+    private void setupBlock() {
         View switchBarContainer = LayoutInflater.from(
                 getPrefContext()).inflate(R.layout.styled_switch_bar, null);
-        SwitchBar switchBar = switchBarContainer.findViewById(R.id.switch_bar);
-        switchBar.show();
-        switchBar.setDisabledByAdmin(mSuspendedAppsAdmin);
-        switchBar.setChecked(mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
-        switchBar.addOnSwitchChangeListener(new SwitchBar.OnSwitchChangeListener() {
+        mSwitchBar = switchBarContainer.findViewById(R.id.switch_bar);
+        mSwitchBar.show();
+        mSwitchBar.setDisabledByAdmin(mSuspendedAppsAdmin);
+        mSwitchBar.setChecked(mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
+        mSwitchBar.addOnSwitchChangeListener(new SwitchBar.OnSwitchChangeListener() {
             @Override
             public void onSwitchChanged(Switch switchView, boolean isChecked) {
-                int importance = isChecked ? IMPORTANCE_LOW : IMPORTANCE_NONE;
-                mImportance.setSummary(getImportanceSummary(importance));
+                int importance = 0;
+                if (mShowLegacyChannelConfig) {
+                    importance = isChecked ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_NONE;
+                    mImportanceToggle.setChecked(importance == IMPORTANCE_UNSPECIFIED);
+                } else {
+                    importance = isChecked ? IMPORTANCE_LOW : IMPORTANCE_NONE;
+                    mImportance.setSummary(getImportanceSummary(importance));
+                }
                 mChannel.setImportance(importance);
                 mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
                 mBackend.updateChannel(mPkg, mUid, mChannel);
-                updateDependents();
+                updateDependents(mChannel.getImportance() == IMPORTANCE_NONE);
             }
         });
 
         mBlockBar = new LayoutPreference(getPrefContext(), switchBarContainer);
-        mBlockBar.setOrder(-500);
+        mBlockBar.setOrder(ORDER_FIRST);
         mBlockBar.setKey(KEY_BLOCK);
         getPreferenceScreen().addPreference(mBlockBar);
 
@@ -214,23 +239,8 @@
         setupBlockDesc(R.string.channel_notifications_off_desc);
     }
 
-    protected void setupBadge() {
-        mBadge.setDisabledByAdmin(mSuspendedAppsAdmin);
-        mBadge.setEnabled(mAppRow.showBadge);
-        mBadge.setChecked(mChannel.canShowBadge());
-        mBadge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                final boolean value = (Boolean) newValue;
-                mChannel.setShowBadge(value);
-                mChannel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
-                mBackend.updateChannel(mPkg, mUid, mChannel);
-                return true;
-            }
-        });
-    }
-
-    protected void setupImportance() {
+    private void setupImportance() {
+        mImportance = findPreference(KEY_IMPORTANCE);
         Bundle channelArgs = new Bundle();
         channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
         channelArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
@@ -245,23 +255,43 @@
         mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
     }
 
-    private boolean isLockScreenSecure() {
-        LockPatternUtils utils = new LockPatternUtils(getActivity());
-        boolean lockscreenSecure = utils.isSecure(UserHandle.myUserId());
-        UserInfo parentUser = mUm.getProfileParent(UserHandle.myUserId());
-        if (parentUser != null){
-            lockscreenSecure |= utils.isSecure(parentUser.id);
+    private String getImportanceSummary(int importance) {
+        String title;
+        String summary = null;
+        switch (importance) {
+            case IMPORTANCE_UNSPECIFIED:
+                title = getContext().getString(R.string.notification_importance_unspecified);
+                break;
+            case NotificationManager.IMPORTANCE_MIN:
+                title = getContext().getString(R.string.notification_importance_min_title);
+                summary = getContext().getString(R.string.notification_importance_min);
+                break;
+            case NotificationManager.IMPORTANCE_LOW:
+                title = getContext().getString(R.string.notification_importance_low_title);
+                summary = getContext().getString(R.string.notification_importance_low);
+                break;
+            case NotificationManager.IMPORTANCE_DEFAULT:
+                title = getContext().getString(R.string.notification_importance_default_title);
+                if (hasValidSound()) {
+                    summary = getContext().getString(R.string.notification_importance_default);
+                }
+                break;
+            case NotificationManager.IMPORTANCE_HIGH:
+            case NotificationManager.IMPORTANCE_MAX:
+                title = getContext().getString(R.string.notification_importance_high_title);
+                if (hasValidSound()) {
+                    summary = getContext().getString(R.string.notification_importance_high);
+                }
+                break;
+            default:
+                return "";
         }
 
-        return lockscreenSecure;
-    }
-
-    protected boolean checkCanBeVisible(int minImportanceVisible) {
-        int importance = mChannel.getImportance();
-        if (importance == NotificationManager.IMPORTANCE_UNSPECIFIED) {
-            return true;
+        if (summary != null) {
+            return getContext().getString(R.string.notification_importance_divider, title, summary);
+        } else {
+            return title;
         }
-        return importance >= minImportanceVisible;
     }
 
     @Override
@@ -279,9 +309,10 @@
         if (mRingtone != null) {
             mRingtone.onActivityResult(requestCode, resultCode, data);
         }
+        mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
     }
 
-    private boolean canPulseLight() {
+    boolean canPulseLight() {
         if (!getResources()
                 .getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)) {
             return false;
@@ -290,18 +321,32 @@
                 Settings.System.NOTIFICATION_LIGHT_PULSE, 0) == 1;
     }
 
-    private void updateDependents() {
-        setVisible(mBlockedDesc, mChannel.getImportance() == IMPORTANCE_NONE);
+    boolean hasValidSound() {
+        return mChannel.getSound() != null && !Uri.EMPTY.equals(mChannel.getSound());
+    }
+
+    void updateDependents(boolean banned) {
+        if (mShowLegacyChannelConfig) {
+            setVisible(mImportanceToggle, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
+        } else {
+            setVisible(mImportance, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
+            setVisible(mLights, checkCanBeVisible(
+                    NotificationManager.IMPORTANCE_DEFAULT) && canPulseLight());
+            setVisible(mVibrate, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT));
+            setVisible(mRingtone, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT));
+        }
         setVisible(mBadge, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
-        setVisible(mImportance, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
-        setVisible(mLights, checkCanBeVisible(
-                NotificationManager.IMPORTANCE_LOW) && canPulseLight());
-        setVisible(mVibrate, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT));
-        setVisible(mRingtone, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT));
         setVisible(mPriority, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
                 || (checkCanBeVisible(NotificationManager.IMPORTANCE_LOW)
-                        && mDndVisualEffectsSuppressed));
-        setVisible(mVisibilityOverride, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN)
+                && mDndVisualEffectsSuppressed));
+        setVisible(mVisibilityOverride, checkCanBeVisible(NotificationManager.IMPORTANCE_LOW)
                 && isLockScreenSecure());
+        setVisible(mBlockedDesc, mChannel.getImportance() == IMPORTANCE_NONE);
+        if (mAppLink != null) {
+            setVisible(mAppLink, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
+        }
+        if (mFooter !=null) {
+            setVisible(mFooter, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
+        }
     }
 }
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index b591d85..a1c5263 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -58,6 +58,8 @@
     private static List<PreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle) {
         final List<PreferenceController> controllers = new ArrayList<>();
+        final BadgingNotificationPreferenceController badgeController =
+                new BadgingNotificationPreferenceController(context);
         final PulseNotificationPreferenceController pulseController =
                 new PulseNotificationPreferenceController(context);
         final LockScreenNotificationPreferenceController lockScreenNotificationController =
@@ -67,6 +69,7 @@
             lifecycle.addObserver(lockScreenNotificationController);
         }
         controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle));
+        controllers.add(badgeController);
         controllers.add(pulseController);
         controllers.add(lockScreenNotificationController);
         return controllers;
diff --git a/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java b/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
index 547ff80..73469b0 100644
--- a/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
+++ b/src/com/android/settings/notification/LockScreenNotificationPreferenceController.java
@@ -281,6 +281,7 @@
             return;
         }
         mLockscreenSelectedValue = getSummaryResource();
+        mLockscreen.setSummary("%s");
         mLockscreen.setValue(Integer.toString(mLockscreenSelectedValue));
     }
 
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index 6226eac..84d7e31 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -148,6 +148,15 @@
         }
     }
 
+    public boolean onlyHasDefaultChannel(String pkg, int uid) {
+        try {
+            return sINM.onlyHasDefaultChannel(pkg, uid);
+        } catch (Exception e) {
+            Log.w(TAG, "Error calling NoMan", e);
+            return false;
+        }
+    }
+
     static class Row {
         public String section;
     }
diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java
index c08f161..695c796 100644
--- a/src/com/android/settings/notification/NotificationSettingsBase.java
+++ b/src/com/android/settings/notification/NotificationSettingsBase.java
@@ -16,10 +16,18 @@
 
 package com.android.settings.notification;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+
+import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.applications.AppInfoBase;
+import com.android.settings.applications.LayoutPreference;
 import com.android.settings.widget.FooterPreference;
+import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedSwitchPreference;
 
@@ -35,6 +43,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -60,16 +69,23 @@
             = new Intent(Intent.ACTION_MAIN)
             .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES);
 
+    protected static final int ORDER_FIRST = -500;
+    protected static final int ORDER_LAST = 1000;
+
+    protected static final String KEY_APP_LINK = "app_link";
+    protected static final String KEY_HEADER = "header";
     protected static final String KEY_BLOCK = "block";
     protected static final String KEY_BADGE = "badge";
     protected static final String KEY_BYPASS_DND = "bypass_dnd";
     protected static final String KEY_VISIBILITY_OVERRIDE = "visibility_override";
-    protected static final String KEY_IMPORTANCE = "importance";
     protected static final String KEY_BLOCKED_DESC = "block_desc";
+    protected static final String KEY_ALLOW_SOUND = "allow_sound";
 
     protected PackageManager mPm;
     protected UserManager mUm;
-    protected final NotificationBackend mBackend = new NotificationBackend();
+    protected NotificationBackend mBackend = new NotificationBackend();
+    protected LockPatternUtils mLockPatternUtils;
+    protected NotificationManager mNm;
     protected Context mContext;
     protected boolean mCreated;
     protected int mUid;
@@ -79,13 +95,18 @@
     protected RestrictedSwitchPreference mBadge;
     protected RestrictedSwitchPreference mPriority;
     protected RestrictedDropDownPreference mVisibilityOverride;
+    protected RestrictedSwitchPreference mImportanceToggle;
+    protected LayoutPreference mBlockBar;
+    protected SwitchBar mSwitchBar;
     protected FooterPreference mBlockedDesc;
+    protected Preference mAppLink;
 
     protected EnforcedAdmin mSuspendedAppsAdmin;
     protected boolean mDndVisualEffectsSuppressed;
 
     protected NotificationChannel mChannel;
     protected NotificationBackend.AppRow mAppRow;
+    protected boolean mShowLegacyChannelConfig = false;
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
@@ -113,6 +134,7 @@
 
         mPm = getPackageManager();
         mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mNm = NotificationManager.from(mContext);
 
         mPkg = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_NAME)
                 ? args.getString(AppInfoBase.ARG_PACKAGE_NAME)
@@ -154,8 +176,7 @@
 
         mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
                 mContext, mPkg, mUserId);
-        NotificationManager.Policy policy =
-                NotificationManager.from(mContext).getNotificationPolicy();
+        NotificationManager.Policy policy = mNm.getNotificationPolicy();
         mDndVisualEffectsSuppressed = policy == null ? false : policy.suppressedVisualEffects != 0;
 
         mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
@@ -241,26 +262,56 @@
         return null;
     }
 
-    protected String getImportanceSummary(int importance) {
-        switch (importance) {
-            case NotificationManager.IMPORTANCE_UNSPECIFIED:
-                return getContext().getString(R.string.notification_importance_unspecified);
-            case NotificationManager.IMPORTANCE_NONE:
-                return getContext().getString(R.string.notification_importance_blocked);
-            case NotificationManager.IMPORTANCE_MIN:
-                return getContext().getString(R.string.notification_importance_min);
-            case NotificationManager.IMPORTANCE_LOW:
-                return getContext().getString(R.string.notification_importance_low);
-            case NotificationManager.IMPORTANCE_DEFAULT:
-                return getContext().getString(R.string.notification_importance_default);
-            case NotificationManager.IMPORTANCE_HIGH:
-            case NotificationManager.IMPORTANCE_MAX:
-            default:
-                return getContext().getString(R.string.notification_importance_high);
+    protected void addAppLinkPref() {
+        if (mAppRow.settingsIntent != null) {
+            mAppLink = new Preference(getPrefContext());
+            mAppLink.setKey(KEY_APP_LINK);
+            mAppLink.setOrder(500);
+            mAppLink.setIntent(mAppRow.settingsIntent);
+            mAppLink.setTitle(mContext.getString(R.string.app_settings_link));
+            getPreferenceScreen().addPreference(mAppLink);
         }
     }
 
+    protected void populateDefaultChannelPrefs() {
+        if (mPkgInfo != null && mChannel != null) {
+            addPreferencesFromResource(R.xml.legacy_channel_notification_settings);
+            setupPriorityPref(mChannel.canBypassDnd());
+            setupVisOverridePref(mChannel.getLockscreenVisibility());
+            setupImportanceToggle();
+            setupBadge();
+        }
+        mSwitchBar.setChecked(!mAppRow.banned
+                && mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
+    }
+
+    abstract void setupBadge();
+
+    abstract void updateDependents(boolean banned);
+
+    // 'allow sound'
+    private void setupImportanceToggle() {
+        mImportanceToggle = (RestrictedSwitchPreference) findPreference(KEY_ALLOW_SOUND);
+        mImportanceToggle.setDisabledByAdmin(mSuspendedAppsAdmin);
+        mImportanceToggle.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT
+                || mChannel.getImportance() == IMPORTANCE_UNSPECIFIED);
+        mImportanceToggle.setOnPreferenceChangeListener(
+                new Preference.OnPreferenceChangeListener() {
+                    @Override
+                    public boolean onPreferenceChange(Preference preference, Object newValue) {
+                        final int importance =
+                                ((Boolean) newValue ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_LOW);
+                        mChannel.setImportance(importance);
+                        mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+                        mBackend.updateChannel(mPkg, mUid, mChannel);
+                        updateDependents(mChannel.getImportance() == IMPORTANCE_NONE);
+                        return true;
+                    }
+                });
+    }
+
     protected void setupPriorityPref(boolean priority) {
+        mPriority = (RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
         mPriority.setDisabledByAdmin(mSuspendedAppsAdmin);
         mPriority.setChecked(priority);
         mPriority.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@@ -276,6 +327,8 @@
     }
 
     protected void setupVisOverridePref(int sensitive) {
+        mVisibilityOverride =
+                (RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE);
         ArrayList<CharSequence> entries = new ArrayList<>();
         ArrayList<CharSequence> values = new ArrayList<>();
 
@@ -328,6 +381,8 @@
     }
 
     protected void setupBlockDesc(int summaryResId) {
+        mBlockedDesc = (FooterPreference) getPreferenceScreen().findPreference(
+                KEY_BLOCKED_DESC);
         mBlockedDesc = new FooterPreference(getPrefContext());
         mBlockedDesc.setSelectable(false);
         mBlockedDesc.setTitle(summaryResId);
@@ -336,6 +391,13 @@
         getPreferenceScreen().addPreference(mBlockedDesc);
     }
 
+    protected boolean checkCanBeVisible(int minImportanceVisible) {
+        int importance = mChannel.getImportance();
+        if (importance == NotificationManager.IMPORTANCE_UNSPECIFIED) {
+            return true;
+        }
+        return importance >= minImportanceVisible;
+    }
 
     private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
             CharSequence entryValue, int keyguardNotificationFeatures) {
@@ -359,7 +421,6 @@
         return globalVis;
     }
 
-
     private boolean getLockscreenNotificationsEnabled() {
         return Settings.Secure.getInt(getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
@@ -369,4 +430,17 @@
         return Settings.Secure.getInt(getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
     }
+
+    protected boolean isLockScreenSecure() {
+        if (mLockPatternUtils == null) {
+            mLockPatternUtils = new LockPatternUtils(getActivity());
+        }
+        boolean lockscreenSecure = mLockPatternUtils.isSecure(UserHandle.myUserId());
+        UserInfo parentUser = mUm.getProfileParent(UserHandle.myUserId());
+        if (parentUser != null){
+            lockscreenSecure |= mLockPatternUtils.isSecure(parentUser.id);
+        }
+
+        return lockscreenSecure;
+    }
 }
diff --git a/src/com/android/settings/password/FingerprintManagerWrapper.java b/src/com/android/settings/password/FingerprintManagerWrapper.java
index b00f786..51b31af 100644
--- a/src/com/android/settings/password/FingerprintManagerWrapper.java
+++ b/src/com/android/settings/password/FingerprintManagerWrapper.java
@@ -18,6 +18,8 @@
 
 import android.annotation.NonNull;
 import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
+import android.os.CancellationSignal;
 
 import com.android.internal.util.Preconditions;
 
@@ -33,15 +35,33 @@
         mFingerprintManager = fingerprintManager;
     }
 
+    @Override
     public boolean isHardwareDetected() {
         return mFingerprintManager.isHardwareDetected();
     }
 
+    @Override
     public boolean hasEnrolledFingerprints(int userId) {
         return mFingerprintManager.hasEnrolledFingerprints(userId);
     }
 
+    @Override
     public long preEnroll() {
         return mFingerprintManager.preEnroll();
     }
+
+    @Override
+    public void setActiveUser(int userId) {
+        mFingerprintManager.setActiveUser(userId);
+    }
+
+    @Override
+    public void enroll(
+            byte[] token,
+            CancellationSignal cancel,
+            int flags,
+            int userId,
+            EnrollmentCallback callback) {
+        mFingerprintManager.enroll(token, cancel, flags, userId, callback);
+    }
 }
diff --git a/src/com/android/settings/password/IFingerprintManager.java b/src/com/android/settings/password/IFingerprintManager.java
index 15a9242..9402146 100644
--- a/src/com/android/settings/password/IFingerprintManager.java
+++ b/src/com/android/settings/password/IFingerprintManager.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.password;
 
+import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
+import android.os.CancellationSignal;
+
 /**
  * This is the workaround to allow us test {@link SetNewPasswordController} which uses a new hidden
  * API {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints(int)} that
@@ -28,4 +31,9 @@
     boolean hasEnrolledFingerprints(int userId);
 
     long preEnroll();
+
+    void setActiveUser(int userId);
+
+    void enroll(byte [] token, CancellationSignal cancel, int flags,
+            int userId, EnrollmentCallback callback);
 }
diff --git a/src/com/android/settings/search2/SearchFragment.java b/src/com/android/settings/search2/SearchFragment.java
index 5ee22b5..2a5c961 100644
--- a/src/com/android/settings/search2/SearchFragment.java
+++ b/src/com/android/settings/search2/SearchFragment.java
@@ -291,6 +291,9 @@
      */
     @Override
     public void onIndexingFinished() {
+        if (getActivity() == null) {
+            return;
+        }
         if (mShowingSavedQuery) {
             mSavedQueryController.loadSavedQueries();
         } else {
diff --git a/src/com/android/settings/utils/NotificationChannelHelper.java b/src/com/android/settings/utils/NotificationChannelHelper.java
deleted file mode 100644
index bf008dc..0000000
--- a/src/com/android/settings/utils/NotificationChannelHelper.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.utils;
-
-import android.app.INotificationManager;
-import android.app.NotificationChannel;
-import android.os.RemoteException;
-
-/**
- * Wrappers around methods in {@link INotificationManager} and {@link NotificationChannel} to
- * facilitate unit testing.
- *
- * TODO: delete this class once robolectric supports Android O
- */
-public class NotificationChannelHelper {
-    private INotificationManager mNotificationManager;
-
-    public NotificationChannelHelper(
-            INotificationManager notificationManager) {
-        mNotificationManager = notificationManager;
-    }
-
-    /**
-     * Returns the notification channel settings for a app given its package name, user id, and
-     * channel id.
-     */
-    public NotificationChannelWrapper getNotificationChannelForPackage(String pkg, int uid,
-            String channelId, boolean includeDeleted) throws RemoteException {
-        NotificationChannel channel = mNotificationManager.getNotificationChannelForPackage(
-                pkg, uid, channelId, includeDeleted);
-        return channel == null ? null : new NotificationChannelWrapper(channel);
-    }
-
-    /**
-     * Wrapper around {@link NotificationChannel} to facilitate unit testing.
-     *
-     * TODO: delete this class once robolectric supports Android O
-     */
-    public class NotificationChannelWrapper {
-        private NotificationChannel mChannel;
-
-        public NotificationChannelWrapper(NotificationChannel channel) {
-            mChannel = channel;
-        }
-
-        public int getImportance() {
-            return mChannel.getImportance();
-        }
-    }
-}
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index 24d62ad..af80fd4 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -15,13 +15,15 @@
  */
 package com.android.settings.wifi;
 
-import android.app.INotificationManager;
+import static android.content.Context.NETWORK_SCORE_SERVICE;
+import static android.content.Context.WIFI_SERVICE;
+
 import android.content.Context;
 import android.content.Intent;
 import android.net.NetworkScoreManager;
 import android.net.wifi.WifiManager;
-import android.os.ServiceManager;
 import android.provider.SearchIndexableResource;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
@@ -32,7 +34,6 @@
 import com.android.settings.network.WifiCallingPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.utils.NotificationChannelHelper;
 import com.android.settings.wifi.p2p.WifiP2pPreferenceController;
 
 import java.util.ArrayList;
@@ -72,18 +73,14 @@
     protected List<PreferenceController> getPreferenceControllers(Context context) {
         final NetworkScoreManagerWrapper networkScoreManagerWrapper =
                 new NetworkScoreManagerWrapper(context.getSystemService(NetworkScoreManager.class));
-        final NotificationChannelHelper notificationChannelHelper =
-                new NotificationChannelHelper(INotificationManager.Stub.asInterface(
-                        ServiceManager.getService(Context.NOTIFICATION_SERVICE)));
-        final WifiManager wifiManager = context.getSystemService(WifiManager.class);
         mUseOpenWifiPreferenceController = new UseOpenWifiPreferenceController(context, this,
                 networkScoreManagerWrapper, getLifecycle());
+        final WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
         final List<PreferenceController> controllers = new ArrayList<>();
         controllers.add(new WifiWakeupPreferenceController(context, getLifecycle()));
         controllers.add(new NetworkScorerPickerPreferenceController(context,
                 networkScoreManagerWrapper));
-        controllers.add(new NotifyOpenNetworksPreferenceController(context,
-                networkScoreManagerWrapper, notificationChannelHelper, getPackageManager()));
+        controllers.add(new NotifyOpenNetworksPreferenceController(context, getLifecycle()));
         controllers.add(mUseOpenWifiPreferenceController);
         controllers.add(new WifiSleepPolicyPreferenceController(context));
         controllers.add(new WifiInfoPreferenceController(context, getLifecycle(), wifiManager));
diff --git a/src/com/android/settings/wifi/NotifyOpenNetworksPreferenceController.java b/src/com/android/settings/wifi/NotifyOpenNetworksPreferenceController.java
index a85a266..6e88d79 100644
--- a/src/com/android/settings/wifi/NotifyOpenNetworksPreferenceController.java
+++ b/src/com/android/settings/wifi/NotifyOpenNetworksPreferenceController.java
@@ -16,46 +16,75 @@
 
 package com.android.settings.wifi;
 
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
+import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.NetworkScorerAppData;
-import android.os.RemoteException;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
 import android.provider.Settings;
-import android.support.annotation.Nullable;
+import android.support.v14.preference.SwitchPreference;
 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.core.PreferenceController;
-import com.android.settings.network.NetworkScoreManagerWrapper;
-import com.android.settings.utils.NotificationChannelHelper;
-import com.android.settings.utils.NotificationChannelHelper.NotificationChannelWrapper;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
 
 /**
- * {@link PreferenceController} that shows whether we should notify user when open network is
- * available. The preference links to {@link NotificationChannel} settings.
+ * {@link PreferenceController} that controls whether we should notify user when open network is
+ * available.
  */
-public class NotifyOpenNetworksPreferenceController extends PreferenceController {
+public class NotifyOpenNetworksPreferenceController extends PreferenceController implements
+        LifecycleObserver, OnResume, OnPause {
 
-    private static final String TAG = "OpenNetworks";
     private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks";
+    private SettingObserver mSettingObserver;
 
-    private NetworkScoreManagerWrapper mNetworkScoreManager;
-    private NotificationChannelHelper mNotificationChannelHelper;
-    private PackageManager mPackageManager;
-
-    public NotifyOpenNetworksPreferenceController(
-            Context context,
-            NetworkScoreManagerWrapper networkScoreManager,
-            NotificationChannelHelper notificationChannelHelper,
-            PackageManager packageManager) {
+    public NotifyOpenNetworksPreferenceController(Context context, Lifecycle lifecycle) {
         super(context);
-        mNetworkScoreManager = networkScoreManager;
-        mNotificationChannelHelper = notificationChannelHelper;
-        mPackageManager = packageManager;
+        lifecycle.addObserver(this);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mSettingObserver = new SettingObserver(screen.findPreference(KEY_NOTIFY_OPEN_NETWORKS));
+    }
+
+    @Override
+    public void onResume() {
+        if (mSettingObserver != null) {
+            mSettingObserver.register(mContext.getContentResolver(), true /* register */);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (mSettingObserver != null) {
+            mSettingObserver.register(mContext.getContentResolver(), false /* register */);
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!TextUtils.equals(preference.getKey(), KEY_NOTIFY_OPEN_NETWORKS)) {
+            return false;
+        }
+        if (!(preference instanceof SwitchPreference)) {
+            return false;
+        }
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+                ((SwitchPreference) preference).isChecked() ? 1 : 0);
+        return true;
     }
 
     @Override
@@ -64,59 +93,40 @@
     }
 
     @Override
-    public boolean isAvailable() {
-        return getNotificationChannel() != null;
-    }
-
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        if (!TextUtils.equals(preference.getKey(), KEY_NOTIFY_OPEN_NETWORKS)) {
-            return false;
-        }
-        NetworkScorerAppData scorer = mNetworkScoreManager.getActiveScorer();
-        if (scorer == null) {
-            return false;
-        }
-
-        Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
-        intent.putExtra(Settings.EXTRA_CHANNEL_ID,
-                scorer.getNetworkAvailableNotificationChannelId());
-        intent.putExtra(Settings.EXTRA_APP_PACKAGE, scorer.getRecommendationServicePackageName());
-        mContext.startActivity(intent);
-        return true;
-    }
-
-    @Override
     public void updateState(Preference preference) {
-        NotificationChannelWrapper channel = getNotificationChannel();
-        if (channel == null) {
-            preference.setSummary(null);
-        } else {
-            preference.setSummary(channel.getImportance() != NotificationManager.IMPORTANCE_NONE ?
-                    R.string.notification_toggle_on : R.string.notification_toggle_off);
+        if (!(preference instanceof SwitchPreference)) {
+            return;
         }
+        final SwitchPreference notifyOpenNetworks = (SwitchPreference) preference;
+        notifyOpenNetworks.setChecked(Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
     }
 
-    @Nullable
-    private NotificationChannelWrapper getNotificationChannel() {
-        NetworkScorerAppData scorer = mNetworkScoreManager.getActiveScorer();
-        if (scorer == null) {
-            return null;
+    class SettingObserver extends ContentObserver {
+        private final Uri NETWORKS_AVAILABLE_URI = Settings.Global.getUriFor(
+                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
+
+        private final Preference mPreference;
+
+        public SettingObserver(Preference preference) {
+            super(new Handler());
+            mPreference = preference;
         }
-        String packageName = scorer.getRecommendationServicePackageName();
-        String channelId = scorer.getNetworkAvailableNotificationChannelId();
-        if (packageName == null || channelId == null) {
-            return null;
+
+        public void register(ContentResolver cr, boolean register) {
+            if (register) {
+                cr.registerContentObserver(NETWORKS_AVAILABLE_URI, false, this);
+            } else {
+                cr.unregisterContentObserver(this);
+            }
         }
-        try {
-            return mNotificationChannelHelper.getNotificationChannelForPackage(
-                    packageName,
-                    mPackageManager.getPackageUid(packageName, 0 /* flags */),
-                    channelId,
-                    false /* includeDeleted */ );
-        } catch (RemoteException | PackageManager.NameNotFoundException e) {
-            Log.d(TAG, "Failed to get notification channel.", e);
-            return null;
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            super.onChange(selfChange, uri);
+            if (NETWORKS_AVAILABLE_URI.equals(uri)) {
+                updateState(mPreference);
+            }
         }
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
new file mode 100644
index 0000000..646774d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.fingerprint;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.verify;
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
+import android.os.CancellationSignal;
+import android.widget.Button;
+
+import com.android.settings.ChooseLockSettingsHelper;
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.password.IFingerprintManager;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
+import com.android.settings.testutils.shadow.ShadowEventLogWriter;
+import com.android.settings.testutils.shadow.ShadowUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowActivity.IntentForResult;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+        manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                SettingsShadowResources.class,
+                SettingsShadowResources.SettingsShadowTheme.class,
+                ShadowDynamicIndexableContentMonitor.class,
+                ShadowEventLogWriter.class,
+                ShadowUtils.class
+        })
+public class FingerprintEnrollFindSensorTest {
+
+    @Mock
+    private IFingerprintManager mFingerprintManager;
+
+    private FingerprintEnrollFindSensor mActivity;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowUtils.setFingerprintManager(mFingerprintManager);
+
+        RuntimeEnvironment.getAppResourceLoader().getResourceIndex();
+
+        mActivity = Robolectric.buildActivity(
+                FingerprintEnrollFindSensor.class,
+                new Intent()
+                        // Set the challenge token so the confirm screen will not be shown
+                        .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]))
+                .setup().get();
+    }
+
+    @After
+    public void tearDown() {
+        ShadowUtils.reset();
+    }
+
+    @Test
+    public void clickNextAndFingerprint_shouldNotCrash() {
+        ArgumentCaptor<EnrollmentCallback> callbackCaptor =
+                ArgumentCaptor.forClass(EnrollmentCallback.class);
+        verify(mFingerprintManager).enroll(
+                any(byte[].class),
+                any(CancellationSignal.class),
+                anyInt(),
+                anyInt(),
+                callbackCaptor.capture());
+
+        Button nextButton = mActivity.findViewById(R.id.next_button);
+        nextButton.performClick();
+        callbackCaptor.getValue().onEnrollmentProgress(123);
+        nextButton.performClick();
+
+        ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
+        IntentForResult startedActivity =
+                shadowActivity.getNextStartedActivityForResult();
+        assertThat(startedActivity).named("Next activity 1").isNotNull();
+        assertThat(startedActivity.intent.getComponent())
+                .isEqualTo(new ComponentName(application, FingerprintEnrollEnrolling.class));
+
+        // Should only start one next activity
+        assertThat(shadowActivity.getNextStartedActivityForResult()).named("Next activity 2")
+                .isNull();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 3556d09..3d5d5dc 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -17,6 +17,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.Process;
 import android.text.TextUtils;
@@ -128,8 +129,6 @@
     @Mock
     private LayoutPreference mBatteryLayoutPref;
     @Mock
-    private TextView mBatteryPercentText;
-    @Mock
     private TextView mSummary1;
     @Mock
     private BatteryInfo mBatteryInfo;
@@ -140,6 +139,7 @@
     @Mock
     private SettingsActivity mSettingsActivity;
 
+    private TextView mBatteryPercentText;
     private List<BatterySipper> mUsageList;
     private Context mRealContext;
     private TestFragment mFragment;
@@ -163,7 +163,7 @@
         mLastFullChargePref = new PowerGaugePreference(mRealContext);
         mFragment = spy(new TestFragment(mContext));
         mFragment.initFeatureProvider();
-        mBatteryMeterView = new BatteryMeterView(mRealContext);
+        mBatteryMeterView = spy(new BatteryMeterView(mRealContext));
         mBatteryMeterView.mDrawable = new BatteryMeterView.BatteryMeterDrawable(mRealContext, 0);
 
         when(mFragment.getActivity()).thenReturn(mSettingsActivity);
@@ -185,6 +185,7 @@
         mCellBatterySipper.drainType = BatterySipper.DrainType.CELL;
         mCellBatterySipper.totalPowerMah = POWER_MAH;
 
+        mBatteryPercentText = new TextView(mRealContext);
         when(mBatteryLayoutPref.findViewById(R.id.summary1)).thenReturn(mSummary1);
         when(mBatteryLayoutPref.findViewById(R.id.battery_percent)).thenReturn(mBatteryPercentText);
         when(mBatteryLayoutPref.findViewById(R.id.battery_header_icon))
@@ -278,6 +279,50 @@
     }
 
     @Test
+    public void testInitHeaderPreference_initCorrectly() {
+        mFragment.mBatteryLevel = 100;
+
+        mFragment.initHeaderPreference();
+
+        assertThat(mBatteryMeterView.getBatteryLevel()).isEqualTo(100);
+        assertThat(mBatteryPercentText.getText().toString()).isEqualTo("100%");
+    }
+
+    @Test
+    public void testStartBatteryHeaderAnimationIfNecessary_batteryLevelChanged_animationStarted() {
+        final int prevLevel = 100;
+        final int curLevel = 80;
+
+        mFragment.startBatteryHeaderAnimationIfNecessary(mBatteryMeterView, mBatteryPercentText,
+                prevLevel, curLevel);
+
+        assertThat(mBatteryMeterView.getBatteryLevel()).isEqualTo(curLevel);
+        assertThat(mBatteryPercentText.getText().toString()).isEqualTo("80%");
+    }
+
+    @Test
+    public void testOnSaveInstanceState_saveBatteryLevel() {
+        Bundle bundle = new Bundle();
+        mFragment.mBatteryLevel = BATTERY_LEVEL;
+        // mock it to stop crash in getPreferenceScreen
+        doReturn(null).when(mFragment).getPreferenceScreen();
+
+        mFragment.onSaveInstanceState(bundle);
+
+        assertThat(bundle.getInt(PowerUsageSummary.ARG_BATTERY_LEVEL)).isEqualTo(BATTERY_LEVEL);
+    }
+
+    @Test
+    public void testOnActivityCreated_setBatteryLevel() {
+        Bundle bundle = new Bundle();
+        bundle.putInt(PowerUsageSummary.ARG_BATTERY_LEVEL, BATTERY_LEVEL);
+
+        mFragment.onActivityCreated(bundle);
+
+        assertThat(mFragment.mBatteryLevel).isEqualTo(BATTERY_LEVEL);
+    }
+
+    @Test
     public void testExtractKeyFromSipper_typeAPPUidObjectNull_returnPackageNames() {
         mNormalBatterySipper.uidObj = null;
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
diff --git a/tests/robotests/src/com/android/settings/notification/BadgingNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BadgingNotificationPreferenceControllerTest.java
new file mode 100644
index 0000000..618574c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/BadgingNotificationPreferenceControllerTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import static android.provider.Settings.Secure.NOTIFICATION_BADGING;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BadgingNotificationPreferenceControllerTest {
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PreferenceScreen mScreen;
+
+    private BadgingNotificationPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = new BadgingNotificationPreferenceController(mContext);
+    }
+
+    @Test
+    public void display_configIsTrue_shouldDisplay() {
+        when(mContext.getResources().
+                getBoolean(com.android.internal.R.bool.config_notificationBadging))
+                .thenReturn(true);
+        mController.displayPreference(mScreen);
+
+        verify(mScreen, never()).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void display_configIsFalse_shouldNotDisplay() {
+        when(mContext.getResources().
+                getBoolean(com.android.internal.R.bool.config_notificationBadging))
+                .thenReturn(false);
+        final Preference preference = mock(Preference.class);
+        when(mScreen.getPreferenceCount()).thenReturn(1);
+        when(mScreen.getPreference(0)).thenReturn(preference);
+        when(preference.getKey()).thenReturn(mController.getPreferenceKey());
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void updateState_preferenceSetCheckedWhenSettingIsOn() {
+        final TwoStatePreference preference = mock(TwoStatePreference.class);
+        final Context context = ShadowApplication.getInstance().getApplicationContext();
+        Settings.Secure.putInt(context.getContentResolver(), NOTIFICATION_BADGING, 1);
+
+        mController = new BadgingNotificationPreferenceController(context);
+        mController.updateState(preference);
+
+        verify(preference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_preferenceSetUncheckedWhenSettingIsOff() {
+        final TwoStatePreference preference = mock(TwoStatePreference.class);
+        final Context context = ShadowApplication.getInstance().getApplicationContext();
+        Settings.Secure.putInt(context.getContentResolver(), NOTIFICATION_BADGING, 0);
+
+        mController = new BadgingNotificationPreferenceController(context);
+        mController.updateState(preference);
+
+        verify(preference).setChecked(false);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java b/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
index 2296370..2e91ec6 100644
--- a/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
@@ -349,4 +349,21 @@
 
         verify(fragment.mSavedQueryController).loadSavedQueries();
     }
+
+    @Test
+    public void onIndexingFinished_noActivity_shouldNotCrash() {
+        ActivityController<SearchActivity> activityController =
+            Robolectric.buildActivity(SearchActivity.class);
+        activityController.setup();
+        SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
+            .findFragmentById(R.id.main_content));
+        when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
+            .thenReturn(true);
+        fragment.mQuery = "bright";
+        ReflectionHelpers.setField(fragment, "mLoaderManager", null);
+        ReflectionHelpers.setField(fragment, "mHost", null);
+
+        fragment.onIndexingFinished();
+        // no crash
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
index 565aff9..cb02d3e 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
@@ -149,10 +149,14 @@
             // Replace all private string references with a placeholder.
             if (set != null) {
                 for (int i = 0; i < set.getAttributeCount(); ++i) {
-                    if (set.getAttributeValue(i).startsWith("@*android:string")) {
-                        Node node = ReflectionHelpers.callInstanceMethod(
-                                XmlResourceParserImpl.class, set, "getAttributeAt",
-                                ReflectionHelpers.ClassParameter.from(int.class, i));
+                    String attributeValue = set.getAttributeValue(i);
+                    Node node = ReflectionHelpers.callInstanceMethod(
+                            XmlResourceParserImpl.class, set, "getAttributeAt",
+                            ReflectionHelpers.ClassParameter.from(int.class, i));
+                    if (attributeValue.contains("attr/fingerprint_layout_theme")) {
+                        // Workaround for https://github.com/robolectric/robolectric/issues/2641
+                        node.setNodeValue("@style/FingerprintLayoutTheme");
+                    } else if (attributeValue.startsWith("@*android:string")) {
                         node.setNodeValue("PLACEHOLDER");
                     }
                 }
@@ -166,7 +170,6 @@
                     ReflectionHelpers.getField(assetManager, "appliedStyles");
             for (Long idx : appliedStylesList.keySet()) {
                 List<Object> appliedStyles = appliedStylesList.get(idx);
-                int i = 1;
                 for (Object appliedStyle : appliedStyles) {
                     StyleResolver styleResolver = ReflectionHelpers.getField(appliedStyle, "style");
                     List<StyleData> styleDatas =
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
index 81cc607..eb82362 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 
 import com.android.settings.Utils;
+import com.android.settings.password.IFingerprintManager;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
@@ -26,8 +27,23 @@
 @Implements(Utils.class)
 public class ShadowUtils {
 
+    private static IFingerprintManager sFingerprintManager = null;
+
     @Implementation
     public static int enforceSameOwner(Context context, int userId) {
         return userId;
     }
+
+    @Implementation
+    public static IFingerprintManager getFingerprintManagerWrapperOrNull(Context context) {
+        return sFingerprintManager;
+    }
+
+    public static void setFingerprintManager(IFingerprintManager fingerprintManager) {
+        sFingerprintManager = fingerprintManager;
+    }
+
+    public static void reset() {
+        sFingerprintManager = null;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/NotifyOpenNetworkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/NotifyOpenNetworkPreferenceControllerTest.java
index 78dbcbd..75b304e 100644
--- a/tests/robotests/src/com/android/settings/wifi/NotifyOpenNetworkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NotifyOpenNetworkPreferenceControllerTest.java
@@ -16,29 +16,25 @@
 
 package com.android.settings.wifi;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.when;
+import static android.provider.Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
 
-import android.app.NotificationManager;
-import android.content.ComponentName;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
 import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.NetworkScorerAppData;
-import android.os.RemoteException;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
-import com.android.settings.R;
+
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.network.NetworkScoreManagerWrapper;
-import com.android.settings.utils.NotificationChannelHelper;
-import com.android.settings.utils.NotificationChannelHelper.NotificationChannelWrapper;
+import com.android.settings.core.lifecycle.Lifecycle;
+
 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;
@@ -47,123 +43,67 @@
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class NotifyOpenNetworkPreferenceControllerTest {
 
-    private static final String TEST_SCORER_PACKAGE = "Test Package";
-    private static final String TEST_SCORER_CLASS = "Test Class";
-    private static final String TEST_SCORER_LABEL = "Test Label";
-    private static final String NOTIFICATION_ID = "Notification Id";
-    private static final CharSequence NOTIFICATION_NAME = "Notification Name";
-
     private Context mContext;
     private NotifyOpenNetworksPreferenceController mController;
-    @Mock private NetworkScoreManagerWrapper mNetworkScorer;
-    @Mock private NotificationChannelHelper mNotificationChannelHelper;
-    @Mock private PackageManager mPackageManager;
-    @Mock private NotificationChannelWrapper mChannel;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        mController = new NotifyOpenNetworksPreferenceController(
-                mContext, mNetworkScorer, mNotificationChannelHelper, mPackageManager);
-        ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
-
-        NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
-                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
-                NOTIFICATION_ID);
-        when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData);
+        mController = new NotifyOpenNetworksPreferenceController(mContext, mock(Lifecycle.class));
     }
 
     @Test
-    public void testIsAvailable_shouldReturnFalseWhenScorerDoesNotExist()
-            throws RemoteException {
-        when(mNetworkScorer.getActiveScorer()).thenReturn(null);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void testIsAvailable_shouldReturnFalseWhenNotificationChannelIdDoesNotExist()
-            throws RemoteException {
-        ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
-        NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
-                0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */,
-                null /* networkAvailableNotificationChannelId */);
-        when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void testIsAvailable_shouldReturnFalseWhenNotificationChannelDoesNotExist()
-            throws RemoteException {
-        when(mNotificationChannelHelper.getNotificationChannelForPackage(
-                anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(null);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void testIsAvailable_shouldReturnTrueWhenNotificationChannelExists()
-            throws RemoteException {
-        when(mNotificationChannelHelper.getNotificationChannelForPackage(
-                anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(mChannel);
-
+    public void testIsAvailable_shouldAlwaysReturnTrue() {
         assertThat(mController.isAvailable()).isTrue();
     }
 
     @Test
     public void handlePreferenceTreeClick_nonMatchingKey_shouldDoNothing() {
-        final Preference pref = new Preference(mContext);
+        final SwitchPreference pref = new SwitchPreference(mContext);
 
         assertThat(mController.handlePreferenceTreeClick(pref)).isFalse();
     }
 
     @Test
-    public void handlePreferenceTreeClick_nullScorer_shouldDoNothing() {
+    public void handlePreferenceTreeClick_nonMatchingType_shouldDoNothing() {
         final Preference pref = new Preference(mContext);
         pref.setKey(mController.getPreferenceKey());
-        when(mNetworkScorer.getActiveScorer()).thenReturn(null);
 
         assertThat(mController.handlePreferenceTreeClick(pref)).isFalse();
     }
 
     @Test
-    public void handlePreferenceTreeClick_matchingKeyAndScorerExists_shouldLaunchActivity()
-            throws RemoteException {
-        final Preference pref = new Preference(mContext);
+    public void handlePreferenceTreeClick_matchingKeyAndType_shouldUpdateSetting() {
+        final SwitchPreference pref = new SwitchPreference(mContext);
+        pref.setChecked(true);
         pref.setKey(mController.getPreferenceKey());
-        when(mNotificationChannelHelper.getNotificationChannelForPackage(
-                anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(mChannel);
 
         assertThat(mController.handlePreferenceTreeClick(pref)).isTrue();
+        assertThat(Settings.Global.getInt(mContext.getContentResolver(),
+                WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0))
+                .isEqualTo(1);
     }
 
     @Test
-    public void updateState_notificationsEnabled_shouldShowEnabledSummary() throws RemoteException {
-        final Preference pref = new Preference(mContext);
-        pref.setKey(mController.getPreferenceKey());
-        when(mNotificationChannelHelper.getNotificationChannelForPackage(
-                anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(mChannel);
-        when(mChannel.getImportance()).thenReturn(NotificationManager.IMPORTANCE_DEFAULT);
-        mController.updateState(pref);
+    public void updateState_preferenceSetCheckedWhenSettingsAreEnabled() {
+        final SwitchPreference preference = mock(SwitchPreference.class);
+        Settings.System.putInt(mContext.getContentResolver(),
+                WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1);
 
-        assertThat(pref.getSummary()).isEqualTo(
-                mContext.getString(R.string.notification_toggle_on));
+        mController.updateState(preference);
+
+        verify(preference).setChecked(true);
     }
 
     @Test
-    public void updateState_notificationsEnabled_shouldShowDisabledSummary()
-            throws RemoteException {
-        final Preference pref = new Preference(mContext);
-        pref.setKey(mController.getPreferenceKey());
-        when(mNotificationChannelHelper.getNotificationChannelForPackage(
-                anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(mChannel);
-        when(mChannel.getImportance()).thenReturn(NotificationManager.IMPORTANCE_NONE);
-        mController.updateState(pref);
+    public void updateState_preferenceSetCheckedWhenSettingsAreDisabled() {
+        final SwitchPreference preference = mock(SwitchPreference.class);
+        Settings.System.putInt(mContext.getContentResolver(),
+                WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0);
 
-        assertThat(pref.getSummary()).isEqualTo(
-                mContext.getString(R.string.notification_toggle_off));
+        mController.updateState(preference);
+
+        verify(preference).setChecked(false);
     }
-
 }