1 /* 2 * Copyright (C) 2021 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.car.audio; 18 19 import static android.car.media.CarAudioManager.PRIMARY_AUDIO_ZONE; 20 import static android.util.Log.DEBUG; 21 import static android.util.Log.VERBOSE; 22 23 import static com.android.car.CarLog.TAG_AUDIO; 24 25 import android.annotation.NonNull; 26 import android.media.AudioManager; 27 import android.media.audiopolicy.AudioPolicy; 28 import android.media.audiopolicy.AudioPolicy.Builder; 29 import android.util.Log; 30 import android.util.Slog; 31 32 import com.android.car.audio.CarAudioContext.AudioContext; 33 import com.android.internal.annotations.VisibleForTesting; 34 import com.android.server.utils.Slogf; 35 36 37 import java.util.Objects; 38 39 final class CarAudioPolicyVolumeCallback extends AudioPolicy.AudioPolicyVolumeCallback{ 40 private final CarAudioService mCarAudioService; 41 private final AudioManager mAudioManager; 42 private final boolean mUseCarVolumeGroupMuting; 43 addVolumeCallbackToPolicy(@onNull Builder policyBuilder, @NonNull CarAudioService carAudioService, @NonNull AudioManager audioManager, boolean useCarVolumeGroupMuting)44 static void addVolumeCallbackToPolicy(@NonNull Builder policyBuilder, 45 @NonNull CarAudioService carAudioService, 46 @NonNull AudioManager audioManager, boolean useCarVolumeGroupMuting) { 47 Objects.requireNonNull(policyBuilder, "AudioPolicy.Builder cannot be null"); 48 policyBuilder.setAudioPolicyVolumeCallback( 49 new CarAudioPolicyVolumeCallback(carAudioService, audioManager, 50 useCarVolumeGroupMuting)); 51 if (Log.isLoggable(TAG_AUDIO, DEBUG)) { 52 Slog.d(TAG_AUDIO, "Registered car audio policy volume callback"); 53 } 54 } 55 56 @VisibleForTesting CarAudioPolicyVolumeCallback(@onNull CarAudioService carAudioService, @NonNull AudioManager audioManager, boolean useCarVolumeGroupMuting)57 CarAudioPolicyVolumeCallback(@NonNull CarAudioService carAudioService, 58 @NonNull AudioManager audioManager, boolean useCarVolumeGroupMuting) { 59 mCarAudioService = Objects.requireNonNull(carAudioService, 60 "CarAudioService cannot be null"); 61 mAudioManager = Objects.requireNonNull(audioManager, "AudioManager cannot be null"); 62 mUseCarVolumeGroupMuting = useCarVolumeGroupMuting; 63 } 64 65 @Override onVolumeAdjustment(int adjustment)66 public void onVolumeAdjustment(int adjustment) { 67 @AudioContext int suggestedContext = mCarAudioService 68 .getSuggestedAudioContextForPrimaryZone(); 69 70 int zoneId = PRIMARY_AUDIO_ZONE; 71 int groupId = mCarAudioService.getVolumeGroupIdForAudioContext(zoneId, suggestedContext); 72 boolean isMuted = isMuted(zoneId, groupId); 73 74 if (Slogf.isLoggable(TAG_AUDIO, VERBOSE)) { 75 Slogf.v(TAG_AUDIO, "onVolumeAdjustment: " 76 + AudioManager.adjustToString(adjustment) + " suggested audio context: " 77 + CarAudioContext.toString(suggestedContext) + " suggested volume group: " 78 + groupId + " is muted " + isMuted); 79 } 80 81 final int currentVolume = mCarAudioService.getGroupVolume(zoneId, groupId); 82 final int flags = AudioManager.FLAG_FROM_KEY | AudioManager.FLAG_SHOW_UI; 83 int minGain = mCarAudioService.getGroupMinVolume(zoneId, groupId); 84 switch (adjustment) { 85 case AudioManager.ADJUST_LOWER: 86 int minValue = Math.max(currentVolume - 1, minGain); 87 if (isMuted) { 88 minValue = minGain; 89 } 90 mCarAudioService.setGroupVolume(zoneId, groupId, minValue, flags); 91 break; 92 case AudioManager.ADJUST_RAISE: 93 int maxValue = Math.min(currentVolume + 1, 94 mCarAudioService.getGroupMaxVolume(zoneId, groupId)); 95 if (isMuted) { 96 maxValue = minGain; 97 } 98 mCarAudioService.setGroupVolume(zoneId, groupId, maxValue, flags); 99 break; 100 case AudioManager.ADJUST_MUTE: 101 case AudioManager.ADJUST_UNMUTE: 102 setMute(adjustment == AudioManager.ADJUST_MUTE, groupId, flags); 103 break; 104 case AudioManager.ADJUST_TOGGLE_MUTE: 105 setMute(!isMuted, groupId, flags); 106 break; 107 case AudioManager.ADJUST_SAME: 108 default: 109 break; 110 } 111 } 112 isMuted(int zoneId, int groupId)113 private boolean isMuted(int zoneId, int groupId) { 114 if (mUseCarVolumeGroupMuting) { 115 return mCarAudioService.isVolumeGroupMuted(zoneId, groupId); 116 } 117 return mAudioManager.isMasterMute(); 118 } 119 setMute(boolean mute, int groupId, int flags)120 private void setMute(boolean mute, int groupId, int flags) { 121 if (mUseCarVolumeGroupMuting) { 122 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, groupId, mute, flags); 123 return; 124 } 125 mCarAudioService.setMasterMute(mute, flags); 126 } 127 } 128