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