Merge "Update the initial expanded count for apps and notifications." into pi-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 060429e..d55493c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -743,6 +743,27 @@
         </activity>
 
         <activity
+            android:name=".notification.ZenSuggestionActivity"
+            android:label="@string/zen_mode_settings_title"
+            android:icon="@drawable/ic_zen"
+            android:theme="@android:style/Theme.NoDisplay">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.ZEN" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.dismiss"
+                       android:value="0" />
+            <meta-data android:name="com.android.settings.title"
+                       android:resource="@string/zen_suggestion_title" />
+            <meta-data android:name="com.android.settings.summary"
+                       android:resource="@string/zen_suggestion_summary" />
+        </activity>
+
+        <activity
             android:name=".notification.ZenOnboardingActivity"
             android:label="@string/zen_onboarding_dnd_visual_disturbances_header"
             android:icon="@drawable/ic_settings_notifications"
@@ -755,7 +776,6 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
-
         <activity
             android:name="Settings$ZenModeAutomationSettingsActivity"
             android:label="@string/zen_mode_automation_settings_title"
diff --git a/res/drawable/ic_local_phone_24_lib.xml b/res/drawable/ic_local_phone_24_lib.xml
new file mode 100644
index 0000000..4574802
--- /dev/null
+++ b/res/drawable/ic_local_phone_24_lib.xml
@@ -0,0 +1,28 @@
+<!--
+    Copyright 2018 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?android:attr/colorControlNormal">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M16.01,14.48l-2.62,2.62c-2.75-1.49-5.01-3.75-6.5-6.5l2.62-2.62c0.24-0.24,0.34-0.58,0.27-0.9L9.13,3.82 c-0.09-0.47-0.5-0.8-0.98-0.8L4,3.01c-0.56,0-1.03,0.47-1,1.03c0.17,2.91,1.04,5.63,2.43,8.01c1.57,2.69,3.81,4.93,6.5,6.5 c2.38,1.39,5.1,2.26,8.01,2.43c0.56,0.03,1.03-0.44,1.03-1l0-4.15c0-0.48-0.34-0.89-0.8-0.98l-3.26-0.65 C16.58,14.14,16.24,14.24,16.01,14.48z" />
+    <path
+        android:pathData="M0,0h24v24H0V0z" />
+</vector>
diff --git a/res/drawable/ic_zen.xml b/res/drawable/ic_zen.xml
index 8c50d5d..2c55e02 100644
--- a/res/drawable/ic_zen.xml
+++ b/res/drawable/ic_zen.xml
@@ -14,13 +14,13 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0"
-    android:height="24dp"
-    android:width="24dp" >
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0"
+        android:height="24dp"
+        android:width="24dp" >
 
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4 11H8c-.55 0-1-.45-1-1s.45-1 1-1h8c.55 0 1 .45 1 1s-.45 1-1 1z" />
+        android:fillColor="?android:attr/colorControlActivated"
+        android:pathData="M 12 2 C 6.48 2 2 6.48 2 12 s 4.48 10 10 10 10 -4.48 10 -10 S 17.52 2 12 2 z m 4 11 H 8 c -.55 0 -1 -.45 -1 -1 s .45 -1 1 -1 h 8c.55 0 1 .45 1 1 s -.45 1 -1 1z" />
 
 </vector>
diff --git a/res/layout/preference_volume_slider.xml b/res/layout/preference_volume_slider.xml
index 89ecec0..5e5d595 100644
--- a/res/layout/preference_volume_slider.xml
+++ b/res/layout/preference_volume_slider.xml
@@ -45,8 +45,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:layout_marginTop="8dip"
-        android:layout_marginBottom="8dip">
+        android:layout_marginTop="16dip"
+        android:layout_marginBottom="16dip">
 
         <LinearLayout
             android:layout_width="match_parent"
diff --git a/res/values/bools.xml b/res/values/bools.xml
index 61a3c75..29de06b 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -78,6 +78,9 @@
     <!-- Whether alarm_volume should be shown or not. -->
     <bool name="config_show_alarm_volume">true</bool>
 
+    <!-- Whether call_volume should be shown or not. -->
+    <bool name="config_show_call_volume">true</bool>
+
     <!-- Whether notification_volume should be shown or not. -->
     <bool name="config_show_notification_volume">true</bool>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 22cb3c8..8347f99 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8718,7 +8718,7 @@
     <string name="ignore_optimizations_off">Optimize</string>
 
     <!-- Ignore battery optimizations on description [CHAR LIMIT=NONE] -->
-    <string name="ignore_optimizations_on_desc">May drain your battery more quickly</string>
+    <string name="ignore_optimizations_on_desc">May drain your battery more quickly. App will no longer be restricted from using background battery.</string>
 
     <!-- Ignore battery optimizations off description [CHAR LIMIT=NONE] -->
     <string name="ignore_optimizations_off_desc">Recommended for better battery life</string>
@@ -9870,12 +9870,21 @@
     <!-- Help URI, USB Audio [DO NOT TRANSLATE] -->
     <string name="help_url_audio_accessory_not_supported" translatable="false"></string>
 
+    <!-- Help URI, restricted apps page [DO NOT TRANSLATE] -->
+    <string name="help_uri_restricted_apps" translatable="false"></string>
+
     <!-- Help URI, battery saver page [DO NOT TRANSLATE] -->
     <string name="help_url_battery_saver_settings" translatable="false"></string>
 
     <!-- Help URI, smart battery page [DO NOT TRANSLATE] -->
     <string name="help_uri_smart_battery_settings" translatable="false"></string>
 
+    <!-- Title label for dnd suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
+    <string name="zen_suggestion_title">Update Do Not Disturb</string>
+
+    <!-- Summary label for dnd suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
+    <string name="zen_suggestion_summary">Hide notifications to stay focused</string>
+
     <!-- Title label for new device suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
     <string name="new_device_suggestion_title">What\'s new and exciting?</string>
 
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 15fbcc8..61f529f 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -38,12 +38,29 @@
         android:order="-175"
         settings:controller="com.android.settings.sound.MediaOutputPreferenceController"/>
 
+    <!-- Call volume -->
+    <com.android.settings.notification.VolumeSeekBarPreference
+        android:key="call_volume"
+        android:icon="@drawable/ic_local_phone_24_lib"
+        android:title="@string/call_volume_option_title"
+        android:order="-170"
+        settings:allowDividerAbove="true"
+        settings:controller="com.android.settings.notification.CallVolumePreferenceController"/>
+
+    <!-- Hands free profile output switcher -->
+    <ListPreference
+        android:key="take_call_on_output"
+        android:title="@string/take_call_on_title"
+        android:dialogTitle="@string/take_call_on_title"
+        android:order="-165"
+        settings:controller="com.android.settings.sound.HandsFreeProfileOutputPreferenceController"/>
+
     <!-- Ring volume -->
     <com.android.settings.notification.VolumeSeekBarPreference
         android:key="ring_volume"
         android:icon="@*android:drawable/ic_audio_ring_notif"
         android:title="@string/ring_volume_option_title"
-        android:order="-170"
+        android:order="-160"
         settings:controller="com.android.settings.notification.RingVolumePreferenceController"
         settings:allowDividerAbove="true"/>
 
@@ -51,15 +68,7 @@
     <SwitchPreference
         android:key="vibrate_when_ringing"
         android:title="@string/vibrate_when_ringing_title"
-        android:order="-160"/>
-
-    <!-- Hands free profile output switcher -->
-    <ListPreference
-        android:key="take_call_on_output"
-        android:title="@string/take_call_on_title"
-        android:dialogTitle="@string/take_call_on_title"
-        android:order="-155"
-        settings:controller="com.android.settings.sound.HandsFreeProfileOutputPreferenceController"/>
+        android:order="-155"/>
 
     <!-- Alarm volume -->
     <com.android.settings.notification.VolumeSeekBarPreference
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 301e71b..328d4a2 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -545,7 +545,7 @@
                 startAppInfoFragment(AppStorageSettings.class, R.string.storage_settings);
                 break;
             case LIST_TYPE_HIGH_POWER:
-                HighPowerDetail.show(this, mCurrentPkgName, INSTALLED_APP_DETAILS);
+                HighPowerDetail.show(this, mCurrentUid, mCurrentPkgName, INSTALLED_APP_DETAILS);
                 break;
             case LIST_TYPE_OVERLAY:
                 startAppInfoFragment(DrawOverlayDetails.class, R.string.overlay_settings);
diff --git a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
index 1e4b693..c8e6f26 100644
--- a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
@@ -16,11 +16,11 @@
 package com.android.settings.bluetooth;
 
 import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.media.AudioManager;
 import android.support.annotation.VisibleForTesting;
 import android.util.Log;
+
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -57,18 +57,20 @@
     }
 
     @Override
-    public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+    public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
+            int bluetoothProfile) {
         if (DBG) {
-            Log.d(TAG,"onConnectionStateChanged() device : " +
-                    cachedDevice.getName() + ", state : " + state);
+            Log.d(TAG, "onProfileConnectionStateChanged() device: " +
+                    cachedDevice.getName() + ", state: " + state + ", bluetoothProfile: "
+                    + bluetoothProfile);
         }
-        if (state == BluetoothAdapter.STATE_CONNECTED) {
+        if (state == BluetoothProfile.STATE_CONNECTED) {
             if (isFilterMatched(cachedDevice)) {
                 addPreference(cachedDevice);
             } else {
                 removePreference(cachedDevice);
             }
-        } else if (state == BluetoothAdapter.STATE_DISCONNECTED) {
+        } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
             removePreference(cachedDevice);
         }
     }
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
index dfcbfca..8937b17 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
@@ -162,6 +162,11 @@
     }
 
     @Override
+    public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
+            int bluetoothProfile) {
+    }
+
+    @Override
     public void onServiceConnected() {
         // When bluetooth service connected update the UI
         forceUpdate();
diff --git a/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
index 11702bc..d43290c 100644
--- a/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
@@ -15,7 +15,6 @@
  */
 package com.android.settings.bluetooth;
 
-import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
@@ -60,19 +59,20 @@
     }
 
     @Override
-    public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+    public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
+            int bluetoothProfile) {
         if (DBG) {
-            Log.d(TAG,"onConnectionStateChanged() device : " +
-                    cachedDevice.getName() + ", state : " + state);
+            Log.d(TAG, "onProfileConnectionStateChanged() device: " +
+                    cachedDevice.getName() + ", state: " + state + ", bluetoothProfile: "
+                    + bluetoothProfile);
         }
-
-        if (state == BluetoothAdapter.STATE_CONNECTED) {
+        if (state == BluetoothProfile.STATE_CONNECTED) {
             if (isFilterMatched(cachedDevice)) {
                 addPreference(cachedDevice);
             } else {
                 removePreference(cachedDevice);
             }
-        } else if (state == BluetoothAdapter.STATE_DISCONNECTED) {
+        } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
             removePreference(cachedDevice);
         }
     }
diff --git a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
index c25a43b..34cb574 100644
--- a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
@@ -15,8 +15,8 @@
  */
 package com.android.settings.bluetooth;
 
-import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.support.annotation.VisibleForTesting;
 
@@ -43,10 +43,11 @@
     }
 
     @Override
-    public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
-        if (state == BluetoothAdapter.STATE_CONNECTED) {
+    public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
+            int bluetoothProfile) {
+        if (state == BluetoothProfile.STATE_CONNECTED) {
             removePreference(cachedDevice);
-        } else if (state == BluetoothAdapter.STATE_DISCONNECTED) {
+        } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
             addPreference(cachedDevice);
         }
     }
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index 5e45c43..cd478fc 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -100,7 +100,7 @@
         PARENT_TO_CATEGORY_KEY_MAP.put(GestureSettings.class.getName(),
             CategoryKey.CATEGORY_GESTURES);
         PARENT_TO_CATEGORY_KEY_MAP.put(NightDisplaySettings.class.getName(),
-            CategoryKey.CATEGORY_NIGHT_LIGHT);
+            CategoryKey.CATEGORY_NIGHT_DISPLAY);
 
         CATEGORY_KEY_TO_PARENT_MAP = new ArrayMap<>(PARENT_TO_CATEGORY_KEY_MAP.size());
 
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
index d0c0b25..257e8c3 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
@@ -22,7 +22,6 @@
 import android.content.SharedPreferences;
 import android.service.settings.suggestions.Suggestion;
 import android.support.annotation.NonNull;
-import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 import android.util.Pair;
 
@@ -32,6 +31,8 @@
 import com.android.settings.display.NightDisplayPreferenceController;
 import com.android.settings.fingerprint.FingerprintEnrollSuggestionActivity;
 import com.android.settings.fingerprint.FingerprintSuggestionActivity;
+import com.android.settings.notification.ZenOnboardingActivity;
+import com.android.settings.notification.ZenSuggestionActivity;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.password.ScreenLockSuggestionActivity;
 import com.android.settings.support.NewDeviceIntroSuggestionActivity;
@@ -88,6 +89,8 @@
             return NightDisplayPreferenceController.isSuggestionComplete(context);
         } else if (className.equals(NewDeviceIntroSuggestionActivity.class.getName())) {
             return NewDeviceIntroSuggestionActivity.isSuggestionComplete(context);
+        } else if (className.equals(ZenSuggestionActivity.class.getName())) {
+            return ZenOnboardingActivity.isSuggestionComplete(context);
         }
         return false;
     }
diff --git a/src/com/android/settings/fuelgauge/HighPowerDetail.java b/src/com/android/settings/fuelgauge/HighPowerDetail.java
index 9cafbcb..4f70700 100644
--- a/src/com/android/settings/fuelgauge/HighPowerDetail.java
+++ b/src/com/android/settings/fuelgauge/HighPowerDetail.java
@@ -17,6 +17,7 @@
 package com.android.settings.fuelgauge;
 
 import android.app.AlertDialog;
+import android.app.AppOpsManager;
 import android.app.Dialog;
 import android.app.Fragment;
 import android.content.Context;
@@ -43,12 +44,18 @@
 
     private static final String ARG_DEFAULT_ON = "default_on";
 
-    private final PowerWhitelistBackend mBackend = PowerWhitelistBackend.getInstance();
-
-    private String mPackageName;
+    @VisibleForTesting
+    PowerWhitelistBackend mBackend;
+    @VisibleForTesting
+    BatteryUtils mBatteryUtils;
+    @VisibleForTesting
+    String mPackageName;
+    @VisibleForTesting
+    int mPackageUid;
     private CharSequence mLabel;
     private boolean mDefaultOn;
-    private boolean mIsEnabled;
+    @VisibleForTesting
+    boolean mIsEnabled;
     private Checkable mOptionOn;
     private Checkable mOptionOff;
 
@@ -60,8 +67,11 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        mBatteryUtils = BatteryUtils.getInstance(getContext());
+        mBackend = PowerWhitelistBackend.getInstance();
 
         mPackageName = getArguments().getString(AppInfoBase.ARG_PACKAGE_NAME);
+        mPackageUid = getArguments().getInt(AppInfoBase.ARG_PACKAGE_UID);
         PackageManager pm = getContext().getPackageManager();
         try {
             mLabel = pm.getApplicationInfo(mPackageName, 0).loadLabel(pm);
@@ -129,6 +139,8 @@
             if (newValue != oldValue) {
                 logSpecialPermissionChange(newValue, mPackageName, getContext());
                 if (newValue) {
+                    mBatteryUtils.setForceAppStandby(mPackageUid, mPackageName,
+                            AppOpsManager.MODE_ALLOWED);
                     mBackend.addApp(mPackageName);
                 } else {
                     mBackend.removeApp(mPackageName);
@@ -165,10 +177,11 @@
                 : R.string.high_power_off);
     }
 
-    public static void show(Fragment caller, String packageName, int requestCode) {
+    public static void show(Fragment caller, int uid, String packageName, int requestCode) {
         HighPowerDetail fragment = new HighPowerDetail();
         Bundle args = new Bundle();
         args.putString(AppInfoBase.ARG_PACKAGE_NAME, packageName);
+        args.putInt(AppInfoBase.ARG_PACKAGE_UID, uid);
         fragment.setArguments(args);
         fragment.setTargetFragment(caller, requestCode);
         fragment.show(caller.getFragmentManager(), HighPowerDetail.class.getSimpleName());
diff --git a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
index 23b4067..5a7f4ba 100644
--- a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
+++ b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
@@ -122,6 +122,11 @@
         return MetricsProto.MetricsEvent.FUELGAUGE_RESTRICTED_APP_DETAILS;
     }
 
+    @Override
+    public int getHelpResource() {
+        return R.string.help_uri_restricted_apps;
+    }
+
     @VisibleForTesting
     void refreshUi() {
         mRestrictedAppListGroup.removeAll();
diff --git a/src/com/android/settings/notification/CallVolumePreferenceController.java b/src/com/android/settings/notification/CallVolumePreferenceController.java
new file mode 100644
index 0000000..c0e1633
--- /dev/null
+++ b/src/com/android/settings/notification/CallVolumePreferenceController.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 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.media.AudioManager;
+
+import com.android.settings.R;
+
+
+public class CallVolumePreferenceController extends VolumeSeekBarPreferenceController {
+
+    private AudioManager mAudioManager;
+
+    public CallVolumePreferenceController(Context context, String key) {
+        super(context, key);
+        mAudioManager = context.getSystemService(AudioManager.class);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mContext.getResources().getBoolean(R.bool.config_show_call_volume)
+                && !mHelper.isSingleVolume() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public int getAudioStream() {
+        if (mAudioManager.isBluetoothScoOn()) {
+            return AudioManager.STREAM_BLUETOOTH_SCO;
+        }
+        return AudioManager.STREAM_VOICE_CALL;
+    }
+
+    @Override
+    public int getMuteIcon() {
+        // User will not be allowed to fully mute the call volume, use original
+        // icon for mute icon.
+        return R.drawable.ic_local_phone_24_lib;
+    }
+
+}
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index dbf8ecf..3ba71a1 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -151,6 +151,7 @@
         volumeControllers.add(use(MediaVolumePreferenceController.class));
         volumeControllers.add(use(RingVolumePreferenceController.class));
         volumeControllers.add(use(NotificationVolumePreferenceController.class));
+        volumeControllers.add(use(CallVolumePreferenceController.class));
 
         for (VolumeSeekBarPreferenceController controller : volumeControllers) {
             controller.setCallback(mVolumeCallback);
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java
index d7b5e52..b94d494 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreference.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java
@@ -83,7 +83,9 @@
     public void setStream(int stream) {
         mStream = stream;
         setMax(mAudioManager.getStreamMaxVolume(mStream));
-        setMin(mAudioManager.getStreamMinVolume(mStream));
+        // Use getStreamMinVolumeInt for non-public stream type
+        // eg: AudioManager.STREAM_BLUETOOTH_SCO
+        setMin(mAudioManager.getStreamMinVolumeInt(mStream));
         setProgress(mAudioManager.getStreamVolume(mStream));
     }
 
@@ -108,10 +110,6 @@
     @Override
     public void onBindViewHolder(PreferenceViewHolder view) {
         super.onBindViewHolder(view);
-        if (mStream == 0) {
-            Log.w(TAG, "No stream found, not binding volumizer");
-            return;
-        }
         mSeekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
         mIconView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
         mSuppressionTextView = (TextView) view.findViewById(R.id.suppression_text);
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index d579256..9e2b650 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -135,6 +135,9 @@
     }
 
     protected void saveVisualEffectsPolicy(int category, boolean suppress) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.ZEN_SETTINGS_UPDATED, 1);
+
         int suppressedEffects = getNewSuppressedEffects(suppress, category);
         savePolicy(mPolicy.priorityCategories, mPolicy.priorityCallSenders,
                 mPolicy.priorityMessageSenders, suppressedEffects);
diff --git a/src/com/android/settings/notification/ZenOnboardingActivity.java b/src/com/android/settings/notification/ZenOnboardingActivity.java
index 9d71f54..ff86ef6 100644
--- a/src/com/android/settings/notification/ZenOnboardingActivity.java
+++ b/src/com/android/settings/notification/ZenOnboardingActivity.java
@@ -19,16 +19,33 @@
 import android.app.Activity;
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
+import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.Bundle;
-import android.support.annotation.VisibleForTesting;
+import android.provider.Settings;
+import android.text.format.DateUtils;
+import android.util.Log;
 import android.view.View;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
+import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 
 public class ZenOnboardingActivity extends Activity {
 
+    private static final String TAG = "ZenOnboardingActivity";
+
+    @VisibleForTesting
+    static final String PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME =
+            "pref_zen_suggestion_first_display_time_ms";
+    @VisibleForTesting
+    static final String PREF_KEY_SUGGESTION_VIEWED = "pref_zen_suggestion_viewed";
+    @VisibleForTesting
+    static final long ALWAYS_SHOW_THRESHOLD = DateUtils.DAY_IN_MILLIS * 14;
+
     private NotificationManager mNm;
     private MetricsLogger mMetrics;
 
@@ -38,6 +55,10 @@
         setNotificationManager(getSystemService(NotificationManager.class));
         setMetricsLogger(new MetricsLogger());
 
+        Context context = getApplicationContext();
+        Settings.Global.putInt(context.getContentResolver(),
+                Settings.Global.ZEN_SETTINGS_SUGGESTION_VIEWED, 1);
+
         setupUI();
     }
 
@@ -60,20 +81,79 @@
 
     public void close(View button) {
         mMetrics.action(MetricsEvent.ACTION_ZEN_ONBOARDING_KEEP_CURRENT_SETTINGS);
+
+        Settings.Global.putInt(getApplicationContext().getContentResolver(),
+                Settings.Global.ZEN_SETTINGS_UPDATED, 1);
+
         finishAndRemoveTask();
     }
 
     public void save(View button) {
         mMetrics.action(MetricsEvent.ACTION_ZEN_ONBOARDING_OK);
-        Policy policy = mNm.getNotificationPolicy();
+        NotificationManager.Policy policy = mNm.getNotificationPolicy();
 
-        Policy newPolicy = new NotificationManager.Policy(
+        NotificationManager.Policy newPolicy = new NotificationManager.Policy(
                 Policy.PRIORITY_CATEGORY_REPEAT_CALLERS | policy.priorityCategories,
                 Policy.PRIORITY_SENDERS_STARRED,
                 policy.priorityMessageSenders,
-                Policy.getAllSuppressedVisualEffects());
+                NotificationManager.Policy.getAllSuppressedVisualEffects());
         mNm.setNotificationPolicy(newPolicy);
 
+        Settings.Global.putInt(getApplicationContext().getContentResolver(),
+                Settings.Global.ZEN_SETTINGS_UPDATED, 1);
+
         finishAndRemoveTask();
     }
+
+    public static boolean isSuggestionComplete(Context context) {
+        if (wasZenUpdated(context)) {
+            return true;
+        }
+
+        if (showSuggestion(context) || withinShowTimeThreshold(context)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static boolean wasZenUpdated(Context context) {
+        // ZEN_SETTINGS_UPDATED is true for:
+        // - fresh P+ device
+        // - if zen visual effects values were changed by the user in Settings
+        return Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.ZEN_SETTINGS_UPDATED, 0) != 0;
+    }
+
+    private static boolean showSuggestion(Context context) {
+        // SHOW_ZEN_SETTINGS_SUGGESTION is by default true, but false when:
+        // - user manually turns on dnd
+
+        // SHOW_ZEN_SETTINGS_SUGGESTION is also true when:
+        // - automatic rule has started DND and user has not seen the first use dialog
+        return Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.SHOW_ZEN_SETTINGS_SUGGESTION, 0) != 0;
+
+    }
+
+    private static boolean withinShowTimeThreshold(Context context) {
+        final SuggestionFeatureProvider featureProvider = FeatureFactory.getFactory(context)
+                .getSuggestionFeatureProvider(context);
+        final SharedPreferences prefs = featureProvider.getSharedPrefs(context);
+        final long currentTimeMs = System.currentTimeMillis();
+        final long firstDisplayTimeMs;
+
+        if (!prefs.contains(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME)) {
+            firstDisplayTimeMs = currentTimeMs;
+            prefs.edit().putLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME, currentTimeMs).commit();
+        } else {
+            firstDisplayTimeMs = prefs.getLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME, -1);
+        }
+
+        final long showTimeMs = firstDisplayTimeMs + ALWAYS_SHOW_THRESHOLD;
+        final boolean stillShow = currentTimeMs < showTimeMs;
+
+        Log.d(TAG, "still show zen suggestion based on time: " + stillShow);
+        return stillShow;
+    }
 }
diff --git a/src/com/android/settings/notification/ZenSuggestionActivity.java b/src/com/android/settings/notification/ZenSuggestionActivity.java
new file mode 100644
index 0000000..9d2148c
--- /dev/null
+++ b/src/com/android/settings/notification/ZenSuggestionActivity.java
@@ -0,0 +1,24 @@
+package com.android.settings.notification;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+
+public class ZenSuggestionActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // start up zen settings activity
+        Intent settingsIntent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
+        startActivity(settingsIntent);
+
+        // start up onboarding activity
+        Intent onboardingActivity = new Intent(Settings.ZEN_MODE_ONBOARDING);
+        startActivity(onboardingActivity);
+
+        finish();
+    }
+}
diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
index 81479c9..dde2b30 100644
--- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java
+++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
@@ -161,7 +161,6 @@
      */
     @Override
     public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
-        updateState(mPreference);
     }
 
     @Override
@@ -175,6 +174,12 @@
     }
 
     @Override
+    public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
+            int bluetoothProfile) {
+        updateState(mPreference);
+    }
+
+    @Override
     public void onBluetoothStateChanged(int bluetoothState) {
     }
 
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
index fbc698c..ed95015 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
@@ -15,11 +15,11 @@
  */
 package com.android.settings.bluetooth;
 
-import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
-
 import android.media.AudioManager;
+
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -150,60 +150,61 @@
     }
 
     @Test
-    public void onConnectionStateChanged_a2dpDeviceConnected_notInCall_addPreference() {
+    public void onProfileConnectionStateChanged_a2dpDeviceConnected_notInCall_addPreference() {
         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
         when(mBluetoothDeviceUpdater.
                 isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
         when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true);
 
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED);
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
     }
 
     @Test
-    public void onConnectionStateChanged_a2dpDeviceConnected_inCall_removePreference() {
+    public void onProfileConnectionStateChanged_a2dpDeviceConnected_inCall_removePreference() {
         mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
         when(mBluetoothDeviceUpdater.
                 isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
         when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true);
 
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED);
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
     }
+
     @Test
-    public void onConnectionStateChanged_hfpDeviceConnected_notInCall_removePreference() {
+    public void onProfileConnectionStateChanged_hfpDeviceConnected_notInCall_removePreference() {
         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
         when(mBluetoothDeviceUpdater.
                 isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
         when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true);
 
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED);
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
     }
 
     @Test
-    public void onConnectionStateChanged_hfpDeviceConnected_inCall_addPreference() {
+    public void onProfileConnectionStateChanged_hfpDeviceConnected_inCall_addPreference() {
         mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
         when(mBluetoothDeviceUpdater.
                 isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
         when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true);
 
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED);
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
     }
 
     @Test
-    public void onConnectionStateChanged_deviceDisconnected_removePreference() {
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_DISCONNECTED);
+    public void onProfileConnectionStateChanged_deviceDisconnected_removePreference() {
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
     }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
index 53fc1e6..2f77af6 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java
@@ -156,6 +156,11 @@
         }
 
         @Override
+        public int getProfileId() {
+            return 0;
+        }
+
+        @Override
         public int getOrdinal() {
             return 0;
         }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java
index 56e638a..483df01 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java
@@ -16,6 +16,7 @@
 package com.android.settings.bluetooth;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -23,11 +24,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
-
 import android.media.AudioManager;
+
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -75,6 +76,7 @@
 
     private Collection<CachedBluetoothDevice> cachedDevices;
     private ShadowAudioManager mShadowAudioManager;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -151,60 +153,61 @@
     }
 
     @Test
-    public void onConnectionStateChanged_a2dpDeviceConnected_inCall_addPreference() {
+    public void onProfileConnectionStateChanged_a2dpDeviceConnected_inCall_addPreference() {
         mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
         when(mBluetoothDeviceUpdater.
                 isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
         when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true);
 
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED);
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
     }
 
     @Test
-    public void onConnectionStateChanged_a2dpDeviceConnected_notInCall_removePreference() {
+    public void onProfileConnectionStateChanged_a2dpDeviceConnected_notInCall_removePreference() {
         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
         when(mBluetoothDeviceUpdater.
                 isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
         when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true);
 
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED);
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
     }
+
     @Test
-    public void onConnectionStateChanged_hfpDeviceConnected_inCall_removePreference() {
+    public void onProfileConnectionStateChanged_hfpDeviceConnected_inCall_removePreference() {
         mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
         when(mBluetoothDeviceUpdater.
                 isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
         when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true);
 
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED);
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
     }
 
     @Test
-    public void onConnectionStateChanged_hfpDeviceConnected_notInCall_addPreference() {
+    public void onProfileConnectionStateChanged_hfpDeviceConnected_notInCall_addPreference() {
         mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
         when(mBluetoothDeviceUpdater.
                 isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
         when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true);
 
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED);
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
     }
 
     @Test
-    public void onConnectionStateChanged_deviceDisconnected_removePreference() {
-        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_DISCONNECTED);
+    public void onProfileConnectionStateChanged_deviceDisconnected_removePreference() {
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
     }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
index e0ba829..fae014f 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
@@ -22,7 +22,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
 
@@ -76,7 +76,7 @@
     }
 
     @Test
-    public void testUpdate_filterMatch_addPreference() {
+    public void update_filterMatch_addPreference() {
         doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
         doReturn(false).when(mBluetoothDevice).isConnected();
 
@@ -86,7 +86,7 @@
     }
 
     @Test
-    public void testUpdate_filterNotMatch_removePreference() {
+    public void update_filterNotMatch_removePreference() {
         doReturn(BluetoothDevice.BOND_NONE).when(mBluetoothDevice).getBondState();
         doReturn(true).when(mBluetoothDevice).isConnected();
 
@@ -96,17 +96,17 @@
     }
 
     @Test
-    public void testOnConnectionStateChanged_deviceConnected_removePreference() {
-        mBluetoothDeviceUpdater
-            .onConnectionStateChanged(mCachedBluetoothDevice, BluetoothAdapter.STATE_CONNECTED);
+    public void onProfileConnectionStateChanged_deviceConnected_removePreference() {
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
     }
 
     @Test
-    public void testOnConnectionStateChanged_deviceDisconnected_addPreference() {
-        mBluetoothDeviceUpdater
-            .onConnectionStateChanged(mCachedBluetoothDevice, BluetoothAdapter.STATE_DISCONNECTED);
+    public void onProfileConnectionStateChanged_deviceDisconnected_addPreference() {
+        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP);
 
         verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
     }
diff --git a/tests/robotests/src/com/android/settings/display/NightDisplaySettingsTest.java b/tests/robotests/src/com/android/settings/display/NightDisplaySettingsTest.java
index e3f9092..6942fd8 100644
--- a/tests/robotests/src/com/android/settings/display/NightDisplaySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/display/NightDisplaySettingsTest.java
@@ -48,8 +48,8 @@
     }
 
     @Test
-    public void getCategoryKey_isCategoryNightLight() {
+    public void getCategoryKey_isCategoryNightDisplay() {
         NightDisplaySettings settings = new NightDisplaySettings();
-        assertThat(settings.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_NIGHT_LIGHT);
+        assertThat(settings.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_NIGHT_DISPLAY);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/HighPowerDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/HighPowerDetailTest.java
index 8029c55..1817325 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/HighPowerDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/HighPowerDetailTest.java
@@ -18,27 +18,49 @@
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
+import android.app.AppOpsManager;
 import android.content.Context;
+import android.content.DialogInterface;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
 
 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;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class HighPowerDetailTest {
+    private static final int TEST_UID = 12000;
+    private static final String TEST_PACKAGE = "com.test.package";
 
     private FakeFeatureFactory mFeatureFactory;
+    private HighPowerDetail mFragment;
+
+    @Mock
+    private PowerWhitelistBackend mPowerWhitelistBackend;
+    @Mock
+    private BatteryUtils mBatteryUtils;
 
     @Before
     public void setUp() {
         mFeatureFactory = FakeFeatureFactory.setupForTest();
+
+        MockitoAnnotations.initMocks(this);
+        mFragment = spy(new HighPowerDetail());
+        mFragment.mBackend = mPowerWhitelistBackend;
+        mFragment.mBatteryUtils = mBatteryUtils;
+        mFragment.mPackageUid = TEST_UID;
+        mFragment.mPackageName = TEST_PACKAGE;
     }
 
     @Test
@@ -53,4 +75,13 @@
         verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
                 eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_BATTERY_ALLOW), eq("app"));
     }
+
+    @Test
+    public void onClick_appAddedToDozeWhitelist_getsUnrestricted() {
+        mFragment.mIsEnabled = true;
+        when(mPowerWhitelistBackend.isWhitelisted(TEST_PACKAGE)).thenReturn(false);
+        mFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
+        verify(mBatteryUtils).setForceAppStandby(TEST_UID, TEST_PACKAGE,
+                AppOpsManager.MODE_ALLOWED);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/CallVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/CallVolumePreferenceControllerTest.java
new file mode 100644
index 0000000..bed45e5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/CallVolumePreferenceControllerTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 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 static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.media.AudioManager;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowAudioManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowAudioManager.class})
+public class CallVolumePreferenceControllerTest {
+    private static final String TEST_KEY = "Test_Key";
+
+    @Mock
+    private AudioHelper mHelper;
+
+    private Context mContext;
+    private CallVolumePreferenceController mController;
+    private ShadowAudioManager mShadowAudioManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = new CallVolumePreferenceController(mContext, TEST_KEY);
+        mController.setAudioHelper(mHelper);
+        mShadowAudioManager = ShadowAudioManager.getShadow();
+    }
+
+    @Test
+    public void getAvailabilityStatus_singleVolume_shouldReturnDisable() {
+        when(mHelper.isSingleVolume()).thenReturn(true);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_notSingleVolume_shouldReturnAvailable() {
+        when(mHelper.isSingleVolume()).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void getMuteIcon_shouldEqualToOriginalIcon() {
+        assertThat(mController.getMuteIcon()).isEqualTo(R.drawable.ic_local_phone_24_lib);
+    }
+
+    @Test
+    public void getAudioStream_onBluetoothScoOff_shouldEqualToStreamVoiceCall() {
+        mShadowAudioManager.setBluetoothScoOn(false);
+
+        assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_VOICE_CALL);
+    }
+
+    @Test
+    public void getAudioStream_onBluetoothScoOn_shouldEqualToStreamBtSco() {
+        mShadowAudioManager.setBluetoothScoOn(true);
+
+        assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_BLUETOOTH_SCO);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java
index c32f96a..5955aa8 100644
--- a/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java
@@ -50,17 +50,20 @@
     }
 
     @Test
-    public void setStream_shouldSetMaxAndProgress() {
+    public void setStream_shouldSetMinMaxAndProgress() {
         final int stream = 5;
         final int max = 17;
+        final int min = 1;
         final int progress = 4;
         when(mAudioManager.getStreamMaxVolume(stream)).thenReturn(max);
+        when(mAudioManager.getStreamMinVolumeInt(stream)).thenReturn(min);
         when(mAudioManager.getStreamVolume(stream)).thenReturn(progress);
         doCallRealMethod().when(mPreference).setStream(anyInt());
 
         mPreference.setStream(stream);
 
         verify(mPreference).setMax(max);
+        verify(mPreference).setMin(min);
         verify(mPreference).setProgress(progress);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java b/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
index 7bc9371..b4d3700 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
@@ -29,6 +29,12 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
 
+import static com.android.settings.notification.ZenOnboardingActivity.ALWAYS_SHOW_THRESHOLD;
+import static com.android.settings.notification.ZenOnboardingActivity.PREF_KEY_SUGGESTION_VIEWED;
+import static com.android.settings.notification.ZenOnboardingActivity
+        .PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME;
+import static com.android.settings.notification.ZenOnboardingActivity.isSuggestionComplete;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -39,20 +45,22 @@
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
 import android.content.Context;
+import android.content.SharedPreferences;
+import android.provider.Settings;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 public class ZenOnboardingActivityTest {
@@ -64,6 +72,9 @@
 
     ZenOnboardingActivity mActivity;
 
+    private Context mContext;
+    private FakeFeatureFactory mFeatureFactory;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -75,6 +86,11 @@
         mActivity.setMetricsLogger(mMetricsLogger);
 
         mActivity.setupUI();
+
+        mContext = RuntimeEnvironment.application;
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        when(mFeatureFactory.suggestionsFeatureProvider.getSharedPrefs(any(Context.class)))
+                .thenReturn(getSharedPreferences());
     }
 
     @Test
@@ -124,4 +140,73 @@
 
         verify(mNm, never()).setNotificationPolicy(any());
     }
+
+    @Test
+    public void isSuggestionComplete_zenUpdated() {
+        setZenUpdated(true);
+        setShowSettingsSuggestion(false);
+        setWithinTimeThreshold(true);
+        assertThat(isSuggestionComplete(mContext)).isTrue();
+    }
+
+    @Test
+    public void isSuggestionComplete_withinTimeThreshold() {
+        setZenUpdated(false);
+        setShowSettingsSuggestion(false);
+        setWithinTimeThreshold(true);
+        assertThat(isSuggestionComplete(mContext)).isFalse();
+    }
+
+    @Test
+    public void isSuggestionComplete_showSettingsSuggestionTrue() {
+        setZenUpdated(false);
+        setShowSettingsSuggestion(true);
+        setWithinTimeThreshold(false);
+        assertThat(isSuggestionComplete(mContext)).isFalse();
+    }
+
+    @Test
+    public void isSuggestionComplete_showSettingsSuggestionFalse_notWithinTimeThreshold() {
+        setZenUpdated(false);
+        setShowSettingsSuggestion(false);
+        setWithinTimeThreshold(false);
+        assertThat(isSuggestionComplete(mContext)).isTrue();
+    }
+
+    private void setZenUpdated(boolean updated) {
+        int zenUpdated = 0;
+        if (updated) {
+            zenUpdated = 1;
+        }
+
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.ZEN_SETTINGS_UPDATED, zenUpdated);
+    }
+
+    private void setWithinTimeThreshold(boolean withinTime) {
+        long firstTime = System.currentTimeMillis();
+
+        if (withinTime) {
+            firstTime -= ALWAYS_SHOW_THRESHOLD / 2;
+        } else {
+            firstTime -= ALWAYS_SHOW_THRESHOLD * 2;
+        }
+
+        getSharedPreferences().edit().putLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME,
+               firstTime).commit();
+    }
+
+    private void setShowSettingsSuggestion(boolean show) {
+        int showZenSuggestion = 0;
+        if (show) {
+            showZenSuggestion = 1;
+        }
+
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_ZEN_SETTINGS_SUGGESTION, showZenSuggestion);
+    }
+
+    private SharedPreferences getSharedPreferences() {
+        return mContext.getSharedPreferences("test_zen_sugg", Context.MODE_PRIVATE);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
index bb14667..c6583c7 100644
--- a/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
+++ b/tests/robotests/src/com/android/settings/suggestions/SettingsSuggestionsTest.java
@@ -30,6 +30,8 @@
 import com.android.settings.Settings;
 import com.android.settings.fingerprint.FingerprintEnrollSuggestionActivity;
 import com.android.settings.fingerprint.FingerprintSuggestionActivity;
+import com.android.settings.notification.ZenOnboardingActivity;
+import com.android.settings.notification.ZenSuggestionActivity;
 import com.android.settings.support.NewDeviceIntroSuggestionActivity;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.wallpaper.WallpaperSuggestionActivity;
@@ -83,6 +85,14 @@
     }
 
     @Test
+    public void zenSuggestion_isValid() {
+        assertSuggestionEquals(
+                ZenSuggestionActivity.class.getName(),
+                R.string.zen_suggestion_title,
+                R.string.zen_suggestion_summary);
+    }
+
+    @Test
     public void newDeviceIntroSuggestion_isValid() {
         assertSuggestionEquals(
             NewDeviceIntroSuggestionActivity.class.getName(),
diff --git a/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java b/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
index 1597568..286676d 100644
--- a/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
+++ b/tests/robotests/src/com/android/settings/support/NewDeviceIntroSuggestionActivityTest.java
@@ -78,7 +78,7 @@
         final long currentTime = System.currentTimeMillis();
 
         getSharedPreferences().edit().putLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME,
-                currentTime - 2 * PERMANENT_DISMISS_THRESHOLD);
+                currentTime - 2 * PERMANENT_DISMISS_THRESHOLD).commit();
         assertThat(isSuggestionComplete(mContext)).isTrue();
     }
 
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java
index 88a0fb6..3c37145 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java
@@ -42,7 +42,8 @@
 public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManager {
     private int mRingerMode;
     private int mDeviceCodes;
-    private boolean mMusicActiveRemotely = false;
+    private boolean mMusicActiveRemotely;
+    private boolean mBluetoothScoOn;
     private ArrayList<AudioDeviceCallback> mDeviceCallbacks = new ArrayList();
 
     @Implementation
@@ -104,4 +105,11 @@
     public void reset() {
         mDeviceCallbacks.clear();
     }
+
+    public void setBluetoothScoOn(boolean bluetoothScoOn) {
+        mBluetoothScoOn = bluetoothScoOn;
+    }
+
+    @Implementation
+    public boolean isBluetoothScoOn() { return mBluetoothScoOn; }
 }