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.ActivityThread; 20 import android.app.NotificationManager; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.media.AudioManager; 26 import android.os.Binder; 27 import android.os.Handler; 28 import android.os.Looper; 29 import android.os.Message; 30 import android.provider.DeviceConfig; 31 import android.service.notification.NotificationListenerService; 32 33 import androidx.lifecycle.OnLifecycleEvent; 34 35 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; 36 import com.android.settings.R; 37 import com.android.settingslib.core.lifecycle.Lifecycle; 38 39 import java.util.Set; 40 41 /** 42 * This slider represents both ring and notification 43 */ 44 public class RingVolumePreferenceController extends 45 RingerModeAffectedVolumePreferenceController { 46 47 private static final String KEY_RING_VOLUME = "ring_volume"; 48 private static final String TAG = "RingVolumePreferenceController"; 49 50 private final RingReceiver mReceiver = new RingReceiver(); 51 private final H mHandler = new H(); 52 RingVolumePreferenceController(Context context)53 public RingVolumePreferenceController(Context context) { 54 this(context, KEY_RING_VOLUME); 55 } 56 RingVolumePreferenceController(Context context, String key)57 public RingVolumePreferenceController(Context context, String key) { 58 super(context, key, TAG); 59 60 mNormalIconId = R.drawable.ic_notifications; 61 mVibrateIconId = R.drawable.ic_volume_ringer_vibrate; 62 mSilentIconId = R.drawable.ic_notifications_off_24dp; 63 64 mSeparateNotification = isSeparateNotificationConfigEnabled(); 65 updateRingerMode(); 66 } 67 68 /** 69 * As the responsibility of this slider changes, so should its title & icon 70 */ onDeviceConfigChange(DeviceConfig.Properties properties)71 private void onDeviceConfigChange(DeviceConfig.Properties properties) { 72 Set<String> changeSet = properties.getKeyset(); 73 if (changeSet.contains(SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION)) { 74 boolean valueUpdated = readSeparateNotificationVolumeConfig(); 75 if (valueUpdated) { 76 updateEffectsSuppressor(); 77 selectPreferenceIconState(); 78 } 79 } 80 } 81 82 @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) 83 @Override onResume()84 public void onResume() { 85 super.onResume(); 86 mReceiver.register(true); 87 readSeparateNotificationVolumeConfig(); 88 Binder.withCleanCallingIdentity(() 89 -> DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, 90 ActivityThread.currentApplication().getMainExecutor(), this::onDeviceConfigChange)); 91 updateEffectsSuppressor(); 92 selectPreferenceIconState(); 93 94 if (mPreference != null) { 95 mPreference.setVisible(getAvailabilityStatus() == AVAILABLE); 96 } 97 } 98 99 @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) 100 @Override onPause()101 public void onPause() { 102 super.onPause(); 103 mReceiver.register(false); 104 Binder.withCleanCallingIdentity(() -> 105 DeviceConfig.removeOnPropertiesChangedListener(this::onDeviceConfigChange)); 106 } 107 108 @Override getPreferenceKey()109 public String getPreferenceKey() { 110 return KEY_RING_VOLUME; 111 } 112 113 @Override getAvailabilityStatus()114 public int getAvailabilityStatus() { 115 boolean separateNotification = isSeparateNotificationConfigEnabled(); 116 return !separateNotification && !mHelper.isSingleVolume() 117 ? AVAILABLE : UNSUPPORTED_ON_DEVICE; 118 } 119 120 @Override getAudioStream()121 public int getAudioStream() { 122 return AudioManager.STREAM_RING; 123 } 124 125 @Override hintsMatch(int hints)126 protected boolean hintsMatch(int hints) { 127 boolean notificationSeparated = isSeparateNotificationConfigEnabled(); 128 return (hints & NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS) != 0 129 || (hints & NotificationListenerService.HINT_HOST_DISABLE_EFFECTS) != 0 130 || ((hints & NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS) 131 != 0 && !notificationSeparated); 132 } 133 134 135 private final class H extends Handler { 136 private static final int UPDATE_EFFECTS_SUPPRESSOR = 1; 137 private static final int UPDATE_RINGER_MODE = 2; 138 H()139 private H() { 140 super(Looper.getMainLooper()); 141 } 142 143 @Override handleMessage(Message msg)144 public void handleMessage(Message msg) { 145 switch (msg.what) { 146 case UPDATE_EFFECTS_SUPPRESSOR: 147 updateEffectsSuppressor(); 148 break; 149 case UPDATE_RINGER_MODE: 150 updateRingerMode(); 151 break; 152 } 153 } 154 } 155 156 private class RingReceiver extends BroadcastReceiver { 157 private boolean mRegistered; 158 register(boolean register)159 public void register(boolean register) { 160 if (mRegistered == register) return; 161 if (register) { 162 final IntentFilter filter = new IntentFilter(); 163 filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED); 164 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); 165 mContext.registerReceiver(this, filter); 166 } else { 167 mContext.unregisterReceiver(this); 168 } 169 mRegistered = register; 170 } 171 172 @Override onReceive(Context context, Intent intent)173 public void onReceive(Context context, Intent intent) { 174 final String action = intent.getAction(); 175 if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(action)) { 176 mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR); 177 } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { 178 mHandler.sendEmptyMessage(H.UPDATE_RINGER_MODE); 179 } 180 } 181 } 182 183 } 184