diff --git a/res/drawable/ic_audio_alarm_24dp.xml b/res/drawable/ic_audio_alarm_24dp.xml deleted file mode 100644 index ddfaa0136c9..00000000000 --- a/res/drawable/ic_audio_alarm_24dp.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/res/drawable/ic_audio_vol_24dp.xml b/res/drawable/ic_audio_vol_24dp.xml deleted file mode 100644 index ecb3a40793f..00000000000 --- a/res/drawable/ic_audio_vol_24dp.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/res/drawable/ring_notif.xml b/res/drawable/ring_notif.xml deleted file mode 100644 index cc9da31e382..00000000000 --- a/res/drawable/ring_notif.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - diff --git a/res/drawable/ring_notif_mute.xml b/res/drawable/ring_notif_mute.xml deleted file mode 100644 index fe9417d594f..00000000000 --- a/res/drawable/ring_notif_mute.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/res/drawable/ring_notif_vibrate.xml b/res/drawable/ring_notif_vibrate.xml deleted file mode 100644 index 37113d7fa75..00000000000 --- a/res/drawable/ring_notif_vibrate.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/res/layout/preference_volume_slider.xml b/res/layout/preference_volume_slider.xml new file mode 100644 index 00000000000..878a7104cfe --- /dev/null +++ b/res/layout/preference_volume_slider.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/xml/notification_settings.xml b/res/xml/notification_settings.xml index 3f9b40cbe2a..e5dda19080e 100644 --- a/res/xml/notification_settings.xml +++ b/res/xml/notification_settings.xml @@ -27,25 +27,25 @@ diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java index 68994404a76..bd08d8fab81 100644 --- a/src/com/android/settings/notification/NotificationSettings.java +++ b/src/com/android/settings/notification/NotificationSettings.java @@ -16,9 +16,15 @@ package com.android.settings.notification; +import android.app.NotificationManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; import android.database.ContentObserver; import android.database.Cursor; import android.database.sqlite.SQLiteException; @@ -42,7 +48,6 @@ import android.provider.SearchIndexableResource; import android.provider.Settings; import android.util.Log; -import android.widget.SeekBar; import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; @@ -53,6 +58,7 @@ import com.android.settings.search.Indexable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; public class NotificationSettings extends SettingsPreferenceFragment implements Indexable { private static final String TAG = "NotificationSettings"; @@ -75,6 +81,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback(); private final H mHandler = new H(); private final SettingsObserver mSettingsObserver = new SettingsObserver(); + private final Receiver mReceiver = new Receiver(); private Context mContext; private PackageManager mPM; @@ -90,6 +97,8 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private Preference mNotificationAccess; private boolean mSecure; private int mLockscreenSelectedValue; + private ComponentName mSuppressor; + private int mRingOrNotificationProgress; @Override public void onCreate(Bundle savedInstanceState) { @@ -128,6 +137,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS); refreshNotificationListeners(); + updateEffectsSuppressor(); } @Override @@ -136,6 +146,8 @@ public class NotificationSettings extends SettingsPreferenceFragment implements refreshNotificationListeners(); lookupRingtoneNames(); mSettingsObserver.register(true); + mReceiver.register(true); + updateEffectsSuppressor(); } @Override @@ -143,6 +155,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements super.onPause(); mVolumeCallback.stopSample(); mSettingsObserver.register(false); + mReceiver.register(false); } // === Volumes === @@ -154,12 +167,46 @@ public class NotificationSettings extends SettingsPreferenceFragment implements return volumePref; } - private void updateRingOrNotificationIcon(int progress) { - mRingOrNotificationPreference.showIcon(progress > 0 - ? R.drawable.ring_notif - : (mVibrator == null - ? R.drawable.ring_notif_mute - : R.drawable.ring_notif_vibrate)); + private void updateRingOrNotificationIcon() { + mRingOrNotificationPreference.showIcon(mSuppressor != null + ? com.android.internal.R.drawable.ic_audio_ring_notif_mute + : mRingOrNotificationProgress > 0 + ? com.android.internal.R.drawable.ic_audio_ring_notif + : (mVibrator == null + ? com.android.internal.R.drawable.ic_audio_ring_notif_mute + : com.android.internal.R.drawable.ic_audio_ring_notif_vibrate)); + } + + private void updateEffectsSuppressor() { + final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor(); + if (Objects.equals(suppressor, mSuppressor)) return; + mSuppressor = suppressor; + if (mRingOrNotificationPreference != null) { + final String text = suppressor != null ? + mContext.getString(com.android.internal.R.string.muted_by, + getSuppressorCaption(suppressor)) : null; + mRingOrNotificationPreference.setSuppressionText(text); + } + updateRingOrNotificationIcon(); + } + + 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(); } private final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback { @@ -464,6 +511,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements private static final int UPDATE_NOTIFICATION_RINGTONE = 2; private static final int STOP_SAMPLE = 3; private static final int UPDATE_RINGER_ICON = 4; + private static final int UPDATE_EFFECTS_SUPPRESSOR = 5; private H() { super(Looper.getMainLooper()); @@ -482,12 +530,36 @@ public class NotificationSettings extends SettingsPreferenceFragment implements mVolumeCallback.stopSample(); break; case UPDATE_RINGER_ICON: - updateRingOrNotificationIcon(msg.arg1); + mRingOrNotificationProgress = msg.arg1; + updateRingOrNotificationIcon(); + break; + case UPDATE_EFFECTS_SUPPRESSOR: + updateEffectsSuppressor(); break; } } } + private class Receiver extends BroadcastReceiver { + private boolean mRegistered; + + public void register(boolean register) { + if (mRegistered == register) return; + if (register) { + mContext.registerReceiver(this, + new IntentFilter(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)); + } else { + mContext.unregisterReceiver(this); + } + mRegistered = register; + } + + @Override + public void onReceive(Context context, Intent intent) { + mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR); + } + } + // === Indexing === public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java index f391f86b350..0fdcc199c4c 100644 --- a/src/com/android/settings/notification/VolumeSeekBarPreference.java +++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java @@ -23,14 +23,18 @@ import android.net.Uri; import android.preference.PreferenceManager; import android.preference.SeekBarPreference; import android.preference.SeekBarVolumizer; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.SeekBar; +import android.widget.TextView; import com.android.settings.R; +import java.util.Objects; + /** A slider preference that directly controls an audio stream volume (no dialog) **/ public class VolumeSeekBarPreference extends SeekBarPreference implements PreferenceManager.OnActivityStopListener { @@ -41,10 +45,13 @@ public class VolumeSeekBarPreference extends SeekBarPreference private SeekBarVolumizer mVolumizer; private Callback mCallback; private ImageView mIconView; + private TextView mSuppressionTextView; + private String mSuppressionText; public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + setLayoutResource(R.layout.preference_volume_slider); } public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) { @@ -108,13 +115,14 @@ public class VolumeSeekBarPreference extends SeekBarPreference mVolumizer.start(); mVolumizer.setSeekBar(mSeekBar); mIconView = (ImageView) view.findViewById(com.android.internal.R.id.icon); + mSuppressionTextView = (TextView) view.findViewById(R.id.suppression_text); mCallback.onStreamValueChanged(mStream, mSeekBar.getProgress()); + updateSuppressionText(); } // during initialization, this preference is the SeekBar listener @Override - public void onProgressChanged(SeekBar seekBar, int progress, - boolean fromTouch) { + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { super.onProgressChanged(seekBar, progress, fromTouch); mCallback.onStreamValueChanged(mStream, progress); } @@ -133,6 +141,21 @@ public class VolumeSeekBarPreference extends SeekBarPreference + "/" + R.raw.media_volume); } + public void setSuppressionText(String text) { + if (Objects.equals(text, mSuppressionText)) return; + mSuppressionText = text; + updateSuppressionText(); + } + + private void updateSuppressionText() { + if (mSuppressionTextView != null && mSeekBar != null) { + mSuppressionTextView.setText(mSuppressionText); + final boolean showSuppression = !TextUtils.isEmpty(mSuppressionText); + mSuppressionTextView.setVisibility(showSuppression ? View.VISIBLE : View.INVISIBLE); + mSeekBar.setVisibility(showSuppression ? View.INVISIBLE : View.VISIBLE); + } + } + public interface Callback { void onSampleStarting(SeekBarVolumizer sbv); void onStreamValueChanged(int stream, int progress);