Display notification effects suppressor in the volume panel.

Bug:16958514

Change-Id: I0eac173875e8af62e3c6b39001722c3fda4517de
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index 7d102ba..600b750 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.content.ComponentName;
 import android.service.notification.Condition;
 
 public interface ZenModeController {
@@ -29,6 +30,7 @@
     long getNextAlarm();
     void setUserId(int userId);
     boolean isZenAvailable();
+    ComponentName getEffectsSuppressor();
 
     public static class Callback {
         public void onZenChanged(int zen) {}
@@ -36,5 +38,6 @@
         public void onConditionsChanged(Condition[] conditions) {}
         public void onNextAlarmChanged() {}
         public void onZenAvailableChanged(boolean available) {}
+        public void onEffectsSupressorChanged() {}
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index b0c8f26..415eb27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -18,7 +18,9 @@
 
 import android.app.AlarmManager;
 import android.app.INotificationManager;
+import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -161,12 +163,23 @@
         mSetupObserver.register();
     }
 
+    @Override
+    public ComponentName getEffectsSuppressor() {
+        return NotificationManager.from(mContext).getEffectsSuppressor();
+    }
+
     private void fireNextAlarmChanged() {
         for (Callback cb : mCallbacks) {
             cb.onNextAlarmChanged();
         }
     }
 
+    private void fireEffectsSuppressorChanged() {
+        for (Callback cb : mCallbacks) {
+            cb.onEffectsSupressorChanged();
+        }
+    }
+
     private void fireZenChanged(int zen) {
         for (Callback cb : mCallbacks) {
             cb.onZenChanged(zen);
@@ -219,6 +232,9 @@
             if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) {
                 fireNextAlarmChanged();
             }
+            if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) {
+                fireEffectsSuppressorChanged();
+            }
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 8a14288..f03c5eb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -19,11 +19,15 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnDismissListener;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -57,6 +61,7 @@
 import android.widget.ImageView;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
 
 import com.android.internal.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -109,6 +114,7 @@
     private static final int MSG_LAYOUT_DIRECTION = 12;
     private static final int MSG_ZEN_MODE_AVAILABLE_CHANGED = 13;
     private static final int MSG_USER_ACTIVITY = 14;
+    private static final int MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED = 15;
 
     // Pseudo stream type for master volume
     private static final int STREAM_MASTER = -100;
@@ -234,8 +240,10 @@
         ViewGroup group;
         ImageView icon;
         SeekBar seekbarView;
+        TextView suppressorView;
         int iconRes;
         int iconMuteRes;
+        int iconSuppressedRes;
     }
 
     // Synchronize when accessing this
@@ -613,8 +621,12 @@
                         toggle(sc);
                     }
                 });
+                sc.iconSuppressedRes = com.android.systemui.R.drawable.ic_ringer_mute;
             }
             sc.seekbarView = (SeekBar) sc.group.findViewById(com.android.systemui.R.id.seekbar);
+            sc.suppressorView =
+                    (TextView) sc.group.findViewById(com.android.systemui.R.id.suppressor);
+            sc.suppressorView.setVisibility(View.GONE);
             final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
                     streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
             sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);
@@ -678,6 +690,40 @@
         sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes);
     }
 
+    private void updateSliderSupressor(StreamControl sc) {
+        final ComponentName suppressor = isNotificationOrRing(sc.streamType)
+                ? mZenController.getEffectsSuppressor() : null;
+        if (suppressor == null) {
+            sc.seekbarView.setVisibility(View.VISIBLE);
+            sc.suppressorView.setVisibility(View.GONE);
+        } else {
+            sc.seekbarView.setVisibility(View.GONE);
+            sc.suppressorView.setVisibility(View.VISIBLE);
+            sc.suppressorView.setText(mContext.getString(com.android.systemui.R.string.muted_by,
+                    getSuppressorCaption(suppressor)));
+            sc.icon.setImageResource(sc.iconSuppressedRes);
+        }
+    }
+
+    private String getSuppressorCaption(ComponentName suppressor) {
+        final PackageManager pm = mContext.getPackageManager();
+        try {
+            final ServiceInfo info = pm.getServiceInfo(suppressor, 0);
+            if (info != null) {
+                final CharSequence seq = info.loadLabel(pm);
+                if (seq != null) {
+                    final String str = seq.toString().trim();
+                    if (str.length() > 0) {
+                        return str;
+                    }
+                }
+            }
+        } catch (Throwable e) {
+            Log.w(TAG, "Error loading suppressor caption", e);
+        }
+        return suppressor.getPackageName();
+    }
+
     /** Update the mute and progress state of a slider */
     private void updateSlider(StreamControl sc) {
         updateSliderProgress(sc, -1);
@@ -686,6 +732,7 @@
         sc.icon.setImageDrawable(null);
         updateSliderIcon(sc, muted);
         updateSliderEnabled(sc, muted, false);
+        updateSliderSupressor(sc);
     }
 
     private void updateSliderEnabled(final StreamControl sc, boolean muted, boolean fixedVolume) {
@@ -1275,7 +1322,9 @@
                 }
                 break;
             }
-            case MSG_RINGER_MODE_CHANGED: {
+
+            case MSG_RINGER_MODE_CHANGED:
+            case MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED: {
                 if (isShowing()) {
                     updateStates();
                 }
@@ -1356,9 +1405,15 @@
     };
 
     private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
+        @Override
         public void onZenAvailableChanged(boolean available) {
             obtainMessage(MSG_ZEN_MODE_AVAILABLE_CHANGED, available ? 1 : 0, 0).sendToTarget();
         }
+        @Override
+        public void onEffectsSupressorChanged() {
+            obtainMessage(MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED,
+                    mZenController.getEffectsSuppressor()).sendToTarget();
+        }
     };
 
     private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {