Volume UI updates

- Reorder streams
- constrain ripples
- Show an introductory ripple on the ringer toggle
- Add sound/vibration feedback for the ringer toggle
- resize some elements

Test: manual
Bug: 76438403
Fixes: 73892482
Change-Id: I92dd6f5681f1822ae493a5a2b218b15970293e80
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
index c8bcdaa..5f4cf03 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
@@ -19,6 +19,7 @@
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.os.Handler;
+import android.os.VibrationEffect;
 import android.util.SparseArray;
 
 import com.android.systemui.plugins.VolumeDialogController.Callbacks;
@@ -44,7 +45,8 @@
     void setRingerMode(int ringerModeNormal, boolean external);
 
     boolean hasVibrator();
-    void vibrate();
+    void vibrate(VibrationEffect effect);
+    void scheduleTouchFeedback();
 
     AudioManager getAudioManager();
 
diff --git a/packages/SystemUI/res/drawable/rounded_full_bg_bottom.xml b/packages/SystemUI/res/drawable/rounded_full_bg_bottom.xml
index c3e36f2..a4b3c99 100644
--- a/packages/SystemUI/res/drawable/rounded_full_bg_bottom.xml
+++ b/packages/SystemUI/res/drawable/rounded_full_bg_bottom.xml
@@ -1,4 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
     <solid android:color="?android:attr/colorPrimaryDark" />
diff --git a/packages/SystemUI/res/drawable/rounded_ripple.xml b/packages/SystemUI/res/drawable/rounded_ripple.xml
new file mode 100644
index 0000000..5588eb2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/rounded_ripple.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="?android:attr/colorControlHighlight">
+    <item android:id="@android:id/mask">
+        <shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <solid android:color="#FFFFFFFF"/>
+            <corners android:radius="8dp"/>
+        </shape>
+    </item>
+    <item android:id="@android:id/background">
+        <shape android:shape="rectangle">
+            <solid android:color="#FFFFFFFF"/>
+            <corners android:radius="8dp"/>
+        </shape>
+    </item>
+</ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/car_volume_dialog.xml b/packages/SystemUI/res/layout/car_volume_dialog.xml
index e45c0f9..94cc001 100644
--- a/packages/SystemUI/res/layout/car_volume_dialog.xml
+++ b/packages/SystemUI/res/layout/car_volume_dialog.xml
@@ -38,7 +38,7 @@
             android:orientation="vertical"
             android:clipChildren="false"
             android:clipToPadding="false"
-            android:elevation="@dimen/volume_panel_elevation" >
+            android:elevation="@dimen/volume_dialog_elevation" >
             <LinearLayout
                 android:id="@+id/car_volume_dialog_rows"
                 android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 0a3f4eb..d4fe1c6 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -17,9 +17,11 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:padding="@dimen/volume_dialog_panel_transparent_padding"
     android:background="@android:color/transparent"
     android:theme="@style/qs_theme"
-    android:clipChildren="false" >
+    android:clipChildren="false"
+    android:clipToPadding="false">
     <!-- right-aligned to be physically near volume button -->
     <LinearLayout
         android:id="@+id/volume_dialog"
@@ -30,22 +32,25 @@
         android:background="@android:color/transparent"
         android:layout_margin="@dimen/volume_dialog_base_margin"
         android:orientation="vertical"
-        android:clipChildren="false" >
+        android:clipChildren="false"
+        android:clipToPadding="false" >
 
         <FrameLayout
             android:id="@+id/ringer"
             android:layout_width="@dimen/volume_dialog_ringer_size"
             android:layout_height="@dimen/volume_dialog_ringer_size"
             android:layout_marginBottom="@dimen/volume_dialog_spacer"
-            android:elevation="@dimen/volume_panel_elevation"
+            android:translationZ="@dimen/volume_dialog_elevation"
             android:layout_gravity="right"
+            android:clipChildren="false"
+            android:clipToPadding="false"
             android:background="@drawable/rounded_bg_full">
             <com.android.keyguard.AlphaOptimizedImageButton
                 android:id="@+id/ringer_icon"
                 style="@style/VolumeButtons"
-                android:background="?android:selectableItemBackgroundBorderless"
-                android:layout_width="@dimen/volume_dialog_tap_target_size"
-                android:layout_height="@dimen/volume_dialog_tap_target_size"
+                android:background="@drawable/rounded_ripple"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
                 android:tint="@color/accent_tint_color_selector"
                 android:layout_gravity="center"
                 android:soundEffectsEnabled="false" />
@@ -59,10 +64,10 @@
             android:minWidth="@dimen/volume_dialog_panel_width"
             android:layout_height="wrap_content"
             android:orientation="vertical"
+            android:translationZ="@dimen/volume_dialog_elevation"
             android:clipChildren="false"
             android:clipToPadding="false"
-            android:background="@drawable/rounded_bg_full"
-            android:elevation="@dimen/volume_panel_elevation" >
+            android:background="@drawable/rounded_bg_full" >
             <LinearLayout
                 android:id="@+id/volume_dialog_rows"
                 android:layout_width="wrap_content"
@@ -84,7 +89,7 @@
                     android:layout_height="@dimen/volume_dialog_tap_target_size"
                     android:layout_gravity="center"
                     android:contentDescription="@string/accessibility_volume_settings"
-                    android:background="?android:selectableItemBackgroundBorderless"
+                    android:background="@drawable/ripple_drawable_20dp"
                     android:tint="?android:attr/colorControlNormal"
                     android:soundEffectsEnabled="false" />
             </FrameLayout>
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index bcc3692..6128da8 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -60,7 +60,7 @@
             style="@style/VolumeButtons"
             android:layout_width="@dimen/volume_dialog_tap_target_size"
             android:layout_height="@dimen/volume_dialog_tap_target_size"
-            android:background="?android:selectableItemBackgroundBorderless"
+            android:background="@drawable/ripple_drawable_20dp"
             android:layout_marginBottom="@dimen/volume_dialog_row_margin_bottom"
             android:tint="@color/accent_tint_color_selector"
             android:soundEffectsEnabled="false" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 91c8724..0f07ca4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -270,13 +270,15 @@
     <!-- The width of the panel that holds the quick settings. -->
     <dimen name="qs_panel_width">@dimen/notification_panel_width</dimen>
 
+    <dimen name="volume_dialog_panel_transparent_padding">8dp</dimen>
+
     <!-- the amount the volume panel should be offset at the end from the view next to it (or
     the screen edge, in portrait-->
     <dimen name="volume_dialog_base_margin">8dp</dimen>
 
     <dimen name="volume_dialog_panel_width">64dp</dimen>
 
-    <dimen name="volume_dialog_slider_height">108dp</dimen>
+    <dimen name="volume_dialog_slider_height">116dp</dimen>
 
     <dimen name="volume_dialog_row_height">252dp</dimen>
 
@@ -286,7 +288,7 @@
 
     <dimen name="volume_dialog_spacer">4dp</dimen>
 
-    <dimen name="volume_dialog_slider_margin_top">22dp</dimen>
+    <dimen name="volume_dialog_slider_margin_top">14dp</dimen>
 
     <dimen name="volume_dialog_slider_margin_bottom">-2dp</dimen>
 
@@ -294,6 +296,8 @@
 
     <dimen name="volume_dialog_settings_icon_size">16dp</dimen>
 
+    <dimen name="volume_dialog_elevation">9dp</dimen>
+
     <!-- Gravity for the notification panel -->
     <integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
 
@@ -734,8 +738,6 @@
     <dimen name="volume_expander_margin_end">2dp</dimen>
     <dimen name="volume_expander_margin_top">6dp</dimen>
 
-    <dimen name="volume_panel_elevation">8dp</dimen>
-
     <!-- Padding between icon and text for managed profile toast -->
     <dimen name="managed_profile_toast_padding">4dp</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 419e9d2..e9b2be9 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1350,7 +1350,7 @@
 
     <string name="volume_dialog_title">%s volume controls</string>
 
-    <string name="volume_dialog_ringer_guidance_ring">Calls and notifications will ring</string>
+    <string name="volume_dialog_ringer_guidance_ring">Calls and notifications will ring (<xliff:g id="volume level" example="56">%1$s</xliff:g>)</string>
 
     <string name="output_title">Media output</string>
     <string name="output_calls_title">Phone call output</string>
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 1a9655e..2a27147 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -53,7 +53,8 @@
             Key.NUM_APPS_LAUNCHED,
             Key.HAS_SEEN_RECENTS_ONBOARDING,
             Key.SEEN_RINGER_GUIDANCE_COUNT,
-            Key.QS_HAS_TURNED_OFF_MOBILE_DATA
+            Key.QS_HAS_TURNED_OFF_MOBILE_DATA,
+            Key.TOUCHED_RINGER_TOGGLE
     })
     public @interface Key {
         @Deprecated
@@ -91,6 +92,7 @@
         String SEEN_RINGER_GUIDANCE_COUNT = "RingerGuidanceCount";
         String QS_TILE_SPECS_REVEALED = "QsTileSpecsRevealed";
         String QS_HAS_TURNED_OFF_MOBILE_DATA = "QsHasTurnedOffMobileData";
+        String TOUCHED_RINGER_TOGGLE = "TouchedRingerToggle";
     }
 
     public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index ee6748e..a97effd 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.volume;
 
+import static android.media.AudioManager.RINGER_MODE_NORMAL;
+
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -29,6 +31,7 @@
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
+import android.media.IAudioService;
 import android.media.IVolumeController;
 import android.media.VolumePolicy;
 import android.media.session.MediaController.PlaybackInfo;
@@ -39,6 +42,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.provider.Settings;
@@ -73,9 +77,11 @@
 public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpable {
     private static final String TAG = Util.logTag(VolumeDialogControllerImpl.class);
 
+
+    private static final int TOUCH_FEEDBACK_TIMEOUT_MS = 1000;
     private static final int DYNAMIC_STREAM_START_INDEX = 100;
     private static final int VIBRATE_HINT_DURATION = 50;
-    private static final AudioAttributes SONFICIATION_VIBRATION_ATTRIBUTES =
+    private static final AudioAttributes SONIFICIATION_VIBRATION_ATTRIBUTES =
             new AudioAttributes.Builder()
                     .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                     .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
@@ -100,6 +106,7 @@
     private final W mWorker;
     private final Context mContext;
     private AudioManager mAudio;
+    private IAudioService mAudioService;
     protected StatusBar mStatusBar;
     private final NotificationManager mNoMan;
     private final SettingObserver mObserver;
@@ -113,6 +120,7 @@
     private boolean mShowA11yStream;
     private boolean mShowVolumeDialog;
     private boolean mShowSafetyWarning;
+    private long mLastToggledRingerOn;
     private final NotificationManager mNotificationManager;
 
     private boolean mDestroyed;
@@ -140,6 +148,8 @@
         mReceiver.init();
         mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
+        mAudioService = IAudioService.Stub.asInterface(
+                ServiceManager.getService(Context.AUDIO_SERVICE));
         updateStatusBar();
 
         boolean accessibilityVolumeStreamActive = context.getSystemService(
@@ -300,10 +310,24 @@
       mShowSafetyWarning = safetyWarning;
     }
 
-    public void vibrate() {
+    @Override
+    public void scheduleTouchFeedback() {
+        mLastToggledRingerOn = System.currentTimeMillis();
+    }
+
+    private void playTouchFeedback() {
+        if (System.currentTimeMillis() - mLastToggledRingerOn < TOUCH_FEEDBACK_TIMEOUT_MS) {
+            try {
+                mAudioService.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
+            } catch (RemoteException e) {
+                // ignore
+            }
+        }
+    }
+
+    public void vibrate(VibrationEffect effect) {
         if (mHasVibrator) {
-            mVibrator.vibrate(VibrationEffect.createOneShot(VIBRATE_HINT_DURATION,
-                    VibrationEffect.DEFAULT_AMPLITUDE), SONFICIATION_VIBRATION_ATTRIBUTES);
+            mVibrator.vibrate(effect, SONIFICIATION_VIBRATION_ATTRIBUTES);
         }
     }
 
@@ -425,7 +449,7 @@
         for (int stream : STREAMS.keySet()) {
             updateStreamLevelW(stream, getAudioManagerStreamVolume(stream));
             streamStateW(stream).levelMin = getAudioManagerStreamMinVolume(stream);
-            streamStateW(stream).levelMax = getAudioManagerStreamMaxVolume(stream);
+            streamStateW(stream).levelMax = Math.max(1, getAudioManagerStreamMaxVolume(stream));
             updateStreamMuteW(stream, mAudio.isStreamMute(stream));
             final StreamState ss = streamStateW(stream);
             ss.muteSupported = mAudio.isStreamAffectedByMute(stream);
@@ -556,6 +580,11 @@
         if (rm == mState.ringerModeInternal) return false;
         mState.ringerModeInternal = rm;
         Events.writeEvent(mContext, Events.EVENT_INTERNAL_RINGER_MODE_CHANGED, rm);
+
+        if (mState.ringerModeInternal == RINGER_MODE_NORMAL) {
+            playTouchFeedback();
+        }
+
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 71c7f80..acdd0c7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -22,6 +22,10 @@
 import static android.media.AudioManager.RINGER_MODE_SILENT;
 import static android.media.AudioManager.RINGER_MODE_VIBRATE;
 import static android.media.AudioManager.STREAM_ACCESSIBILITY;
+import static android.media.AudioManager.STREAM_ALARM;
+import static android.media.AudioManager.STREAM_MUSIC;
+import static android.media.AudioManager.STREAM_RING;
+import static android.media.AudioManager.STREAM_VOICE_CALL;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
@@ -41,13 +45,17 @@
 import android.graphics.Color;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.ColorDrawable;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
+import android.media.MediaPlayer;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.text.InputFilter;
@@ -126,6 +134,7 @@
     private final Accessibility mAccessibility = new Accessibility();
     private final ColorStateList mActiveSliderTint;
     private final ColorStateList mInactiveSliderTint;
+    private final Vibrator mVibrator;
 
     private boolean mShowing;
     private boolean mShowA11yStream;
@@ -146,6 +155,7 @@
         mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
         mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
     }
 
     public void init(int windowType, Callback callback) {
@@ -203,6 +213,9 @@
                     .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
                     .withEndAction(() -> {
                         mWindow.getDecorView().requestAccessibilityFocus();
+                        if (!Prefs.getBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, true)) {
+                            mRingerIcon.postOnAnimationDelayed(mSinglePress, 1500);
+                        }
                     })
                     .start();
         });
@@ -223,12 +236,16 @@
         mSettingsIcon = mDialog.findViewById(R.id.settings);
 
         if (mRows.isEmpty()) {
+            if (!AudioSystem.isSingleVolume(mContext)) {
+                addRow(STREAM_ACCESSIBILITY, R.drawable.ic_volume_accessibility,
+                        R.drawable.ic_volume_accessibility, true, false);
+            }
             addRow(AudioManager.STREAM_MUSIC,
                     R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true, true);
             if (!AudioSystem.isSingleVolume(mContext)) {
                 addRow(AudioManager.STREAM_RING,
                         R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true, false);
-                addRow(AudioManager.STREAM_ALARM,
+                addRow(STREAM_ALARM,
                         R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, true, false);
                 addRow(AudioManager.STREAM_VOICE_CALL,
                         R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false, false);
@@ -236,8 +253,6 @@
                         R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false, false);
                 addRow(AudioManager.STREAM_SYSTEM, R.drawable.ic_volume_system,
                         R.drawable.ic_volume_system_mute, false, false);
-                addRow(STREAM_ACCESSIBILITY, R.drawable.ic_volume_accessibility,
-                        R.drawable.ic_volume_accessibility, true, false);
             }
         } else {
             addExistingRows();
@@ -287,11 +302,11 @@
         if (D.BUG) Slog.d(TAG, "Adding row for stream " + stream);
         VolumeRow row = new VolumeRow();
         initRow(row, stream, iconRes, iconMuteRes, important, defaultStream);
-        int rowSize;
-        if (mShowA11yStream && dynamic && (rowSize = mRows.size()) > 1) {
-            // A11y Stream should be the first in the list, so it's shown to start of other rows
-            mDialogRowsView.addView(row.view, 0);
-            mRows.add(rowSize - 2, row);
+        if (dynamic && mRows.size() > 2) {
+            // Dynamic Streams should be the first in the list, so they're shown to start of
+            // everything except a11y
+            mDialogRowsView.addView(row.view, 1);
+            mRows.add(1, row);
         } else {
             mDialogRowsView.addView(row.view);
             mRows.add(row);
@@ -315,6 +330,11 @@
                 return row;
             }
         }
+        for (VolumeRow row : mRows) {
+            if (row.stream == STREAM_MUSIC) {
+                return row;
+            }
+        }
         return mRows.get(0);
     }
 
@@ -414,6 +434,7 @@
         mRingerIcon.setOnClickListener(v -> {
             Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, AudioManager.STREAM_RING,
                     mRingerIcon.getTag());
+            Prefs.putBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, true);
             final StreamState ss = mState.states.get(AudioManager.STREAM_RING);
             if (ss == null) {
                 return;
@@ -424,7 +445,6 @@
             final boolean hasVibrator = mController.hasVibrator();
             if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
                 if (hasVibrator) {
-                    mController.vibrate();
                     newRingerMode = AudioManager.RINGER_MODE_VIBRATE;
                 } else {
                     newRingerMode = AudioManager.RINGER_MODE_SILENT;
@@ -438,30 +458,56 @@
                 }
             }
             updateRingerH();
-
+            provideTouchFeedbackH(newRingerMode);
             mController.setRingerMode(newRingerMode, false);
             maybeShowToastH(newRingerMode);
         });
         updateRingerH();
     }
 
+
+    private void provideTouchFeedbackH(int newRingerMode) {
+        VibrationEffect effect = null;
+        switch (newRingerMode) {
+            case RINGER_MODE_NORMAL:
+                mController.scheduleTouchFeedback();
+                break;
+            case RINGER_MODE_SILENT:
+                effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
+                break;
+            case RINGER_MODE_VIBRATE:
+            default:
+                effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
+        }
+        if (effect != null) {
+            mController.vibrate(effect);
+        }
+    }
+
     private void maybeShowToastH(int newRingerMode) {
         int seenToastCount = Prefs.getInt(mContext, Prefs.Key.SEEN_RINGER_GUIDANCE_COUNT, 0);
 
         if (seenToastCount > VolumePrefs.SHOW_RINGER_TOAST_COUNT) {
             return;
         }
-        int toastText;
+        CharSequence toastText = null;
         switch (newRingerMode) {
             case RINGER_MODE_NORMAL:
-                toastText = R.string.volume_dialog_ringer_guidance_ring;
+                final StreamState ss = mState.states.get(AudioManager.STREAM_RING);
+                if (ss != null) {
+                    toastText = mContext.getString(
+                            R.string.volume_dialog_ringer_guidance_ring,
+                            Utils.formatPercentage(ss.level, ss.levelMax));
+                }
                 break;
             case RINGER_MODE_SILENT:
-                toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
+                toastText = mContext.getString(
+                        com.android.internal.R.string.volume_dialog_ringer_guidance_silent);
                 break;
             case RINGER_MODE_VIBRATE:
             default:
-                toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
+                toastText = mContext.getString(
+                        com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate);
         }
 
         Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
@@ -538,7 +584,7 @@
     }
 
     private boolean shouldBeVisibleH(VolumeRow row, VolumeRow activeRow) {
-        boolean isActive = row == activeRow;
+        boolean isActive = row.stream == activeRow.stream;
         if (row.stream == AudioSystem.STREAM_ACCESSIBILITY) {
             return mShowA11yStream;
         }
@@ -550,7 +596,17 @@
             return true;
         }
 
-        return row.defaultStream || isActive;
+        if (isActive) {
+            return true;
+        }
+
+        if (row.defaultStream) {
+            return activeRow.stream == STREAM_RING
+                    || activeRow.stream == STREAM_ALARM
+                    || activeRow.stream == STREAM_VOICE_CALL;
+        }
+
+        return false;
     }
 
     private void updateRowsH(final VolumeRow activeRow) {
@@ -670,7 +726,8 @@
         if (mActiveStream != state.activeStream) {
             mPrevActiveStream = mActiveStream;
             mActiveStream = state.activeStream;
-            updateRowsH(getActiveRow());
+            VolumeRow activeRow = getActiveRow();
+            updateRowsH(activeRow);
             rescheduleTimeoutH();
         }
         for (VolumeRow row : mRows) {
@@ -696,7 +753,7 @@
         final boolean isA11yStream = row.stream == STREAM_ACCESSIBILITY;
         final boolean isRingStream = row.stream == AudioManager.STREAM_RING;
         final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
-        final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
+        final boolean isAlarmStream = row.stream == STREAM_ALARM;
         final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC;
         final boolean isRingVibrate = isRingStream
                 && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
@@ -921,6 +978,21 @@
         }
     }
 
+    private Runnable mSinglePress = new Runnable() {
+        @Override
+        public void run() {
+            mRingerIcon.setPressed(true);
+            mRingerIcon.postOnAnimationDelayed(mSingleUnpress, 200);
+        }
+    };
+
+    private Runnable mSingleUnpress = new Runnable() {
+        @Override
+        public void run() {
+            mRingerIcon.setPressed(false);
+        }
+    };
+
     private final VolumeDialogController.Callbacks mControllerCallbackH
             = new VolumeDialogController.Callbacks() {
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
index 173400f..434327c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
@@ -43,7 +43,7 @@
     public static final String PREF_ADJUST_ALARMS = "pref_adjust_alarms";
     public static final String PREF_ADJUST_NOTIFICATION = "pref_adjust_notification";
 
-    public static final int SHOW_RINGER_TOAST_COUNT = 9;
+    public static final int SHOW_RINGER_TOAST_COUNT = 12;
 
     public static final boolean DEFAULT_SHOW_HEADERS = true;
     public static final boolean DEFAULT_ENABLE_AUTOMUTE = true;