1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.notification; 18 19 import android.app.NotificationManager; 20 import android.content.BroadcastReceiver; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.pm.PackageManager; 26 import android.content.pm.ServiceInfo; 27 import android.media.AudioManager; 28 import android.os.Handler; 29 import android.os.Looper; 30 import android.os.Message; 31 import android.os.Vibrator; 32 import android.util.Log; 33 34 import com.android.internal.annotations.VisibleForTesting; 35 import com.android.settings.Utils; 36 import com.android.settings.core.lifecycle.Lifecycle; 37 import com.android.settings.notification.VolumeSeekBarPreference.Callback; 38 39 import java.util.Objects; 40 41 public class RingVolumePreferenceController extends VolumeSeekBarPreferenceController { 42 43 private static final String TAG = "RingVolumeController"; 44 private static final String KEY_RING_VOLUME = "ring_volume"; 45 46 private AudioManager mAudioManager; 47 private Vibrator mVibrator; 48 private int mRingerMode = -1; 49 private ComponentName mSuppressor; 50 private final RingReceiver mReceiver = new RingReceiver(); 51 private final H mHandler = new H(); 52 private AudioHelper mHelper; 53 RingVolumePreferenceController(Context context, Callback callback, Lifecycle lifecycle)54 public RingVolumePreferenceController(Context context, Callback callback, Lifecycle lifecycle) { 55 this(context, callback, lifecycle, new AudioHelper(context)); 56 } 57 58 @VisibleForTesting RingVolumePreferenceController(Context context, Callback callback, Lifecycle lifecycle, AudioHelper helper)59 RingVolumePreferenceController(Context context, Callback callback, Lifecycle lifecycle, 60 AudioHelper helper) { 61 super(context, callback, lifecycle); 62 mHelper = helper; 63 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 64 mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); 65 if (mVibrator != null && !mVibrator.hasVibrator()) { 66 mVibrator = null; 67 } 68 updateRingerMode(); 69 } 70 71 @Override onResume()72 public void onResume() { 73 super.onResume(); 74 mReceiver.register(true); 75 updateEffectsSuppressor(); 76 updatePreferenceIcon(); 77 } 78 79 @Override onPause()80 public void onPause() { 81 super.onPause(); 82 mReceiver.register(false); 83 } 84 85 @Override getPreferenceKey()86 public String getPreferenceKey() { 87 return KEY_RING_VOLUME; 88 } 89 90 @Override isAvailable()91 public boolean isAvailable() { 92 return Utils.isVoiceCapable(mContext) && !mHelper.isSingleVolume(); 93 } 94 95 @Override getAudioStream()96 public int getAudioStream() { 97 return AudioManager.STREAM_RING; 98 } 99 100 @Override getMuteIcon()101 public int getMuteIcon() { 102 return com.android.internal.R.drawable.ic_audio_ring_notif_mute; 103 } 104 updateRingerMode()105 private void updateRingerMode() { 106 final int ringerMode = mAudioManager.getRingerModeInternal(); 107 if (mRingerMode == ringerMode) return; 108 mRingerMode = ringerMode; 109 updatePreferenceIcon(); 110 } 111 wasRingerModeVibrate()112 private boolean wasRingerModeVibrate() { 113 return mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_SILENT 114 && mAudioManager.getLastAudibleStreamVolume(AudioManager.STREAM_RING) == 0; 115 } 116 updateEffectsSuppressor()117 private void updateEffectsSuppressor() { 118 final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor(); 119 if (Objects.equals(suppressor, mSuppressor)) return; 120 mSuppressor = suppressor; 121 if (mPreference != null) { 122 final String text = SuppressorHelper.getSuppressionText(mContext, suppressor); 123 mPreference.setSuppressionText(text); 124 } 125 updatePreferenceIcon(); 126 } 127 updatePreferenceIcon()128 private void updatePreferenceIcon() { 129 if (mPreference != null) { 130 mPreference.showIcon(mSuppressor != null 131 ? com.android.internal.R.drawable.ic_audio_ring_notif_mute 132 : mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate() 133 ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate 134 : com.android.internal.R.drawable.ic_audio_ring_notif); 135 } 136 } 137 138 private final class H extends Handler { 139 private static final int UPDATE_EFFECTS_SUPPRESSOR = 1; 140 private static final int UPDATE_RINGER_MODE = 2; 141 H()142 private H() { 143 super(Looper.getMainLooper()); 144 } 145 146 @Override handleMessage(Message msg)147 public void handleMessage(Message msg) { 148 switch (msg.what) { 149 case UPDATE_EFFECTS_SUPPRESSOR: 150 updateEffectsSuppressor(); 151 break; 152 case UPDATE_RINGER_MODE: 153 updateRingerMode(); 154 break; 155 } 156 } 157 } 158 159 private class RingReceiver extends BroadcastReceiver { 160 private boolean mRegistered; 161 register(boolean register)162 public void register(boolean register) { 163 if (mRegistered == register) return; 164 if (register) { 165 final IntentFilter filter = new IntentFilter(); 166 filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED); 167 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); 168 mContext.registerReceiver(this, filter); 169 } else { 170 mContext.unregisterReceiver(this); 171 } 172 mRegistered = register; 173 } 174 175 @Override onReceive(Context context, Intent intent)176 public void onReceive(Context context, Intent intent) { 177 final String action = intent.getAction(); 178 if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(action)) { 179 mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR); 180 } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { 181 mHandler.sendEmptyMessage(H.UPDATE_RINGER_MODE); 182 } 183 } 184 } 185 186 } 187