| /* |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.settings.notification; |
| |
| import android.app.INotificationManager; |
| import android.app.NotificationManager; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.media.AudioManager; |
| import android.os.Binder; |
| import android.os.ServiceManager; |
| import android.os.Vibrator; |
| import android.provider.DeviceConfig; |
| import android.util.Log; |
| |
| import com.android.internal.annotations.VisibleForTesting; |
| import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; |
| |
| import java.util.Objects; |
| |
| /** |
| * Shared functionality and interfaces for volume controllers whose state can change by ringer mode |
| */ |
| public abstract class RingerModeAffectedVolumePreferenceController extends |
| VolumeSeekBarPreferenceController { |
| |
| private final String mTag; |
| |
| protected int mNormalIconId; |
| protected int mVibrateIconId; |
| protected int mSilentIconId; |
| protected int mMuteIcon; |
| |
| protected Vibrator mVibrator; |
| protected int mRingerMode = AudioManager.RINGER_MODE_NORMAL; |
| protected ComponentName mSuppressor; |
| protected boolean mSeparateNotification; |
| protected INotificationManager mNoMan; |
| |
| private static final boolean CONFIG_SEPARATE_NOTIFICATION_DEFAULT_VAL = false; |
| |
| public RingerModeAffectedVolumePreferenceController(Context context, String key, String tag) { |
| super(context, key); |
| mTag = tag; |
| mVibrator = mContext.getSystemService(Vibrator.class); |
| if (mVibrator != null && !mVibrator.hasVibrator()) { |
| mVibrator = null; |
| } |
| } |
| |
| protected void updateEffectsSuppressor() { |
| final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor(); |
| if (Objects.equals(suppressor, mSuppressor)) return; |
| |
| if (mNoMan == null) { |
| mNoMan = INotificationManager.Stub.asInterface( |
| ServiceManager.getService(Context.NOTIFICATION_SERVICE)); |
| } |
| |
| final int hints; |
| try { |
| hints = mNoMan.getHintsFromListenerNoToken(); |
| } catch (android.os.RemoteException ex) { |
| Log.w(mTag, "updateEffectsSuppressor: " + ex.getMessage()); |
| return; |
| } |
| |
| if (hintsMatch(hints)) { |
| mSuppressor = suppressor; |
| if (mPreference != null) { |
| final String text = SuppressorHelper.getSuppressionText(mContext, suppressor); |
| mPreference.setSuppressionText(text); |
| } |
| } |
| } |
| |
| @VisibleForTesting |
| void setPreference(VolumeSeekBarPreference volumeSeekBarPreference) { |
| mPreference = volumeSeekBarPreference; |
| } |
| |
| @VisibleForTesting |
| void setVibrator(Vibrator vibrator) { |
| mVibrator = vibrator; |
| } |
| |
| @Override |
| public boolean isSliceable() { |
| return true; |
| } |
| |
| @Override |
| public boolean isPublicSlice() { |
| return true; |
| } |
| |
| @Override |
| public boolean useDynamicSliceSummary() { |
| return true; |
| } |
| |
| @Override |
| public int getMuteIcon() { |
| return mMuteIcon; |
| } |
| |
| protected boolean isSeparateNotificationConfigEnabled() { |
| return Binder.withCleanCallingIdentity(() |
| -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, |
| SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, |
| CONFIG_SEPARATE_NOTIFICATION_DEFAULT_VAL)); |
| } |
| |
| /** |
| * side effect: updates the cached value of the config |
| * @return has the config changed? |
| */ |
| protected boolean readSeparateNotificationVolumeConfig() { |
| boolean newVal = isSeparateNotificationConfigEnabled(); |
| |
| boolean valueUpdated = newVal != mSeparateNotification; |
| if (valueUpdated) { |
| mSeparateNotification = newVal; |
| } |
| |
| return valueUpdated; |
| } |
| |
| /** |
| * Updates UI Icon in response to ringer mode changes. |
| * @return whether the ringer mode has changed. |
| */ |
| protected boolean updateRingerMode() { |
| final int ringerMode = mHelper.getRingerModeInternal(); |
| if (mRingerMode == ringerMode) { |
| return false; |
| } |
| mRingerMode = ringerMode; |
| selectPreferenceIconState(); |
| return true; |
| } |
| |
| /** |
| * Switching among normal/mute/vibrate |
| */ |
| protected void selectPreferenceIconState() { |
| if (mPreference != null) { |
| if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) { |
| mPreference.showIcon(mNormalIconId); |
| } else { |
| if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE && mVibrator != null) { |
| mMuteIcon = mVibrateIconId; |
| } else { |
| mMuteIcon = mSilentIconId; |
| } |
| mPreference.showIcon(getMuteIcon()); |
| } |
| } |
| } |
| |
| protected abstract boolean hintsMatch(int hints); |
| |
| } |