VolumeZen: Slider icon as ringer-mode toggle.

- When manipulating the ringer/notification stream, the volume
  slider icon on the left now serves as a toggle.  Single-press
  for vibrate, long-press for silent.
- Disable slider when silent.
- Add touch feedback to slider icon when clickable.
- Vibrate when toggling to vibrate.
- Play sound when toggling to audible.
- Adjust the slider icon padding so it appears to be square,
  and the same size as the icon on the right.

Bug:15330217
Change-Id: Id7262d9315e6e761e1d5750714c356c3ac735951
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index cbfc641..7000e82 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -42,6 +42,8 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.view.Window;
@@ -284,7 +286,6 @@
             }
         }
         if (LOGD) Log.d(mTag, String.format("new VolumePanel hasParent=%s", parent != null));
-        final int layoutId = com.android.systemui.R.layout.volume_panel;
         if (parent == null) {
             // dialog mode
             mDialog = new Dialog(context) {
@@ -318,15 +319,7 @@
                     | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                     | LayoutParams.FLAG_HARDWARE_ACCELERATED);
             mDialog.setCanceledOnTouchOutside(true);
-            // temporary workaround for no window shadows
-            final FrameLayout layout = new FrameLayout(mContext);
-            final int z = res.getDimensionPixelSize(com.android.systemui.R.dimen.volume_panel_z);
-            layout.setPadding(z, z, z, z);
-            final View v = LayoutInflater.from(mContext).inflate(layoutId, layout, false);
-            v.setBackgroundResource(com.android.systemui.R.drawable.qs_panel_background);
-            v.setElevation(z);
-            layout.addView(v);
-            mDialog.setContentView(layout);
+            mDialog.setContentView(com.android.systemui.R.layout.volume_dialog);
             mDialog.setOnDismissListener(new OnDismissListener() {
                 @Override
                 public void onDismiss(DialogInterface dialog) {
@@ -336,6 +329,7 @@
             });
 
             mDialog.create();
+            // temporary workaround, until we support window-level shadows
             mDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0x00000000));
 
             mView = window.findViewById(R.id.content);
@@ -350,7 +344,8 @@
         } else {
             // embedded mode
             mDialog = null;
-            mView = LayoutInflater.from(mContext).inflate(layoutId, parent, true);
+            mView = LayoutInflater.from(mContext).inflate(
+                    com.android.systemui.R.layout.volume_panel, parent, true);
         }
         mPanel = (ViewGroup) mView.findViewById(com.android.systemui.R.id.visible_panel);
         mSliderPanel = (ViewGroup) mView.findViewById(com.android.systemui.R.id.slider_panel);
@@ -460,6 +455,24 @@
             sc.iconRes = streamRes.iconRes;
             sc.iconMuteRes = streamRes.iconMuteRes;
             sc.icon.setImageResource(sc.iconRes);
+            sc.icon.setClickable(isNotificationOrRing(streamType));
+            if (sc.icon.isClickable()) {
+                sc.icon.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        resetTimeout();
+                        toggle(sc);
+                    }
+                });
+                sc.icon.setOnLongClickListener(new OnLongClickListener() {
+                    @Override
+                    public boolean onLongClick(View v) {
+                        resetTimeout();
+                        longToggle(sc);
+                        return true;
+                    }
+                });
+            }
             sc.seekbarView = (SeekBar) sc.group.findViewById(com.android.systemui.R.id.seekbar);
             final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
                     streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
@@ -470,6 +483,26 @@
         }
     }
 
+    private void toggle(StreamControl sc) {
+        if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) {
+            mAudioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
+            postVolumeChanged(sc.streamType, AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE);
+        } else {
+            mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+            postVolumeChanged(sc.streamType, AudioManager.FLAG_PLAY_SOUND);
+        }
+    }
+
+    private void longToggle(StreamControl sc) {
+        if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
+            mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+            postVolumeChanged(sc.streamType, AudioManager.FLAG_PLAY_SOUND);
+        } else {
+            mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+            postVolumeChanged(sc.streamType, AudioManager.FLAG_SHOW_UI); // disable the slider
+        }
+    }
+
     private void reorderSliders(int activeStreamType) {
         mSliderPanel.removeAllViews();
 
@@ -493,23 +526,35 @@
         // Force reloading the image resource
         sc.icon.setImageDrawable(null);
         sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes);
-        if (((sc.streamType == AudioManager.STREAM_RING) ||
-                (sc.streamType == AudioManager.STREAM_NOTIFICATION)) &&
+        if (isNotificationOrRing(sc.streamType) &&
                 mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) {
             sc.icon.setImageResource(com.android.systemui.R.drawable.ic_ringer_vibrate);
         }
+        updateSliderEnabled(sc, muted, false);
+    }
+
+    private void updateSliderEnabled(StreamControl sc, boolean muted, boolean fixedVolume) {
         if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {
             // never disable touch interactions for remote playback, the muting is not tied to
             // the state of the phone.
             sc.seekbarView.setEnabled(true);
-        } else if ((sc.streamType != mAudioManager.getMasterStreamType() && muted) ||
+        } else if (fixedVolume ||
+                        (sc.streamType != mAudioManager.getMasterStreamType() && muted) ||
                         (sConfirmSafeVolumeDialog != null)) {
             sc.seekbarView.setEnabled(false);
+        } else if (isNotificationOrRing(sc.streamType)
+                && mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
+            sc.seekbarView.setEnabled(false);
         } else {
             sc.seekbarView.setEnabled(true);
         }
     }
 
+    private static boolean isNotificationOrRing(int streamType) {
+        return streamType == AudioManager.STREAM_RING
+                || streamType == AudioManager.STREAM_NOTIFICATION;
+    }
+
     public void setZenModePanelCallback(ZenModePanel.Callback callback) {
         mZenPanelCallback = callback;
     }
@@ -562,8 +607,7 @@
 
     private void updateZenMode(boolean zen) {
         if (mZenModeCapable) {
-            final boolean show = mActiveStreamType == AudioManager.STREAM_NOTIFICATION
-                    || mActiveStreamType == AudioManager.STREAM_RING;
+            final boolean show = isNotificationOrRing(mActiveStreamType);
             mExpandButton.setVisibility(show ? View.VISIBLE : View.GONE);
             mExpandDivider.setVisibility(show ? View.VISIBLE : View.GONE);
             mExpandButton.setImageResource(zen ? com.android.systemui.R.drawable.ic_vol_zen_on
@@ -790,15 +834,8 @@
             }
 
             sc.seekbarView.setProgress(index);
-            if (((flags & AudioManager.FLAG_FIXED_VOLUME) != 0) ||
-                    (streamType != mAudioManager.getMasterStreamType() &&
-                     streamType != AudioService.STREAM_REMOTE_MUSIC &&
-                     isMuted(streamType)) ||
-                     sConfirmSafeVolumeDialog != null) {
-                sc.seekbarView.setEnabled(false);
-            } else {
-                sc.seekbarView.setEnabled(true);
-            }
+            updateSliderEnabled(sc, isMuted(streamType),
+                    (flags & AudioManager.FLAG_FIXED_VOLUME) != 0);
         }
 
         if (!isShowing()) {
@@ -1173,7 +1210,7 @@
 
     private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
         public void onZenChanged(boolean zen) {
-            updateZenMode(zen);
+            postZenModeChanged(zen);
         }
     };
 }