diff options
| author | 2023-05-11 12:15:01 +0000 | |
|---|---|---|
| committer | 2023-05-11 12:15:01 +0000 | |
| commit | 457e90a46c13fe4d2fc1502de0e3ca12a9540c6a (patch) | |
| tree | b005896c3ca37a1bdb7e12e807a9efbf4928b7eb | |
| parent | b6426114bd37681525d1322f7c9547422a524452 (diff) | |
| parent | 7298a68a881dfd9b89593f970fc8155da9309a61 (diff) | |
Merge changes from topic "adjust-only-avb" into udc-dev
* changes:
Check for feature flag for numeric volume UI
Implement soundbar volume UI for TV panels.
Add wrapper for AudioManager, allowing it to be faked in tests
Rename "Absolute Volume Control" to "absolute volume behavior"
Fix system server crash on receiving <Report Audio Status>
48 files changed, 1396 insertions, 799 deletions
diff --git a/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java b/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java index d7563e085e61..d764ec41b3b9 100644 --- a/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java +++ b/services/core/java/com/android/server/hdmi/AbsoluteVolumeAudioStatusAction.java @@ -17,11 +17,14 @@ package com.android.server.hdmi; /** - * Action to query and track the audio status of the System Audio device when enabling or using - * Absolute Volume Control. Must be removed when AVC is disabled. Performs two main functions: - * 1. When enabling AVC: queries the starting audio status of the System Audio device and - * enables the feature upon receiving a response. - * 2. While AVC is enabled: monitors <Report Audio Status> messages from the System Audio device and + * Action to query and track the audio status of the System Audio device when using + * absolute volume behavior, or adjust-only absolute volume behavior. Must be removed when + * neither behavior is used. + * + * Performs two main functions: + * 1. When enabling AVB: queries the starting audio status of the System Audio device and + * adopts the appropriate volume behavior upon receiving a response. + * 2. While AVB is enabled: monitors <Report Audio Status> messages from the System Audio device and * notifies AudioService if the audio status changes. */ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { @@ -74,16 +77,23 @@ final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction { boolean mute = HdmiUtils.isAudioStatusMute(cmd); int volume = HdmiUtils.getAudioStatusVolume(cmd); + + // If the volume is out of range, report it as handled and ignore the message. + // According to the spec, such values are either reserved or indicate an unknown volume. + if (volume == Constants.UNKNOWN_VOLUME) { + return true; + } + AudioStatus audioStatus = new AudioStatus(volume, mute); if (mState == STATE_WAIT_FOR_INITIAL_AUDIO_STATUS) { - localDevice().getService().enableAbsoluteVolumeControl(audioStatus); + localDevice().getService().enableAbsoluteVolumeBehavior(audioStatus); mState = STATE_MONITOR_AUDIO_STATUS; } else if (mState == STATE_MONITOR_AUDIO_STATUS) { if (audioStatus.getVolume() != mLastAudioStatus.getVolume()) { - localDevice().getService().notifyAvcVolumeChange(audioStatus.getVolume()); + localDevice().getService().notifyAvbVolumeChange(audioStatus.getVolume()); } if (audioStatus.getMute() != mLastAudioStatus.getMute()) { - localDevice().getService().notifyAvcMuteChange(audioStatus.getMute()); + localDevice().getService().notifyAvbMuteChange(audioStatus.getMute()); } } mLastAudioStatus = audioStatus; diff --git a/services/core/java/com/android/server/hdmi/AudioDeviceVolumeManagerWrapper.java b/services/core/java/com/android/server/hdmi/AudioDeviceVolumeManagerWrapper.java index 438c1ea01e29..94842041af82 100644 --- a/services/core/java/com/android/server/hdmi/AudioDeviceVolumeManagerWrapper.java +++ b/services/core/java/com/android/server/hdmi/AudioDeviceVolumeManagerWrapper.java @@ -16,9 +16,11 @@ package com.android.server.hdmi; +import static android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener; +import static android.media.AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener; + import android.annotation.CallbackExecutor; import android.annotation.NonNull; -import android.content.Context; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceVolumeManager; import android.media.VolumeInfo; @@ -26,42 +28,48 @@ import android.media.VolumeInfo; import java.util.concurrent.Executor; /** - * Wrapper for {@link AudioDeviceVolumeManager}. Creates an instance of the class and directly - * passes method calls to that instance. + * Interface with the methods from {@link AudioDeviceVolumeManager} used by the HDMI framework. + * Allows the class to be faked for tests. + * + * See implementations {@link DefaultAudioDeviceVolumeManagerWrapper} and + * {@link FakeAudioFramework.FakeAudioDeviceVolumeManagerWrapper}. */ -public class AudioDeviceVolumeManagerWrapper - implements AudioDeviceVolumeManagerWrapperInterface { +public interface AudioDeviceVolumeManagerWrapper { - private static final String TAG = "AudioDeviceVolumeManagerWrapper"; - - private final AudioDeviceVolumeManager mAudioDeviceVolumeManager; + /** + * Wrapper for {@link AudioDeviceVolumeManager#addOnDeviceVolumeBehaviorChangedListener( + * Executor, OnDeviceVolumeBehaviorChangedListener)} + */ + void addOnDeviceVolumeBehaviorChangedListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener); - public AudioDeviceVolumeManagerWrapper(Context context) { - mAudioDeviceVolumeManager = new AudioDeviceVolumeManager(context); - } + /** + * Wrapper for {@link AudioDeviceVolumeManager#removeOnDeviceVolumeBehaviorChangedListener( + * OnDeviceVolumeBehaviorChangedListener)} + */ + void removeOnDeviceVolumeBehaviorChangedListener( + @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener); - @Override - public void addOnDeviceVolumeBehaviorChangedListener( + /** + * Wrapper for {@link AudioDeviceVolumeManager#setDeviceAbsoluteVolumeBehavior( + * AudioDeviceAttributes, VolumeInfo, Executor, OnAudioDeviceVolumeChangedListener, boolean)} + */ + void setDeviceAbsoluteVolumeBehavior( + @NonNull AudioDeviceAttributes device, + @NonNull VolumeInfo volume, @NonNull @CallbackExecutor Executor executor, - @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener) - throws SecurityException { - mAudioDeviceVolumeManager.addOnDeviceVolumeBehaviorChangedListener(executor, listener); - } - - @Override - public void removeOnDeviceVolumeBehaviorChangedListener( - @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener) { - mAudioDeviceVolumeManager.removeOnDeviceVolumeBehaviorChangedListener(listener); - } + @NonNull AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener vclistener, + boolean handlesVolumeAdjustment); - @Override - public void setDeviceAbsoluteVolumeBehavior( + /** + * Wrapper for {@link AudioDeviceVolumeManager#setDeviceAbsoluteVolumeAdjustOnlyBehavior( + * AudioDeviceAttributes, VolumeInfo, Executor, OnAudioDeviceVolumeChangedListener, boolean)} + */ + void setDeviceAbsoluteVolumeAdjustOnlyBehavior( @NonNull AudioDeviceAttributes device, @NonNull VolumeInfo volume, @NonNull @CallbackExecutor Executor executor, @NonNull AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener vclistener, - boolean handlesVolumeAdjustment) { - mAudioDeviceVolumeManager.setDeviceAbsoluteVolumeBehavior(device, volume, executor, - vclistener, handlesVolumeAdjustment); - } + boolean handlesVolumeAdjustment); } diff --git a/services/core/java/com/android/server/hdmi/AudioDeviceVolumeManagerWrapperInterface.java b/services/core/java/com/android/server/hdmi/AudioDeviceVolumeManagerWrapperInterface.java deleted file mode 100644 index 1a1d4c19358b..000000000000 --- a/services/core/java/com/android/server/hdmi/AudioDeviceVolumeManagerWrapperInterface.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.server.hdmi; - -import static android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener; -import static android.media.AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener; - -import android.annotation.CallbackExecutor; -import android.annotation.NonNull; -import android.media.AudioDeviceAttributes; -import android.media.AudioDeviceVolumeManager; -import android.media.VolumeInfo; - -import java.util.concurrent.Executor; - -/** - * Interface with the methods from {@link AudioDeviceVolumeManager} used by the HDMI framework. - * Allows the class to be faked for tests. - */ -public interface AudioDeviceVolumeManagerWrapperInterface { - - /** - * Wrapper for {@link AudioDeviceVolumeManager#addOnDeviceVolumeBehaviorChangedListener( - * Executor, OnDeviceVolumeBehaviorChangedListener)} - */ - void addOnDeviceVolumeBehaviorChangedListener( - @NonNull @CallbackExecutor Executor executor, - @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener); - - /** - * Wrapper for {@link AudioDeviceVolumeManager#removeOnDeviceVolumeBehaviorChangedListener( - * OnDeviceVolumeBehaviorChangedListener)} - */ - void removeOnDeviceVolumeBehaviorChangedListener( - @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener); - - /** - * Wrapper for {@link AudioDeviceVolumeManager#setDeviceAbsoluteVolumeBehavior( - * AudioDeviceAttributes, VolumeInfo, Executor, OnAudioDeviceVolumeChangedListener, boolean)} - */ - void setDeviceAbsoluteVolumeBehavior( - @NonNull AudioDeviceAttributes device, - @NonNull VolumeInfo volume, - @NonNull @CallbackExecutor Executor executor, - @NonNull AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener vclistener, - boolean handlesVolumeAdjustment); -} diff --git a/services/core/java/com/android/server/hdmi/AudioManagerWrapper.java b/services/core/java/com/android/server/hdmi/AudioManagerWrapper.java new file mode 100644 index 000000000000..fd4dd516fd51 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/AudioManagerWrapper.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2023 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.server.hdmi; + +import android.annotation.NonNull; +import android.media.AudioAttributes; +import android.media.AudioDeviceAttributes; +import android.media.AudioDeviceVolumeManager; +import android.media.AudioManager; + +import java.util.List; + +/** + * Interface with the methods from {@link AudioDeviceVolumeManager} used by the HDMI control + * framework. Allows the class to be faked for tests. + * + * See implementations {@link DefaultAudioManagerWrapper} and + * {@link FakeAudioFramework.FakeAudioManagerWrapper}. + */ +public interface AudioManagerWrapper { + + /** + * Wraps {@link AudioManager#adjustStreamVolume(int, int, int)} + */ + void adjustStreamVolume(int streamType, int direction, + @AudioManager.PublicVolumeFlags int flags); + + /** + * Wraps {@link AudioManager#setStreamVolume(int, int, int)} + */ + void setStreamVolume(int streamType, int index, @AudioManager.PublicVolumeFlags int flags); + + /** + * Wraps {@link AudioManager#getStreamVolume(int)} + */ + int getStreamVolume(int streamType); + + /** + * Wraps {@link AudioManager#getStreamMinVolume(int)} + */ + int getStreamMinVolume(int streamType); + + /** + * Wraps {@link AudioManager#getStreamMaxVolume(int)} + */ + int getStreamMaxVolume(int streamType); + + /** + * Wraps {@link AudioManager#isStreamMute(int)} + */ + boolean isStreamMute(int streamType); + + /** + * Wraps {@link AudioManager#setStreamMute(int, boolean)} + */ + void setStreamMute(int streamType, boolean state); + + /** + * Wraps {@link AudioManager#setHdmiSystemAudioSupported(boolean)} + */ + int setHdmiSystemAudioSupported(boolean on); + + /** + * Wraps {@link AudioManager#setWiredDeviceConnectionState(AudioDeviceAttributes, int)} + */ + void setWiredDeviceConnectionState(AudioDeviceAttributes attributes, int state); + + /** + * Wraps {@link AudioManager#setWiredDeviceConnectionState(int, int, String, String)} + */ + void setWiredDeviceConnectionState(int device, int state, String address, String name); + + /** + * Wraps {@link AudioManager#getDeviceVolumeBehavior(AudioDeviceAttributes)} + */ + @AudioManager.DeviceVolumeBehavior + int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device); + + /** + * Wraps {@link AudioManager#setDeviceVolumeBehavior(AudioDeviceAttributes, int)} + */ + void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, + @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior); + + /** + * Wraps {@link AudioManager#getDevicesForAttributes(AudioAttributes)} + */ + @NonNull + List<AudioDeviceAttributes> getDevicesForAttributes( + @NonNull AudioAttributes attributes); +} diff --git a/services/core/java/com/android/server/hdmi/AudioStatus.java b/services/core/java/com/android/server/hdmi/AudioStatus.java index a884ffb93a6d..6242c45e8262 100644 --- a/services/core/java/com/android/server/hdmi/AudioStatus.java +++ b/services/core/java/com/android/server/hdmi/AudioStatus.java @@ -23,6 +23,8 @@ import java.util.Objects; /** * Immutable representation of the information in the [Audio Status] operand: * volume status (0 <= N <= 100) and mute status (muted or unmuted). + * The volume level is limited to the range [0, 100] upon construction. + * This object cannot represent an audio status where the volume is unknown, or out of bounds. */ public class AudioStatus { public static final int MAX_VOLUME = 100; @@ -32,7 +34,7 @@ public class AudioStatus { boolean mMute; public AudioStatus(int volume, boolean mute) { - mVolume = volume; + mVolume = Math.max(Math.min(volume, MAX_VOLUME), MIN_VOLUME); mMute = mute; } diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index c235299e3a65..090d728aedc8 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -631,10 +631,14 @@ final class Constants { static final String DEVICE_CONFIG_FEATURE_FLAG_ENABLE_EARC_TX = "enable_earc_tx"; static final String DEVICE_CONFIG_FEATURE_FLAG_TRANSITION_ARC_TO_EARC_TX = "transition_arc_to_earc_tx"; + // Name is abbreviated slightly to avoid line length issues + static final String DEVICE_CONFIG_FEATURE_FLAG_TV_NUMERIC_SOUNDBAR_VOLUME_UI = + "enable_numeric_soundbar_volume_ui_on_tv"; @StringDef({ DEVICE_CONFIG_FEATURE_FLAG_SOUNDBAR_MODE, DEVICE_CONFIG_FEATURE_FLAG_ENABLE_EARC_TX, - DEVICE_CONFIG_FEATURE_FLAG_TRANSITION_ARC_TO_EARC_TX + DEVICE_CONFIG_FEATURE_FLAG_TRANSITION_ARC_TO_EARC_TX, + DEVICE_CONFIG_FEATURE_FLAG_TV_NUMERIC_SOUNDBAR_VOLUME_UI }) @interface FeatureFlag {} diff --git a/services/core/java/com/android/server/hdmi/DefaultAudioDeviceVolumeManagerWrapper.java b/services/core/java/com/android/server/hdmi/DefaultAudioDeviceVolumeManagerWrapper.java new file mode 100644 index 000000000000..ff99ace38ef0 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/DefaultAudioDeviceVolumeManagerWrapper.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2023 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.server.hdmi; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.content.Context; +import android.media.AudioDeviceAttributes; +import android.media.AudioDeviceVolumeManager; +import android.media.VolumeInfo; + +import java.util.concurrent.Executor; + +/** + * "Default" wrapper for {@link AudioDeviceVolumeManager}, as opposed to a "Fake" wrapper for + * testing - see {@link FakeAudioFramework.FakeAudioDeviceVolumeManagerWrapper}. + * + * Creates an instance of {@link AudioDeviceVolumeManager} and directly passes method calls + * to that instance. + */ +public class DefaultAudioDeviceVolumeManagerWrapper + implements AudioDeviceVolumeManagerWrapper { + + private static final String TAG = "AudioDeviceVolumeManagerWrapper"; + + private final AudioDeviceVolumeManager mAudioDeviceVolumeManager; + + public DefaultAudioDeviceVolumeManagerWrapper(Context context) { + mAudioDeviceVolumeManager = new AudioDeviceVolumeManager(context); + } + + @Override + public void addOnDeviceVolumeBehaviorChangedListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener) + throws SecurityException { + mAudioDeviceVolumeManager.addOnDeviceVolumeBehaviorChangedListener(executor, listener); + } + + @Override + public void removeOnDeviceVolumeBehaviorChangedListener( + @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener) { + mAudioDeviceVolumeManager.removeOnDeviceVolumeBehaviorChangedListener(listener); + } + + @Override + public void setDeviceAbsoluteVolumeBehavior( + @NonNull AudioDeviceAttributes device, + @NonNull VolumeInfo volume, + @NonNull @CallbackExecutor Executor executor, + @NonNull AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener vclistener, + boolean handlesVolumeAdjustment) { + mAudioDeviceVolumeManager.setDeviceAbsoluteVolumeBehavior(device, volume, executor, + vclistener, handlesVolumeAdjustment); + } + + @Override + public void setDeviceAbsoluteVolumeAdjustOnlyBehavior( + @NonNull AudioDeviceAttributes device, + @NonNull VolumeInfo volume, + @NonNull @CallbackExecutor Executor executor, + @NonNull AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener vclistener, + boolean handlesVolumeAdjustment) { + mAudioDeviceVolumeManager.setDeviceAbsoluteVolumeAdjustOnlyBehavior(device, volume, + executor, vclistener, handlesVolumeAdjustment); + } +} diff --git a/services/core/java/com/android/server/hdmi/DefaultAudioManagerWrapper.java b/services/core/java/com/android/server/hdmi/DefaultAudioManagerWrapper.java new file mode 100644 index 000000000000..061e145c27f3 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/DefaultAudioManagerWrapper.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2023 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.server.hdmi; + +import android.annotation.NonNull; +import android.content.Context; +import android.media.AudioAttributes; +import android.media.AudioDeviceAttributes; +import android.media.AudioManager; + +import java.util.List; + +/** + * "Default" wrapper for {@link AudioManager}, as opposed to a "Fake" wrapper for testing - + * see {@link FakeAudioFramework.FakeAudioManagerWrapper}. + * + * Creates an instance of {@link AudioManager} and directly passes method calls to that instance. + * +*/ +public class DefaultAudioManagerWrapper implements AudioManagerWrapper { + + private static final String TAG = "DefaultAudioManagerWrapper"; + + private final AudioManager mAudioManager; + + public DefaultAudioManagerWrapper(Context context) { + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + } + + @Override + public void adjustStreamVolume(int streamType, int direction, + @AudioManager.PublicVolumeFlags int flags) { + mAudioManager.adjustStreamVolume(streamType, direction, flags); + } + + @Override + public void setStreamVolume(int streamType, int index, + @AudioManager.PublicVolumeFlags int flags) { + mAudioManager.setStreamVolume(streamType, index, flags); + } + + @Override + public int getStreamVolume(int streamType) { + return mAudioManager.getStreamVolume(streamType); + } + + @Override + public int getStreamMinVolume(int streamType) { + return mAudioManager.getStreamMinVolume(streamType); + } + + @Override + public int getStreamMaxVolume(int streamType) { + return mAudioManager.getStreamMaxVolume(streamType); + } + + @Override + public boolean isStreamMute(int streamType) { + return mAudioManager.isStreamMute(streamType); + } + + @Override + public void setStreamMute(int streamType, boolean state) { + mAudioManager.setStreamMute(streamType, state); + } + + @Override + public int setHdmiSystemAudioSupported(boolean on) { + return mAudioManager.setHdmiSystemAudioSupported(on); + } + + @Override + public void setWiredDeviceConnectionState(AudioDeviceAttributes attributes, int state) { + mAudioManager.setWiredDeviceConnectionState(attributes, state); + } + + @Override + public void setWiredDeviceConnectionState(int device, int state, String address, String name) { + mAudioManager.setWiredDeviceConnectionState(device, state, address, name); + } + + @Override + @AudioManager.DeviceVolumeBehavior + public int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { + return mAudioManager.getDeviceVolumeBehavior(device); + } + + @Override + public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, + @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior) { + mAudioManager.setDeviceVolumeBehavior(device, deviceVolumeBehavior); + } + + @Override + @NonNull + public List<AudioDeviceAttributes> getDevicesForAttributes( + @NonNull AudioAttributes attributes) { + return mAudioManager.getDevicesForAttributes(attributes); + } + +} diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 35c70fbce8ad..f37ad5ed7049 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -1012,17 +1012,23 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice { action.start(); } - void addAvcAudioStatusAction(int targetAddress) { + @ServiceThreadOnly + void addAvbAudioStatusAction(int targetAddress) { + assertRunOnServiceThread(); if (!hasAction(AbsoluteVolumeAudioStatusAction.class)) { addAndStartAction(new AbsoluteVolumeAudioStatusAction(this, targetAddress)); } } - void removeAvcAudioStatusAction() { + @ServiceThreadOnly + void removeAvbAudioStatusAction() { + assertRunOnServiceThread(); removeAction(AbsoluteVolumeAudioStatusAction.class); } - void updateAvcVolume(int volumeIndex) { + @ServiceThreadOnly + void updateAvbVolume(int volumeIndex) { + assertRunOnServiceThread(); for (AbsoluteVolumeAudioStatusAction action : getActions(AbsoluteVolumeAudioStatusAction.class)) { action.updateVolume(volumeIndex); @@ -1035,7 +1041,7 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice { * and send <Set Audio Volume Level> (to see if it gets a <Feature Abort> in response). */ @ServiceThreadOnly - void queryAvcSupport(int targetAddress) { + void querySetAudioVolumeLevelSupport(int targetAddress) { assertRunOnServiceThread(); // Send <Give Features> if using CEC 2.0 or above. @@ -1054,7 +1060,7 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice { @Override public void onComplete(int result) { if (result == HdmiControlManager.RESULT_SUCCESS) { - getService().checkAndUpdateAbsoluteVolumeControlState(); + getService().checkAndUpdateAbsoluteVolumeBehavior(); } } })); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index f47c4b2c24d9..5ef06f9f8967 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -66,7 +66,7 @@ import java.util.stream.Collectors; /** * Represent a logical device of type TV residing in Android system. */ -final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { +public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { private static final String TAG = "HdmiCecLocalDeviceTv"; // Whether ARC is available or not. "true" means that ARC is established between TV and diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java index 18a69c8e9d81..7045e65a8936 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java @@ -259,7 +259,7 @@ public class HdmiCecNetwork { // The addition of a local device should not notify listeners return; } - mHdmiControlService.checkAndUpdateAbsoluteVolumeControlState(); + mHdmiControlService.checkAndUpdateAbsoluteVolumeBehavior(); if (info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) { // Don't notify listeners of devices that haven't reported their physical address yet return; @@ -384,7 +384,7 @@ public class HdmiCecNetwork { final void removeCecDevice(HdmiCecLocalDevice localDevice, int address) { assertRunOnServiceThread(); HdmiDeviceInfo info = removeDeviceInfo(HdmiDeviceInfo.idForCecDevice(address)); - mHdmiControlService.checkAndUpdateAbsoluteVolumeControlState(); + mHdmiControlService.checkAndUpdateAbsoluteVolumeBehavior(); localDevice.mCecMessageCache.flushMessagesFrom(address); if (info.getPhysicalAddress() == HdmiDeviceInfo.PATH_INVALID) { // Don't notify listeners of devices that haven't reported their physical address yet @@ -592,7 +592,7 @@ public class HdmiCecNetwork { updateCecDevice(newDeviceInfo); - mHdmiControlService.checkAndUpdateAbsoluteVolumeControlState(); + mHdmiControlService.checkAndUpdateAbsoluteVolumeBehavior(); } @ServiceThreadOnly @@ -625,7 +625,7 @@ public class HdmiCecNetwork { .build(); updateCecDevice(newDeviceInfo); - mHdmiControlService.checkAndUpdateAbsoluteVolumeControlState(); + mHdmiControlService.checkAndUpdateAbsoluteVolumeBehavior(); } } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 9cd5272b356b..e87ed0a32a97 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -231,8 +231,8 @@ public class HdmiControlService extends SystemService { new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_HDMI_EARC, ""); - // Audio output devices used for Absolute Volume Control - private static final List<AudioDeviceAttributes> AVC_AUDIO_OUTPUT_DEVICES = + // Audio output devices used for absolute volume behavior + private static final List<AudioDeviceAttributes> AVB_AUDIO_OUTPUT_DEVICES = Collections.unmodifiableList(Arrays.asList(AUDIO_OUTPUT_DEVICE_HDMI, AUDIO_OUTPUT_DEVICE_HDMI_ARC, AUDIO_OUTPUT_DEVICE_HDMI_EARC)); @@ -265,7 +265,7 @@ public class HdmiControlService extends SystemService { @HdmiControlManager.VolumeControl private int mHdmiCecVolumeControl; - // Caches the volume behaviors of all audio output devices in AVC_AUDIO_OUTPUT_DEVICES. + // Caches the volume behaviors of all audio output devices in AVB_AUDIO_OUTPUT_DEVICES. @GuardedBy("mLock") private Map<AudioDeviceAttributes, Integer> mAudioDeviceVolumeBehaviors = new HashMap<>(); @@ -458,6 +458,9 @@ public class HdmiControlService extends SystemService { private boolean mEarcTxFeatureFlagEnabled = false; @ServiceThreadOnly + private boolean mNumericSoundbarVolumeUiOnTvFeatureFlagEnabled = false; + + @ServiceThreadOnly private boolean mTransitionFromArcToEarcTxEnabled = false; @ServiceThreadOnly @@ -491,10 +494,10 @@ public class HdmiControlService extends SystemService { private PowerManagerInternalWrapper mPowerManagerInternal; @Nullable - private AudioManager mAudioManager; + private AudioManagerWrapper mAudioManager; @Nullable - private AudioDeviceVolumeManagerWrapperInterface mAudioDeviceVolumeManager; + private AudioDeviceVolumeManagerWrapper mAudioDeviceVolumeManager; @Nullable private Looper mIoLooper; @@ -528,18 +531,20 @@ public class HdmiControlService extends SystemService { /** * Constructor for testing. * - * It's critical to use a fake AudioDeviceVolumeManager because a normally instantiated - * AudioDeviceVolumeManager can access the "real" AudioService on the DUT. + * Takes fakes for AudioManager and AudioDeviceVolumeManager. * - * @see FakeAudioDeviceVolumeManagerWrapper + * This is especially important for AudioDeviceVolumeManager because a normally instantiated + * AudioDeviceVolumeManager can access the "real" AudioService on the DUT. */ @VisibleForTesting HdmiControlService(Context context, List<Integer> deviceTypes, - AudioDeviceVolumeManagerWrapperInterface audioDeviceVolumeManager) { + AudioManagerWrapper audioManager, + AudioDeviceVolumeManagerWrapper audioDeviceVolumeManager) { super(context); mCecLocalDevices = deviceTypes; mSettingsObserver = new SettingsObserver(mHandler); mHdmiCecConfig = new HdmiCecConfig(context); mDeviceConfig = new DeviceConfigWrapper(); + mAudioManager = audioManager; mAudioDeviceVolumeManager = audioDeviceVolumeManager; } @@ -680,6 +685,8 @@ public class HdmiControlService extends SystemService { Constants.DEVICE_CONFIG_FEATURE_FLAG_ENABLE_EARC_TX, false); mTransitionFromArcToEarcTxEnabled = mDeviceConfig.getBoolean( Constants.DEVICE_CONFIG_FEATURE_FLAG_TRANSITION_ARC_TO_EARC_TX, false); + mNumericSoundbarVolumeUiOnTvFeatureFlagEnabled = mDeviceConfig.getBoolean( + Constants.DEVICE_CONFIG_FEATURE_FLAG_TV_NUMERIC_SOUNDBAR_VOLUME_UI, false); synchronized (mLock) { mEarcEnabled = (mHdmiCecConfig.getIntValue( @@ -899,6 +906,17 @@ public class HdmiControlService extends SystemService { false); } }); + + mDeviceConfig.addOnPropertiesChangedListener(getContext().getMainExecutor(), + new DeviceConfig.OnPropertiesChangedListener() { + @Override + public void onPropertiesChanged(DeviceConfig.Properties properties) { + mNumericSoundbarVolumeUiOnTvFeatureFlagEnabled = properties.getBoolean( + Constants.DEVICE_CONFIG_FEATURE_FLAG_TV_NUMERIC_SOUNDBAR_VOLUME_UI, + false); + checkAndUpdateAbsoluteVolumeBehavior(); + } + }); } /** Returns true if the device screen is off */ boolean isScreenOff() { @@ -934,11 +952,6 @@ public class HdmiControlService extends SystemService { } @VisibleForTesting - void setAudioManager(AudioManager audioManager) { - mAudioManager = audioManager; - } - - @VisibleForTesting void setCecController(HdmiCecController cecController) { mCecController = cecController; } @@ -975,11 +988,13 @@ public class HdmiControlService extends SystemService { Context.TV_INPUT_SERVICE); mPowerManager = new PowerManagerWrapper(getContext()); mPowerManagerInternal = new PowerManagerInternalWrapper(); - mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); + if (mAudioManager == null) { + mAudioManager = new DefaultAudioManagerWrapper(getContext()); + } mStreamMusicMaxVolume = getAudioManager().getStreamMaxVolume(AudioManager.STREAM_MUSIC); if (mAudioDeviceVolumeManager == null) { mAudioDeviceVolumeManager = - new AudioDeviceVolumeManagerWrapper(getContext()); + new DefaultAudioDeviceVolumeManagerWrapper(getContext()); } getAudioDeviceVolumeManager().addOnDeviceVolumeBehaviorChangedListener( mServiceThreadExecutor, this::onDeviceVolumeBehaviorChanged); @@ -1773,7 +1788,7 @@ public class HdmiControlService extends SystemService { == HdmiControlManager.VOLUME_CONTROL_DISABLED) { return; } - AudioManager audioManager = getAudioManager(); + AudioManagerWrapper audioManager = getAudioManager(); boolean muted = audioManager.isStreamMute(AudioManager.STREAM_MUSIC); if (mute) { if (!muted) { @@ -2751,7 +2766,7 @@ public class HdmiControlService extends SystemService { pw.println("mPowerStatus: " + mPowerStatusController.getPowerStatus()); pw.println("mIsCecAvailable: " + mIsCecAvailable); pw.println("mCecVersion: " + mCecVersion); - pw.println("mIsAbsoluteVolumeControlEnabled: " + isAbsoluteVolumeControlEnabled()); + pw.println("mIsAbsoluteVolumeBehaviorEnabled: " + isAbsoluteVolumeBehaviorEnabled()); // System settings pw.println("System_settings:"); @@ -2919,7 +2934,7 @@ public class HdmiControlService extends SystemService { @HdmiControlManager.VolumeControl int hdmiCecVolumeControl) { mHdmiCecVolumeControl = hdmiCecVolumeControl; announceHdmiCecVolumeControlFeatureChange(hdmiCecVolumeControl); - runOnServiceThread(this::checkAndUpdateAbsoluteVolumeControlState); + runOnServiceThread(this::checkAndUpdateAbsoluteVolumeBehavior); } // Get the source address to send out commands to devices connected to the current device @@ -3485,7 +3500,7 @@ public class HdmiControlService extends SystemService { * Returns null before the boot phase {@link SystemService#PHASE_SYSTEM_SERVICES_READY}. */ @Nullable - AudioManager getAudioManager() { + AudioManagerWrapper getAudioManager() { return mAudioManager; } @@ -3493,7 +3508,7 @@ public class HdmiControlService extends SystemService { * Returns null before the boot phase {@link SystemService#PHASE_SYSTEM_SERVICES_READY}. */ @Nullable - private AudioDeviceVolumeManagerWrapperInterface getAudioDeviceVolumeManager() { + private AudioDeviceVolumeManagerWrapper getAudioDeviceVolumeManager() { return mAudioDeviceVolumeManager; } @@ -3882,7 +3897,7 @@ public class HdmiControlService extends SystemService { synchronized (mLock) { mSystemAudioActivated = on; } - runOnServiceThread(this::checkAndUpdateAbsoluteVolumeControlState); + runOnServiceThread(this::checkAndUpdateAbsoluteVolumeBehavior); } @ServiceThreadOnly @@ -3993,7 +4008,7 @@ public class HdmiControlService extends SystemService { deviceIsActiveSource, caller); } - runOnServiceThread(this::checkAndUpdateAbsoluteVolumeControlState); + runOnServiceThread(this::checkAndUpdateAbsoluteVolumeBehavior); } // This method should only be called when the device can be the active source @@ -4189,17 +4204,17 @@ public class HdmiControlService extends SystemService { /** * Listener for changes to the volume behavior of an audio output device. Caches the - * volume behavior of devices used for Absolute Volume Control. + * volume behavior of devices used for absolute volume behavior. */ @VisibleForTesting @ServiceThreadOnly void onDeviceVolumeBehaviorChanged(AudioDeviceAttributes device, int volumeBehavior) { assertRunOnServiceThread(); - if (AVC_AUDIO_OUTPUT_DEVICES.contains(device)) { + if (AVB_AUDIO_OUTPUT_DEVICES.contains(device)) { synchronized (mLock) { mAudioDeviceVolumeBehaviors.put(device, volumeBehavior); } - checkAndUpdateAbsoluteVolumeControlState(); + checkAndUpdateAbsoluteVolumeBehavior(); } } @@ -4209,7 +4224,7 @@ public class HdmiControlService extends SystemService { */ @AudioManager.DeviceVolumeBehavior private int getDeviceVolumeBehavior(AudioDeviceAttributes device) { - if (AVC_AUDIO_OUTPUT_DEVICES.contains(device)) { + if (AVB_AUDIO_OUTPUT_DEVICES.contains(device)) { synchronized (mLock) { if (mAudioDeviceVolumeBehaviors.containsKey(device)) { return mAudioDeviceVolumeBehaviors.get(device); @@ -4220,25 +4235,29 @@ public class HdmiControlService extends SystemService { } /** - * Returns whether Absolute Volume Control is enabled or not. This is determined by the + * Returns whether absolute volume behavior is enabled or not. This is determined by the * volume behavior of the relevant HDMI audio output device(s) for this device's type. */ - public boolean isAbsoluteVolumeControlEnabled() { + public boolean isAbsoluteVolumeBehaviorEnabled() { if (!isTvDevice() && !isPlaybackDevice()) { return false; } - AudioDeviceAttributes avcAudioOutputDevice = getAvcAudioOutputDevice(); - if (avcAudioOutputDevice == null) { + AudioDeviceAttributes avbAudioOutputDevice = getAvbAudioOutputDevice(); + if (avbAudioOutputDevice == null) { return false; } - return getDeviceVolumeBehavior(avcAudioOutputDevice) - == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE; + + @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior = + getDeviceVolumeBehavior(avbAudioOutputDevice); + + return deviceVolumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE + || deviceVolumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY; } - private AudioDeviceAttributes getAvcAudioOutputDevice() { - if (isTvDevice()) { + private AudioDeviceAttributes getAvbAudioOutputDevice() { + if (tv() != null) { return tv().getSystemAudioOutputDevice(); - } else if (isPlaybackDevice()) { + } else if (playback() != null) { return AUDIO_OUTPUT_DEVICE_HDMI; } else { return null; @@ -4246,30 +4265,30 @@ public class HdmiControlService extends SystemService { } /** - * Checks the conditions for Absolute Volume Control (AVC), and enables or disables the feature - * if necessary. AVC is enabled precisely when a specific audio output device - * (HDMI for playback devices, and HDMI_ARC or HDMI_EARC for TVs) is using absolute volume - * behavior. + * This method is responsible for adopting or disabling absolute volume behavior and + * adjust-only absolute volume behavior in AudioService. These volume behaviors are adopted on + * specific audio output devices: HDMI for playback devices, and HDMI_ARC or HDMI_EARC for TVs. * - * AVC must be enabled on a Playback device or TV precisely when it is playing - * audio on an external device (the System Audio device) that supports the feature. - * This reduces to these conditions: + * This method enables absolute volume behavior on a Playback device or TV panel when it is + * playing audio on an external device (the System Audio device) that supports the feature. + * This allows the volume level of the System Audio device to be tracked and set by Android. * + * Absolute volume behavior requires the following conditions: * 1. If the System Audio Device is an Audio System: System Audio Mode is active * 2. Our HDMI audio output device is using full volume behavior * 3. CEC volume is enabled - * 4. The System Audio device supports AVC (i.e. it supports <Set Audio Volume Level>) - * - * If not all of these conditions are met, this method disables AVC if necessary. + * 4. The System Audio device supports the <Set Audio Volume Level> message * - * If all of these conditions are met, this method starts an action to query the System Audio - * device's audio status, which enables AVC upon obtaining the audio status. + * This method enables adjust-only absolute volume behavior on TV panels when conditions + * 1, 2, and 3 are met, but condition 4 is not. This allows TVs to track the volume level of + * the System Audio device and display numeric volume UI for it, even if the System Audio device + * does not support <Set Audio Volume Level>. */ @ServiceThreadOnly - void checkAndUpdateAbsoluteVolumeControlState() { + void checkAndUpdateAbsoluteVolumeBehavior() { assertRunOnServiceThread(); - // Can't enable or disable AVC before we have access to system services + // Can't set volume behavior before we have access to system services if (getAudioManager() == null) { return; } @@ -4281,84 +4300,110 @@ public class HdmiControlService extends SystemService { // (Doesn't apply to Playback Devices, where if SAM isn't active, we assume the // TV is the System Audio Device instead.) if (!isSystemAudioActivated()) { - disableAbsoluteVolumeControl(); + switchToFullVolumeBehavior(); return; } } else if (isPlaybackDevice() && playback() != null) { localCecDevice = playback(); } else { - // Either this device type doesn't support AVC, or it hasn't fully initialized yet + // Either this device type doesn't support AVB, or it hasn't fully initialized yet return; } - HdmiDeviceInfo systemAudioDeviceInfo = getHdmiCecNetwork().getSafeCecDeviceInfo( + HdmiDeviceInfo systemAudioDeviceInfo = getDeviceInfo( localCecDevice.findAudioReceiverAddress()); @AudioManager.DeviceVolumeBehavior int currentVolumeBehavior = - getDeviceVolumeBehavior(getAvcAudioOutputDevice()); + getDeviceVolumeBehavior(getAvbAudioOutputDevice()); // Condition 2: Already using full or absolute volume behavior boolean alreadyUsingFullOrAbsoluteVolume = - currentVolumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL - || currentVolumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE; + (currentVolumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL) + || (currentVolumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE) + || (currentVolumeBehavior + == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY); // Condition 3: CEC volume is enabled boolean cecVolumeEnabled = getHdmiCecVolumeControl() == HdmiControlManager.VOLUME_CONTROL_ENABLED; if (!cecVolumeEnabled || !alreadyUsingFullOrAbsoluteVolume) { - disableAbsoluteVolumeControl(); + switchToFullVolumeBehavior(); return; } - // Check for safety: if the System Audio device is a candidate for AVC, we should already + // Check for safety: if the System Audio device is a candidate for AVB, we should already // have received messages from it to trigger the other conditions. if (systemAudioDeviceInfo == null) { - disableAbsoluteVolumeControl(); + switchToFullVolumeBehavior(); return; } - // Condition 4: The System Audio device supports AVC (i.e. <Set Audio Volume Level>). + + // Condition 4: The System Audio device supports <Set Audio Volume Level> switch (systemAudioDeviceInfo.getDeviceFeatures().getSetAudioVolumeLevelSupport()) { case DeviceFeatures.FEATURE_SUPPORTED: - if (!isAbsoluteVolumeControlEnabled()) { - // Start an action that will call {@link #enableAbsoluteVolumeControl} + if (currentVolumeBehavior != AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE) { + // If we're currently using adjust-only absolute volume behavior, switch to + // full volume behavior until we successfully adopt absolute volume behavior + switchToFullVolumeBehavior(); + // Start an action that will call enableAbsoluteVolumeBehavior // once the System Audio device sends <Report Audio Status> - localCecDevice.addAvcAudioStatusAction( + localCecDevice.addAvbAudioStatusAction( systemAudioDeviceInfo.getLogicalAddress()); } return; case DeviceFeatures.FEATURE_NOT_SUPPORTED: - disableAbsoluteVolumeControl(); + // TVs may adopt adjust-only absolute volume behavior if condition 4 isn't met. + // This allows the device to display numeric volume UI for the System Audio device. + if (tv() != null && mNumericSoundbarVolumeUiOnTvFeatureFlagEnabled) { + if (currentVolumeBehavior + != AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY) { + // If we're currently using absolute volume behavior, switch to full volume + // behavior until we successfully adopt adjust-only absolute volume behavior + switchToFullVolumeBehavior(); + // Start an action that will call enableAbsoluteVolumeBehavior + // once the System Audio device sends <Report Audio Status> + localCecDevice.addAvbAudioStatusAction( + systemAudioDeviceInfo.getLogicalAddress()); + } + } else { + switchToFullVolumeBehavior(); + } return; case DeviceFeatures.FEATURE_SUPPORT_UNKNOWN: - disableAbsoluteVolumeControl(); - localCecDevice.queryAvcSupport(systemAudioDeviceInfo.getLogicalAddress()); - return; - default: - return; + switchToFullVolumeBehavior(); + localCecDevice.querySetAudioVolumeLevelSupport( + systemAudioDeviceInfo.getLogicalAddress()); } } - private void disableAbsoluteVolumeControl() { - if (isPlaybackDevice()) { - playback().removeAvcAudioStatusAction(); - } else if (isTvDevice()) { - tv().removeAvcAudioStatusAction(); - } - AudioDeviceAttributes device = getAvcAudioOutputDevice(); - if (getDeviceVolumeBehavior(device) == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE) { + /** + * Switches to full volume behavior, if either absolute or adjust-only absolute volume behavior + * are currently used. Removes the action for handling volume updates for these behaviors. + */ + private void switchToFullVolumeBehavior() { + if (playback() != null) { + playback().removeAvbAudioStatusAction(); + } else if (tv() != null) { + tv().removeAvbAudioStatusAction(); + } + AudioDeviceAttributes device = getAvbAudioOutputDevice(); + int volumeBehavior = getDeviceVolumeBehavior(device); + if (volumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE + || volumeBehavior == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY) { getAudioManager().setDeviceVolumeBehavior(device, AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); } } /** - * Enables Absolute Volume Control. Should only be called when all the conditions for - * AVC are met (see {@link #checkAndUpdateAbsoluteVolumeControlState}). + * Enables absolute volume behavior or adjust-only absolute volume behavior. Should only be + * called when the conditions for one of these behaviors is met - + * see {@link #checkAndUpdateAbsoluteVolumeBehavior}. + * * @param audioStatus The initial audio status to set the audio output device to */ - void enableAbsoluteVolumeControl(AudioStatus audioStatus) { + void enableAbsoluteVolumeBehavior(AudioStatus audioStatus) { HdmiCecLocalDevice localDevice = isPlaybackDevice() ? playback() : tv(); - HdmiDeviceInfo systemAudioDevice = getHdmiCecNetwork().getDeviceInfo( - localDevice.findAudioReceiverAddress()); + HdmiDeviceInfo systemAudioDevice = getDeviceInfo(localDevice.findAudioReceiverAddress()); VolumeInfo volumeInfo = new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) .setMuted(audioStatus.getMute()) .setVolumeIndex(audioStatus.getVolume()) @@ -4370,10 +4415,21 @@ public class HdmiControlService extends SystemService { // AudioService sets the volume of the stream and device based on the input VolumeInfo // when enabling absolute volume behavior, but not the mute state - notifyAvcMuteChange(audioStatus.getMute()); - getAudioDeviceVolumeManager().setDeviceAbsoluteVolumeBehavior( - getAvcAudioOutputDevice(), volumeInfo, mServiceThreadExecutor, - mAbsoluteVolumeChangedListener, true); + notifyAvbMuteChange(audioStatus.getMute()); + + // If <Set Audio Volume Level> is supported, enable absolute volume behavior. + // Otherwise, enable adjust-only AVB on TVs only. + if (systemAudioDevice.getDeviceFeatures().getSetAudioVolumeLevelSupport() + == DeviceFeatures.FEATURE_SUPPORTED) { + getAudioDeviceVolumeManager().setDeviceAbsoluteVolumeBehavior( + getAvbAudioOutputDevice(), volumeInfo, mServiceThreadExecutor, + mAbsoluteVolumeChangedListener, true); + } else if (tv() != null) { + getAudioDeviceVolumeManager().setDeviceAbsoluteVolumeAdjustOnlyBehavior( + getAvbAudioOutputDevice(), volumeInfo, mServiceThreadExecutor, + mAbsoluteVolumeChangedListener, true); + } + } private AbsoluteVolumeChangedListener mAbsoluteVolumeChangedListener; @@ -4407,6 +4463,14 @@ public class HdmiControlService extends SystemService { public void onAudioDeviceVolumeChanged( @NonNull AudioDeviceAttributes audioDevice, @NonNull VolumeInfo volumeInfo) { + + // Do nothing if the System Audio device does not support <Set Audio Volume Level> + if (mSystemAudioDevice.getDeviceFeatures().getSetAudioVolumeLevelSupport() + != DeviceFeatures.FEATURE_SUPPORTED) { + return; + } + + // Send <Set Audio Volume Level> to notify the System Audio device of the volume change int localDeviceAddress = mLocalDevice.getDeviceInfo().getLogicalAddress(); sendCecCommand(SetAudioVolumeLevelMessage.build( localDeviceAddress, @@ -4418,8 +4482,8 @@ public class HdmiControlService extends SystemService { if (errorCode == SendMessageResult.SUCCESS) { // Update the volume tracked in our AbsoluteVolumeAudioStatusAction // so it correctly processes incoming <Report Audio Status> messages - HdmiCecLocalDevice avcDevice = isTvDevice() ? tv() : playback(); - avcDevice.updateAvcVolume(volumeInfo.getVolumeIndex()); + HdmiCecLocalDevice avbDevice = isTvDevice() ? tv() : playback(); + avbDevice.updateAvbVolume(volumeInfo.getVolumeIndex()); } else { sendCecCommand(HdmiCecMessageBuilder.buildGiveAudioStatus( localDeviceAddress, @@ -4477,13 +4541,13 @@ public class HdmiControlService extends SystemService { /** * Notifies AudioService of a change in the volume of the System Audio device. Has no effect if - * AVC is disabled, or the audio output device for AVC is not playing for STREAM_MUSIC + * AVB is disabled, or the audio output device for AVB is not playing for STREAM_MUSIC */ - void notifyAvcVolumeChange(int volume) { - if (!isAbsoluteVolumeControlEnabled()) return; + void notifyAvbVolumeChange(int volume) { + if (!isAbsoluteVolumeBehaviorEnabled()) return; List<AudioDeviceAttributes> streamMusicDevices = getAudioManager().getDevicesForAttributes(STREAM_MUSIC_ATTRIBUTES); - if (streamMusicDevices.contains(getAvcAudioOutputDevice())) { + if (streamMusicDevices.contains(getAvbAudioOutputDevice())) { int flags = AudioManager.FLAG_ABSOLUTE_VOLUME; if (isTvDevice()) { flags |= AudioManager.FLAG_SHOW_UI; @@ -4494,13 +4558,13 @@ public class HdmiControlService extends SystemService { /** * Notifies AudioService of a change in the mute status of the System Audio device. Has no - * effect if AVC is disabled, or the audio output device for AVC is not playing for STREAM_MUSIC + * effect if AVB is disabled, or the audio output device for AVB is not playing for STREAM_MUSIC */ - void notifyAvcMuteChange(boolean mute) { - if (!isAbsoluteVolumeControlEnabled()) return; + void notifyAvbMuteChange(boolean mute) { + if (!isAbsoluteVolumeBehaviorEnabled()) return; List<AudioDeviceAttributes> streamMusicDevices = getAudioManager().getDevicesForAttributes(STREAM_MUSIC_ATTRIBUTES); - if (streamMusicDevices.contains(getAvcAudioOutputDevice())) { + if (streamMusicDevices.contains(getAvbAudioOutputDevice())) { int direction = mute ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE; int flags = AudioManager.FLAG_ABSOLUTE_VOLUME; if (isTvDevice()) { diff --git a/services/core/java/com/android/server/hdmi/SendKeyAction.java b/services/core/java/com/android/server/hdmi/SendKeyAction.java index 7daeaf19c657..2703a2c01848 100644 --- a/services/core/java/com/android/server/hdmi/SendKeyAction.java +++ b/services/core/java/com/android/server/hdmi/SendKeyAction.java @@ -172,10 +172,10 @@ final class SendKeyAction extends HdmiCecFeatureAction { } private void sendKeyUp() { - // When using Absolute Volume Control, query audio status after a volume key is released. + // When using absolute volume behavior, query audio status after a volume key is released. // This allows us to notify AudioService of the resulting volume or mute status changes. if (HdmiCecKeycode.isVolumeKeycode(mLastKeycode) - && localDevice().getService().isAbsoluteVolumeControlEnabled()) { + && localDevice().getService().isAbsoluteVolumeBehaviorEnabled()) { sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(getSourceAddress(), mTargetAddress), __ -> sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus( diff --git a/services/core/java/com/android/server/hdmi/SetAudioVolumeLevelDiscoveryAction.java b/services/core/java/com/android/server/hdmi/SetAudioVolumeLevelDiscoveryAction.java index eb3b33d8ca22..bfa8509b4e5f 100644 --- a/services/core/java/com/android/server/hdmi/SetAudioVolumeLevelDiscoveryAction.java +++ b/services/core/java/com/android/server/hdmi/SetAudioVolumeLevelDiscoveryAction.java @@ -90,7 +90,7 @@ public class SetAudioVolumeLevelDiscoveryAction extends HdmiCecFeatureAction { } void handleTimerEvent(int state) { - if (updateAvcSupport(FEATURE_SUPPORTED)) { + if (updateSetAudioVolumeLevelSupport(FEATURE_SUPPORTED)) { finishWithCallback(HdmiControlManager.RESULT_SUCCESS); } else { finishWithCallback(HdmiControlManager.RESULT_EXCEPTION); @@ -104,7 +104,7 @@ public class SetAudioVolumeLevelDiscoveryAction extends HdmiCecFeatureAction { * * @return Whether support was successfully updated in the network. */ - private boolean updateAvcSupport( + private boolean updateSetAudioVolumeLevelSupport( @DeviceFeatures.FeatureSupportStatus int setAudioVolumeLevelSupport) { HdmiCecNetwork network = localDevice().mService.getHdmiCecNetwork(); HdmiDeviceInfo currentDeviceInfo = network.getCecDeviceInfo(mTargetAddress); diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java index d5761e170d1a..30b188c5dd78 100644 --- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java +++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java @@ -159,7 +159,7 @@ final class VolumeControlAction extends HdmiCecFeatureAction { // Update audio status if current volume position is edge of volume bar, // i.e max or min volume. - AudioManager audioManager = tv().getService().getAudioManager(); + AudioManagerWrapper audioManager = tv().getService().getAudioManager(); int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); if (mIsVolumeUp) { int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java index a7fe64adf1ff..be5e2623ac20 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java @@ -26,7 +26,6 @@ import static org.mockito.Mockito.spy; import android.content.Context; import android.content.ContextWrapper; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -61,19 +60,9 @@ public class ActiveSourceActionTest { public void setUp() throws Exception { mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); + FakeAudioFramework audioFramework = new FakeAudioFramework(); mHdmiControlService = new HdmiControlService(mContextSpy, Collections.emptyList(), - new FakeAudioDeviceVolumeManagerWrapper()) { - @Override - AudioManager getAudioManager() { - return new AudioManager() { - @Override - public void setWiredDeviceConnectionState( - int type, int state, String address, String name) { - // Do nothing. - } - }; - } - + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isPowerStandby() { return false; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java index 3df0449c14b7..5be3c8e4671c 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java @@ -25,7 +25,6 @@ import static org.mockito.Mockito.spy; import android.content.Context; import android.content.ContextWrapper; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -37,8 +36,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Collections; @@ -58,27 +55,21 @@ public class ArcInitiationActionFromAvrTest { private TestLooper mTestLooper = new TestLooper(); private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>(); - @Mock - private AudioManager mAudioManager; - @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + HdmiControlService hdmiControlService = new HdmiControlService(mContextSpy, Collections.emptyList(), - new FakeAudioDeviceVolumeManagerWrapper()) { + audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isPowerStandby() { return false; } - @Override - AudioManager getAudioManager() { - return mAudioManager; - } @Override boolean isAddressAllocated() { diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java index 61ab99b1d017..7845c307c15f 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java @@ -27,7 +27,6 @@ import android.content.ContextWrapper; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -39,7 +38,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -61,8 +59,6 @@ public class ArcTerminationActionFromAvrTest { private TestLooper mTestLooper = new TestLooper(); private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>(); - @Mock - private AudioManager mAudioManager; @Before public void setUp() throws Exception { @@ -70,14 +66,12 @@ public class ArcTerminationActionFromAvrTest { mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + HdmiControlService hdmiControlService = new HdmiControlService(mContextSpy, Collections.emptyList(), - new FakeAudioDeviceVolumeManagerWrapper()) { - @Override - AudioManager getAudioManager() { - return mAudioManager; - } - + audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isPowerStandby() { return false; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeControlTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java index 9f295b8f42c2..bc09d4b10723 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeControlTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java @@ -24,16 +24,11 @@ import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_BOOT_UP; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.TruthJUnit.assume; -import static org.mockito.AdditionalMatchers.not; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -59,8 +54,6 @@ import com.android.server.SystemService; import org.junit.Before; import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -68,20 +61,20 @@ import java.util.Arrays; import java.util.Collections; /** - * Tests that Absolute Volume Control (AVC) is enabled and disabled correctly, and that + * Tests that absolute volume behavior (AVB) is enabled and disabled correctly, and that * the device responds correctly to incoming <Report Audio Status> messages and API calls - * from AudioService when AVC is active. + * from AudioService when AVB is active. * * This is an abstract base class. Concrete subclasses specify the type of the local device, and the * type of the System Audio device. This allows each test to be run for multiple setups. * * We test the following pairs of (local device, System Audio device): - * (Playback, TV): {@link PlaybackDeviceToTvAvcTest} - * (Playback, Audio System): {@link PlaybackDeviceToAudioSystemAvcTest} - * (TV, Audio System): {@link TvToAudioSystemAvcTest} + * (Playback, TV): {@link PlaybackDeviceToTvAvbTest} + * (Playback, Audio System): {@link PlaybackDeviceToAudioSystemAvbTest} + * (TV, Audio System): {@link TvToAudioSystemAvbTest} */ -public abstract class BaseAbsoluteVolumeControlTest { - private HdmiControlService mHdmiControlService; +public abstract class BaseAbsoluteVolumeBehaviorTest { + protected HdmiControlService mHdmiControlService; private HdmiCecController mHdmiCecController; private HdmiCecLocalDevice mHdmiCecLocalDevice; private FakeHdmiCecConfig mHdmiCecConfig; @@ -90,19 +83,20 @@ public abstract class BaseAbsoluteVolumeControlTest { private Context mContextSpy; private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>(); - @Mock protected AudioManager mAudioManager; - protected FakeAudioDeviceVolumeManagerWrapper mAudioDeviceVolumeManager; + protected FakeAudioFramework mAudioFramework; + protected AudioManagerWrapper mAudioManager; + protected AudioDeviceVolumeManagerWrapper mAudioDeviceVolumeManager; protected TestLooper mTestLooper = new TestLooper(); protected FakeNativeWrapper mNativeWrapper; - // Audio Status given by the System Audio device in its initial <Report Audio Status> that - // triggers AVC being enabled + // Default Audio Status given by the System Audio device in its initial <Report Audio Status> + // that triggers AVB being enabled private static final AudioStatus INITIAL_SYSTEM_AUDIO_DEVICE_STATUS = new AudioStatus(50, false); - // VolumeInfo passed to AudioDeviceVolumeManager#setDeviceAbsoluteVolumeBehavior to enable AVC - private static final VolumeInfo ENABLE_AVC_VOLUME_INFO = + // VolumeInfo passed to AudioDeviceVolumeManager#setDeviceAbsoluteVolumeBehavior to enable AVB + private static final VolumeInfo ENABLE_AVB_VOLUME_INFO = new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) .setMuted(INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute()) .setVolumeIndex(INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume()) @@ -110,6 +104,8 @@ public abstract class BaseAbsoluteVolumeControlTest { .setMinVolumeIndex(AudioStatus.MIN_VOLUME) .build(); + private static final int EMPTY_FLAGS = 0; + protected abstract HdmiCecLocalDevice createLocalDevice(HdmiControlService hdmiControlService); protected abstract int getPhysicalAddress(); @@ -126,17 +122,17 @@ public abstract class BaseAbsoluteVolumeControlTest { mContextSpy = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); - mAudioDeviceVolumeManager = spy(new FakeAudioDeviceVolumeManagerWrapper()); + mAudioFramework = new FakeAudioFramework(); + mAudioManager = spy(mAudioFramework.getAudioManager()); + mAudioDeviceVolumeManager = spy(mAudioFramework.getAudioDeviceVolumeManager()); + + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 1, EMPTY_FLAGS); + mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, true); mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), Collections.singletonList(getDeviceType()), - mAudioDeviceVolumeManager) { - @Override - AudioManager getAudioManager() { - return mAudioManager; - } - + mAudioManager, mAudioDeviceVolumeManager) { @Override protected void writeStringSystemProperty(String key, String value) { // do nothing @@ -186,22 +182,12 @@ public abstract class BaseAbsoluteVolumeControlTest { mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_BOOT_UP); mTestLooper.dispatchAll(); - // Simulate AudioManager's behavior and response when setDeviceVolumeBehavior is called - doAnswer(invocation -> { - setDeviceVolumeBehavior(invocation.getArgument(0), invocation.getArgument(1)); - return null; - }).when(mAudioManager).setDeviceVolumeBehavior(any(), anyInt()); - - // Set starting volume behavior - doReturn(AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE) - .when(mAudioManager).getDeviceVolumeBehavior(eq(getAudioOutputDevice())); - // Audio service always plays STREAM_MUSIC on the device we need - doReturn(Collections.singletonList(getAudioOutputDevice())).when(mAudioManager) - .getDevicesForAttributes(HdmiControlService.STREAM_MUSIC_ATTRIBUTES); + mAudioFramework.setDevicesForAttributes(HdmiControlService.STREAM_MUSIC_ATTRIBUTES, + Collections.singletonList(getAudioOutputDevice())); // Max volume of STREAM_MUSIC - doReturn(25).when(mAudioManager).getStreamMaxVolume(AudioManager.STREAM_MUSIC); + mAudioFramework.setStreamMaxVolume(AudioManager.STREAM_MUSIC, 25); // Receive messages from devices to make sure they're registered in HdmiCecNetwork mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildGiveDevicePowerStatus( @@ -221,16 +207,6 @@ public abstract class BaseAbsoluteVolumeControlTest { } /** - * Simulates the volume behavior of {@code device} being set to {@code behavior}. - */ - protected void setDeviceVolumeBehavior(AudioDeviceAttributes device, - @AudioManager.DeviceVolumeBehavior int behavior) { - doReturn(behavior).when(mAudioManager).getDeviceVolumeBehavior(eq(device)); - mHdmiControlService.onDeviceVolumeBehaviorChanged(device, behavior); - mTestLooper.dispatchAll(); - } - - /** * Changes the setting for CEC volume. */ protected void setCecVolumeControlSetting(@HdmiControlManager.VolumeControl int setting) { @@ -278,16 +254,6 @@ public abstract class BaseAbsoluteVolumeControlTest { } /** - * Has the device receive a <Report Audio Status> reporting the status in - * {@link #INITIAL_SYSTEM_AUDIO_DEVICE_STATUS} - */ - protected void receiveInitialReportAudioStatus() { - receiveReportAudioStatus( - INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume(), - INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute()); - } - - /** * Has the device receive a <Report Audio Status> message from the System Audio Device. */ protected void receiveReportAudioStatus(int volume, boolean mute) { @@ -300,40 +266,34 @@ public abstract class BaseAbsoluteVolumeControlTest { } /** - * Triggers all the conditions required to enable Absolute Volume Control. + * Triggers all the conditions required to enable absolute volume behavior. */ - protected void enableAbsoluteVolumeControl() { - setDeviceVolumeBehavior(getAudioOutputDevice(), AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + protected void enableAbsoluteVolumeBehavior() { + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_SUPPORTED); enableSystemAudioModeIfNeeded(); - receiveInitialReportAudioStatus(); + receiveReportAudioStatus( + INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume(), + INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute()); - verifyAbsoluteVolumeEnabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); } - /** - * Verifies that AVC was enabled - that is the audio output device's volume behavior was last - * set to absolute volume behavior. - */ - protected void verifyAbsoluteVolumeEnabled() { - InOrder inOrder = inOrder(mAudioManager, mAudioDeviceVolumeManager); - inOrder.verify(mAudioDeviceVolumeManager, atLeastOnce()).setDeviceAbsoluteVolumeBehavior( - eq(getAudioOutputDevice()), any(), any(), any(), anyBoolean()); - inOrder.verify(mAudioManager, never()).setDeviceVolumeBehavior( - eq(getAudioOutputDevice()), not(eq(AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE))); - } + protected void enableAdjustOnlyAbsoluteVolumeBehavior() { + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); + enableSystemAudioModeIfNeeded(); + receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_NOT_SUPPORTED); + receiveReportAudioStatus( + INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getVolume(), + INITIAL_SYSTEM_AUDIO_DEVICE_STATUS.getMute()); - /** - * Verifies that AVC was disabled - that is, the audio output device's volume behavior was - * last set to something other than absolute volume behavior. - */ - protected void verifyAbsoluteVolumeDisabled() { - InOrder inOrder = inOrder(mAudioManager, mAudioDeviceVolumeManager); - inOrder.verify(mAudioManager, atLeastOnce()).setDeviceVolumeBehavior( - eq(getAudioOutputDevice()), not(eq(AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE))); - inOrder.verify(mAudioDeviceVolumeManager, never()).setDeviceAbsoluteVolumeBehavior( - eq(getAudioOutputDevice()), any(), any(), any(), anyBoolean()); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY); } protected void verifyGiveAudioStatusNeverSent() { @@ -350,7 +310,8 @@ public abstract class BaseAbsoluteVolumeControlTest { @Test public void allConditionsExceptSavlSupportMet_sendsSetAudioVolumeLevelAndGiveFeatures() { - setDeviceVolumeBehavior(getAudioOutputDevice(), AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); enableSystemAudioModeIfNeeded(); @@ -365,7 +326,8 @@ public abstract class BaseAbsoluteVolumeControlTest { @Test public void allConditionsMet_savlSupportLast_reportFeatures_giveAudioStatusSent() { - setDeviceVolumeBehavior(getAudioOutputDevice(), AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); enableSystemAudioModeIfNeeded(); verifyGiveAudioStatusNeverSent(); @@ -376,7 +338,8 @@ public abstract class BaseAbsoluteVolumeControlTest { @Test public void allConditionsMet_savlSupportLast_noFeatureAbort_giveAudioStatusSent() { - setDeviceVolumeBehavior(getAudioOutputDevice(), AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); enableSystemAudioModeIfNeeded(); verifyGiveAudioStatusNeverSent(); @@ -388,7 +351,8 @@ public abstract class BaseAbsoluteVolumeControlTest { @Test public void allConditionsMet_cecVolumeEnabledLast_giveAudioStatusSent() { - setDeviceVolumeBehavior(getAudioOutputDevice(), AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); enableSystemAudioModeIfNeeded(); receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_SUPPORTED); verifyGiveAudioStatusNeverSent(); @@ -404,7 +368,9 @@ public abstract class BaseAbsoluteVolumeControlTest { receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_SUPPORTED); verifyGiveAudioStatusNeverSent(); - setDeviceVolumeBehavior(getAudioOutputDevice(), AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + mTestLooper.dispatchAll(); verifyGiveAudioStatusSent(); } @@ -413,7 +379,8 @@ public abstract class BaseAbsoluteVolumeControlTest { // Only run when the System Audio device is an Audio System. assume().that(getSystemAudioDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - setDeviceVolumeBehavior(getAudioOutputDevice(), AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_SUPPORTED); verifyGiveAudioStatusNeverSent(); @@ -423,62 +390,97 @@ public abstract class BaseAbsoluteVolumeControlTest { } @Test - public void giveAudioStatusSent_systemAudioDeviceSendsReportAudioStatus_avcEnabled() { + public void giveAudioStatusSent_systemAudioDeviceSendsReportAudioStatus_avbEnabled() { + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); enableSystemAudioModeIfNeeded(); receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_SUPPORTED); - setDeviceVolumeBehavior(getAudioOutputDevice(), AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); - // Verify that AVC was never enabled - verify(mAudioDeviceVolumeManager, never()).setDeviceAbsoluteVolumeBehavior( - eq(getAudioOutputDevice()), any(), any(), any(), anyBoolean()); - receiveInitialReportAudioStatus(); + // AVB should not be enabled before receiving <Report Audio Status> + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + + receiveReportAudioStatus(60, false); + + // Check that absolute volume behavior was the last one adopted + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); + + // Check that the volume and mute status received were included when setting AVB + verify(mAudioDeviceVolumeManager).setDeviceAbsoluteVolumeBehavior( + eq(getAudioOutputDevice()), + eq(new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) + .setVolumeIndex(60) + .setMuted(false) + .setMaxVolumeIndex(AudioStatus.MAX_VOLUME) + .setMinVolumeIndex(AudioStatus.MIN_VOLUME) + .build()), + any(), any(), anyBoolean()); + } + + @Test + public void giveAudioStatusSent_reportAudioStatusVolumeOutOfBounds_avbNotEnabled() { + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); + enableSystemAudioModeIfNeeded(); + receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_SUPPORTED); - verifyAbsoluteVolumeEnabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + receiveReportAudioStatus(127, false); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); } @Test - public void avcEnabled_cecVolumeDisabled_absoluteVolumeDisabled() { - enableAbsoluteVolumeControl(); + public void avbEnabled_cecVolumeDisabled_avbDisabled() { + enableAbsoluteVolumeBehavior(); setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_DISABLED); - verifyAbsoluteVolumeDisabled(); + + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); } @Test - public void avcEnabled_setAudioVolumeLevelNotSupported_absoluteVolumeDisabled() { - enableAbsoluteVolumeControl(); + public void avbEnabled_setAudioVolumeLevelNotSupported_avbDisabled() { + enableAbsoluteVolumeBehavior(); receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_NOT_SUPPORTED); - verifyAbsoluteVolumeDisabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); } @Test - public void avcEnabled_setAudioVolumeLevelFeatureAborted_absoluteVolumeDisabled() { - enableAbsoluteVolumeControl(); + public void avbEnabled_setAudioVolumeLevelFeatureAborted_avbDisabled() { + enableAbsoluteVolumeBehavior(); mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildFeatureAbortCommand( getSystemAudioDeviceLogicalAddress(), getLogicalAddress(), Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL, Constants.ABORT_UNRECOGNIZED_OPCODE)); mTestLooper.dispatchAll(); - verifyAbsoluteVolumeDisabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); } @Test - public void avcEnabled_systemAudioModeDisabled_absoluteVolumeDisabled() { + public void avbEnabled_systemAudioModeDisabled_avbDisabled() { // Only run when the System Audio device is an Audio System. assume().that(getSystemAudioDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - enableAbsoluteVolumeControl(); + enableAbsoluteVolumeBehavior(); receiveSetSystemAudioMode(false); - verifyAbsoluteVolumeDisabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); } @Test - public void avcEnabled_receiveReportAudioStatus_notifiesVolumeOrMuteChanges() { + public void avbEnabled_receiveReportAudioStatus_notifiesVolumeOrMuteChanges() { // Initial <Report Audio Status> has volume=50 and mute=false - enableAbsoluteVolumeControl(); + enableAbsoluteVolumeBehavior(); // New volume and mute status: sets both receiveReportAudioStatus(20, true); @@ -512,12 +514,20 @@ public abstract class BaseAbsoluteVolumeControlTest { eq(AudioManager.ADJUST_UNMUTE), anyInt()); clearInvocations(mAudioManager); + // Volume not within range [0, 100]: sets neither volume nor mute + receiveReportAudioStatus(127, true); + verify(mAudioManager, never()).setStreamVolume(eq(AudioManager.STREAM_MUSIC), anyInt(), + anyInt()); + verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), anyInt(), + anyInt()); + clearInvocations(mAudioManager); + // If AudioService causes us to send <Set Audio Volume Level>, the System Audio device's // volume changes. Afterward, a duplicate of an earlier <Report Audio Status> should // still cause us to call setStreamVolume() mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeChanged( getAudioOutputDevice(), - new VolumeInfo.Builder(ENABLE_AVC_VOLUME_INFO) + new VolumeInfo.Builder(ENABLE_AVB_VOLUME_INFO) .setVolumeIndex(20) .build() ); @@ -530,13 +540,13 @@ public abstract class BaseAbsoluteVolumeControlTest { } @Test - public void avcEnabled_audioDeviceVolumeAdjusted_sendsUserControlPressedAndGiveAudioStatus() { - enableAbsoluteVolumeControl(); + public void avbEnabled_audioDeviceVolumeAdjusted_sendsUserControlPressedAndGiveAudioStatus() { + enableAbsoluteVolumeBehavior(); mNativeWrapper.clearResultMessages(); mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeAdjusted( getAudioOutputDevice(), - ENABLE_AVC_VOLUME_INFO, + ENABLE_AVB_VOLUME_INFO, AudioManager.ADJUST_RAISE, AudioDeviceVolumeManager.ADJUST_MODE_NORMAL ); @@ -554,14 +564,16 @@ public abstract class BaseAbsoluteVolumeControlTest { } @Test - public void avcEnabled_audioDeviceVolumeChanged_sendsSetAudioVolumeLevel() { - enableAbsoluteVolumeControl(); + public void avbEnabled_audioDeviceVolumeChanged_sendsSetAudioVolumeLevel() { + enableAbsoluteVolumeBehavior(); mNativeWrapper.clearResultMessages(); mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeChanged( getAudioOutputDevice(), - new VolumeInfo.Builder(ENABLE_AVC_VOLUME_INFO) + new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) .setVolumeIndex(20) + .setMaxVolumeIndex(AudioStatus.MAX_VOLUME) + .setMinVolumeIndex(AudioStatus.MIN_VOLUME) .build() ); mTestLooper.dispatchAll(); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BasePlaybackDeviceAvbTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BasePlaybackDeviceAvbTest.java new file mode 100644 index 000000000000..4c12e436542b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/hdmi/BasePlaybackDeviceAvbTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 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.server.hdmi; + +import android.hardware.hdmi.DeviceFeatures; +import android.hardware.hdmi.HdmiControlManager; +import android.hardware.hdmi.HdmiDeviceInfo; +import android.media.AudioDeviceAttributes; +import android.media.AudioManager; + +import org.junit.Test; + +/** + * Base class for tests for absolute volume behavior on Playback devices. Contains tests that are + * relevant to Playback devices but not to TVs. + * + * Subclasses contain tests for the following pairs of (local device, System Audio device): + * (Playback, TV): {@link PlaybackDeviceToTvAvbTest} + * (Playback, Audio System): {@link PlaybackDeviceToAudioSystemAvbTest} + */ +public abstract class BasePlaybackDeviceAvbTest extends BaseAbsoluteVolumeBehaviorTest { + + @Override + protected HdmiCecLocalDevice createLocalDevice(HdmiControlService hdmiControlService) { + return new HdmiCecLocalDevicePlayback(hdmiControlService); + } + + @Override + protected int getPhysicalAddress() { + return 0x1100; + } + + @Override + protected int getDeviceType() { + return HdmiDeviceInfo.DEVICE_PLAYBACK; + } + + @Override + protected AudioDeviceAttributes getAudioOutputDevice() { + return HdmiControlService.AUDIO_OUTPUT_DEVICE_HDMI; + } + + /** + * Unlike TVs, Playback devices don't start the process for adopting adjust-only AVB + * if the System Audio device doesn't support <Set Audio Volume Level> + */ + @Test + public void savlNotSupported_allOtherConditionsMet_giveAudioStatusNotSent() { + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); + enableSystemAudioModeIfNeeded(); + + receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_NOT_SUPPORTED); + verifyGiveAudioStatusNeverSent(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java index 28ba4bb503f9..9b65762e48ec 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java @@ -54,9 +54,13 @@ public class DetectTvSystemAudioModeSupportActionTest { @Before public void SetUp() { mDeviceInfoForTests = HdmiDeviceInfo.hardwarePort(1001, 1234); + + FakeAudioFramework audioFramework = new FakeAudioFramework(); + HdmiControlService hdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), - Collections.emptyList(), new FakeAudioDeviceVolumeManagerWrapper()) { + Collections.emptyList(), audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override void sendCecCommand( diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java index c4c5c2a7008e..af4eab39492d 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java @@ -31,7 +31,6 @@ import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -76,19 +75,11 @@ public class DevicePowerStatusActionTest { mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(mContextSpy, Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK), - new FakeAudioDeviceVolumeManagerWrapper()) { - @Override - AudioManager getAudioManager() { - return new AudioManager() { - @Override - public void setWiredDeviceConnectionState( - int type, int state, String address, String name) { - // Do nothing. - } - }; - } + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isPowerStandby() { diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionFromPlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionFromPlaybackTest.java index b571f4354452..5070b08a10cc 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionFromPlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionFromPlaybackTest.java @@ -97,10 +97,13 @@ public class DeviceSelectActionFromPlaybackTest { Context context = InstrumentationRegistry.getTargetContext(); mMyLooper = mTestLooper.getLooper(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK), - new FakeAudioDeviceVolumeManagerWrapper()) { + audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isCecControlEnabled() { return true; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionFromTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionFromTvTest.java index 9c1b67010d03..49023c6a22c4 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionFromTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/DeviceSelectActionFromTvTest.java @@ -106,10 +106,13 @@ public class DeviceSelectActionFromTvTest { Context context = InstrumentationRegistry.getTargetContext(); mMyLooper = mTestLooper.getLooper(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), Collections.singletonList(HdmiDeviceInfo.DEVICE_TV), - new FakeAudioDeviceVolumeManagerWrapper()) { + audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isCecControlEnabled() { return true; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeAudioDeviceVolumeManagerWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeAudioDeviceVolumeManagerWrapper.java deleted file mode 100644 index d33ef9bc8879..000000000000 --- a/services/tests/servicestests/src/com/android/server/hdmi/FakeAudioDeviceVolumeManagerWrapper.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.server.hdmi; - -import static android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener; -import static android.media.AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener; - -import android.annotation.CallbackExecutor; -import android.annotation.NonNull; -import android.media.AudioDeviceAttributes; -import android.media.AudioDeviceVolumeManager; -import android.media.AudioManager; -import android.media.VolumeInfo; - -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.Executor; - -/** - * Wrapper for {@link AudioDeviceVolumeManager} that stubs its methods. Useful for testing. - */ -public class FakeAudioDeviceVolumeManagerWrapper implements - AudioDeviceVolumeManagerWrapperInterface { - - private final Set<OnDeviceVolumeBehaviorChangedListener> mVolumeBehaviorListeners; - - public FakeAudioDeviceVolumeManagerWrapper() { - mVolumeBehaviorListeners = new HashSet<>(); - } - - @Override - public void addOnDeviceVolumeBehaviorChangedListener( - @NonNull @CallbackExecutor Executor executor, - @NonNull OnDeviceVolumeBehaviorChangedListener listener) - throws SecurityException { - mVolumeBehaviorListeners.add(listener); - } - - @Override - public void removeOnDeviceVolumeBehaviorChangedListener( - @NonNull OnDeviceVolumeBehaviorChangedListener listener) { - mVolumeBehaviorListeners.remove(listener); - } - - @Override - public void setDeviceAbsoluteVolumeBehavior( - @NonNull AudioDeviceAttributes device, - @NonNull VolumeInfo volume, - @NonNull @CallbackExecutor Executor executor, - @NonNull OnAudioDeviceVolumeChangedListener vclistener, - boolean handlesVolumeAdjustment) { - // Notify all volume behavior listeners that the device adopted absolute volume behavior - for (OnDeviceVolumeBehaviorChangedListener listener : mVolumeBehaviorListeners) { - listener.onDeviceVolumeBehaviorChanged(device, - AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeAudioFramework.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeAudioFramework.java new file mode 100644 index 000000000000..7294ba62cdae --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeAudioFramework.java @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2023 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.server.hdmi; + +import static android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener; +import static android.media.AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.media.AudioAttributes; +import android.media.AudioDeviceAttributes; +import android.media.AudioManager; +import android.media.AudioSystem; +import android.media.VolumeInfo; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executor; + +/** + * Contains a fake AudioManager and fake AudioDeviceVolumeManager. + * Stores the shared state for these managers, simulating a fake AudioService. + */ +public class FakeAudioFramework { + + private final FakeAudioManagerWrapper mAudioManager = new FakeAudioManagerWrapper(); + private final FakeAudioDeviceVolumeManagerWrapper mAudioDeviceVolumeManager = + new FakeAudioDeviceVolumeManagerWrapper(); + + private static final int DEFAULT_DEVICE_VOLUME_BEHAVIOR = + AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE; + private final Map<AudioDeviceAttributes, Integer> mDeviceVolumeBehaviors = new HashMap<>(); + + private final Set<OnDeviceVolumeBehaviorChangedListener> mVolumeBehaviorListeners = + new HashSet<>(); + + private final Map<AudioAttributes, List<AudioDeviceAttributes>> mDevicesForAttributes = + new HashMap<>(); + + private static final int DEFAULT_VOLUME = 0; + private final Map<Integer, Integer> mStreamVolumes = new HashMap<>(); + + private static final int DEFAULT_MAX_VOLUME = 100; + private final Map<Integer, Integer> mStreamMaxVolumes = new HashMap<>(); + + private static final boolean DEFAULT_MUTE_STATUS = false; + private final Map<Integer, Boolean> mStreamMuteStatuses = new HashMap<>(); + + public FakeAudioFramework() { + } + + /** + * Returns a fake AudioManager whose methods affect this object's internal state. + */ + public FakeAudioManagerWrapper getAudioManager() { + return mAudioManager; + } + + public class FakeAudioManagerWrapper implements AudioManagerWrapper { + @Override + public void adjustStreamVolume(int streamType, int direction, + @AudioManager.PublicVolumeFlags int flags) { + switch (direction) { + case AudioManager.ADJUST_MUTE: + mStreamMuteStatuses.put(streamType, true); + break; + case AudioManager.ADJUST_UNMUTE: + mStreamMuteStatuses.put(streamType, false); + break; + default: + // Other adjustments not implemented + } + } + + @Override + public void setStreamVolume(int streamType, int index, + @AudioManager.PublicVolumeFlags int flags) { + mStreamVolumes.put(streamType, index); + } + + @Override + public int getStreamVolume(int streamType) { + return mStreamVolumes.getOrDefault(streamType, DEFAULT_VOLUME); + } + + @Override + public int getStreamMinVolume(int streamType) { + return 0; + } + + @Override + public int getStreamMaxVolume(int streamType) { + return mStreamMaxVolumes.getOrDefault(streamType, DEFAULT_MAX_VOLUME); + } + + @Override + public boolean isStreamMute(int streamType) { + return mStreamMuteStatuses.getOrDefault(streamType, DEFAULT_MUTE_STATUS); + } + + @Override + public void setStreamMute(int streamType, boolean state) { + mStreamMuteStatuses.put(streamType, state); + } + + @Override + public int setHdmiSystemAudioSupported(boolean on) { + return AudioSystem.DEVICE_NONE; + } + + @Override + public void setWiredDeviceConnectionState(AudioDeviceAttributes attributes, int state) { + // Do nothing + } + + @Override + public void setWiredDeviceConnectionState(int device, int state, String address, + String name) { + // Do nothing + } + + + @Override + @AudioManager.DeviceVolumeBehavior + public int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) { + return mDeviceVolumeBehaviors.getOrDefault(device, DEFAULT_DEVICE_VOLUME_BEHAVIOR); + } + + public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device, + @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior) { + setVolumeBehaviorHelper(device, deviceVolumeBehavior); + } + + @Override + @NonNull + public List<AudioDeviceAttributes> getDevicesForAttributes( + @NonNull AudioAttributes attributes) { + return mDevicesForAttributes.getOrDefault(attributes, Collections.emptyList()); + } + } + + /** + * Returns a fake AudioDeviceVolumeManager whose methods affect this object's internal state. + */ + public FakeAudioDeviceVolumeManagerWrapper getAudioDeviceVolumeManager() { + return mAudioDeviceVolumeManager; + } + + public class FakeAudioDeviceVolumeManagerWrapper implements AudioDeviceVolumeManagerWrapper { + @Override + public void addOnDeviceVolumeBehaviorChangedListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull OnDeviceVolumeBehaviorChangedListener listener) + throws SecurityException { + mVolumeBehaviorListeners.add(listener); + } + + @Override + public void removeOnDeviceVolumeBehaviorChangedListener( + @NonNull OnDeviceVolumeBehaviorChangedListener listener) { + mVolumeBehaviorListeners.remove(listener); + } + + @Override + public void setDeviceAbsoluteVolumeBehavior( + @NonNull AudioDeviceAttributes device, + @NonNull VolumeInfo volume, + @NonNull @CallbackExecutor Executor executor, + @NonNull OnAudioDeviceVolumeChangedListener vclistener, + boolean handlesVolumeAdjustment) { + setVolumeBehaviorHelper(device, AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); + } + + @Override + public void setDeviceAbsoluteVolumeAdjustOnlyBehavior( + @NonNull AudioDeviceAttributes device, + @NonNull VolumeInfo volume, + @NonNull @CallbackExecutor Executor executor, + @NonNull OnAudioDeviceVolumeChangedListener vclistener, + boolean handlesVolumeAdjustment) { + setVolumeBehaviorHelper(device, + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY); + } + } + + /** + * Allows tests to manipulate the return value of + * {@link FakeAudioManagerWrapper#getDevicesForAttributes} + */ + public void setDevicesForAttributes(AudioAttributes attributes, + List<AudioDeviceAttributes> devices) { + mDevicesForAttributes.put(attributes, devices); + } + + /** + * Allows tests to manipulate the return value of + * {@link FakeAudioManagerWrapper#getStreamMaxVolume} + */ + public void setStreamMaxVolume(int streamType, int maxVolume) { + mStreamMaxVolumes.put(streamType, maxVolume); + } + + /** + * Helper method for changing an audio device's volume behavior. Notifies listeners. + */ + private void setVolumeBehaviorHelper(AudioDeviceAttributes device, + @AudioManager.DeviceVolumeBehavior int newVolumeBehavior) { + + int currentVolumeBehavior = mDeviceVolumeBehaviors.getOrDefault( + device, DEFAULT_DEVICE_VOLUME_BEHAVIOR); + + mDeviceVolumeBehaviors.put(device, newVolumeBehavior); + + if (newVolumeBehavior != currentVolumeBehavior) { + // Notify volume behavior listeners + for (OnDeviceVolumeBehaviorChangedListener listener : mVolumeBehaviorListeners) { + listener.onDeviceVolumeBehaviorChanged(device, newVolumeBehavior); + } + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java index e3d95586f943..5e54d3b8c237 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java @@ -86,9 +86,11 @@ public class HdmiCecAtomLoggingTest { mContextSpy = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlServiceSpy = spy(new HdmiControlService(mContextSpy, Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK), - new FakeAudioDeviceVolumeManagerWrapper())); + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager())); doNothing().when(mHdmiControlServiceSpy) .writeStringSystemProperty(anyString(), anyString()); doReturn(mHdmiCecAtomWriterSpy).when(mHdmiControlServiceSpy).getAtomWriter(); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java index a7232fefed10..0870bac6ef38 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java @@ -100,9 +100,11 @@ public class HdmiCecControllerTest { public void SetUp() { mMyLooper = mTestLooper.getLooper(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlServiceSpy = spy(new HdmiControlService( InstrumentationRegistry.getTargetContext(), Collections.emptyList(), - new FakeAudioDeviceVolumeManagerWrapper())); + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager())); doReturn(mMyLooper).when(mHdmiControlServiceSpy).getIoLooper(); doReturn(mMyLooper).when(mHdmiControlServiceSpy).getServiceLooper(); doAnswer(__ -> mCecVersion).when(mHdmiControlServiceSpy).getCecVersion(); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java index f5c0f2a0a4b6..a6e05ddc792c 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java @@ -54,23 +54,23 @@ import java.util.ArrayList; @RunWith(JUnit4.class) /** Tests for {@link HdmiCecLocalDeviceAudioSystem} class. */ public class HdmiCecLocalDeviceAudioSystemTest { - private static final HdmiCecMessage MESSAGE_REQUEST_SAD_LCPM = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor( ADDR_TV, ADDR_AUDIO_SYSTEM, new int[] {Constants.AUDIO_CODEC_LPCM}); + private static final int EMPTY_FLAGS = 0; + private HdmiControlService mHdmiControlService; private HdmiCecController mHdmiCecController; private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem; private HdmiCecLocalDevicePlayback mHdmiCecLocalDevicePlayback; private FakeNativeWrapper mNativeWrapper; private FakePowerManagerWrapper mPowerManager; + private FakeAudioFramework mAudioFramework; + private AudioManagerWrapper mAudioManager; private Looper mMyLooper; private TestLooper mTestLooper = new TestLooper(); private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>(); - private int mMusicVolume; - private int mMusicMaxVolume; - private boolean mMusicMute; private static final int SELF_PHYSICAL_ADDRESS = 0x2000; private static final int HDMI_1_PHYSICAL_ADDRESS = 0x2100; private static final int HDMI_2_PHYSICAL_ADDRESS = 0x2200; @@ -88,66 +88,12 @@ public class HdmiCecLocalDeviceAudioSystemTest { mLocalDeviceTypes.add(HdmiDeviceInfo.DEVICE_PLAYBACK); mLocalDeviceTypes.add(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mAudioFramework = new FakeAudioFramework(); + mAudioManager = mAudioFramework.getAudioManager(); mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), - mLocalDeviceTypes, - new FakeAudioDeviceVolumeManagerWrapper()) { - @Override - AudioManager getAudioManager() { - return new AudioManager() { - @Override - public int getStreamVolume(int streamType) { - switch (streamType) { - case STREAM_MUSIC: - return mMusicVolume; - default: - return 0; - } - } - - @Override - public boolean isStreamMute(int streamType) { - switch (streamType) { - case STREAM_MUSIC: - return mMusicMute; - default: - return false; - } - } - - @Override - public int getStreamMaxVolume(int streamType) { - switch (streamType) { - case STREAM_MUSIC: - return mMusicMaxVolume; - default: - return 100; - } - } - - @Override - public void adjustStreamVolume( - int streamType, int direction, int flags) { - switch (streamType) { - case STREAM_MUSIC: - if (direction == AudioManager.ADJUST_UNMUTE) { - mMusicMute = false; - } else if (direction == AudioManager.ADJUST_MUTE) { - mMusicMute = true; - } - break; - default: - } - } - - @Override - public void setWiredDeviceConnectionState( - int type, int state, String address, String name) { - // Do nothing. - } - }; - } - + mLocalDeviceTypes, mAudioManager, + mAudioFramework.getAudioDeviceVolumeManager()) { @Override void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) { mDeviceInfo = device; @@ -236,10 +182,12 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Test public void handleGiveAudioStatus_volume_10_mute_true() throws Exception { - mMusicVolume = 10; - mMusicMute = true; - mMusicMaxVolume = 20; - int scaledVolume = VolumeControlAction.scaleToCecVolume(10, mMusicMaxVolume); + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 10, EMPTY_FLAGS); + mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_MUTE, + EMPTY_FLAGS); + mAudioFramework.setStreamMaxVolume(AudioManager.STREAM_MUSIC, 20); + int scaledVolume = VolumeControlAction.scaleToCecVolume(10, + mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)); HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildReportAudioStatus( ADDR_AUDIO_SYSTEM, ADDR_TV, scaledVolume, true); @@ -303,7 +251,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Test @Ignore("b/120845532") public void handleSetSystemAudioMode_setOn_orignalOff() throws Exception { - mMusicMute = true; + mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, true); HdmiCecMessage messageSet = HdmiCecMessageBuilder.buildSetSystemAudioMode(ADDR_TV, ADDR_AUDIO_SYSTEM, true); HdmiCecMessage messageGive = @@ -326,13 +274,13 @@ public class HdmiCecLocalDeviceAudioSystemTest { .isEqualTo(Constants.HANDLED); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage); - assertThat(mMusicMute).isFalse(); + assertThat(mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)).isFalse(); } @Test @Ignore("b/120845532") public void handleSystemAudioModeRequest_turnOffByTv() throws Exception { - assertThat(mMusicMute).isFalse(); + assertThat(mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)).isFalse(); // Check if feature correctly turned off HdmiCecMessage messageGive = HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(ADDR_TV, ADDR_AUDIO_SYSTEM); @@ -354,7 +302,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { .isEqualTo(Constants.HANDLED); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage); - assertThat(mMusicMute).isTrue(); + assertThat(mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)).isTrue(); } @Test @@ -368,7 +316,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessageBuilder.buildSetSystemAudioMode( ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); - assertThat(mMusicMute).isTrue(); + assertThat(mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)).isTrue(); } @Test @@ -463,13 +411,13 @@ public class HdmiCecLocalDeviceAudioSystemTest { public void terminateSystemAudioMode_systemAudioModeOff() throws Exception { mHdmiCecLocalDeviceAudioSystem.checkSupportAndSetSystemAudioMode(false); assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse(); - mMusicMute = false; + mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, false); HdmiCecMessage message = HdmiCecMessageBuilder.buildSetSystemAudioMode( ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); mHdmiCecLocalDeviceAudioSystem.terminateSystemAudioMode(); assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse(); - assertThat(mMusicMute).isFalse(); + assertThat(mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)).isFalse(); assertThat(mNativeWrapper.getResultMessages()).isEmpty(); } @@ -477,13 +425,13 @@ public class HdmiCecLocalDeviceAudioSystemTest { public void terminateSystemAudioMode_systemAudioModeOn() throws Exception { mHdmiCecLocalDeviceAudioSystem.checkSupportAndSetSystemAudioMode(true); assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isTrue(); - mMusicMute = false; + mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, false); HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildSetSystemAudioMode( ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); mHdmiCecLocalDeviceAudioSystem.terminateSystemAudioMode(); assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isFalse(); - assertThat(mMusicMute).isTrue(); + assertThat(mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)).isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); } @@ -705,8 +653,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Test public void giveAudioStatus_volumeEnabled() { - mMusicVolume = 50; - mMusicMaxVolume = 100; mHdmiControlService.setHdmiCecVolumeControlEnabledInternal( HdmiControlManager.VOLUME_CONTROL_ENABLED); mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true); @@ -733,8 +679,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Test public void giveAudioStatus_volumeDisabled() { - mMusicVolume = 50; - mMusicMaxVolume = 100; mHdmiControlService.setHdmiCecVolumeControlEnabledInternal( HdmiControlManager.VOLUME_CONTROL_DISABLED); mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true); @@ -761,8 +705,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Test public void reportAudioStatus_volumeEnabled() { - mMusicVolume = 50; - mMusicMaxVolume = 100; mHdmiControlService.setHdmiCecVolumeControlEnabledInternal( HdmiControlManager.VOLUME_CONTROL_ENABLED); mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true); @@ -786,8 +728,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Test public void reportAudioStatus_volumeDisabled() { - mMusicVolume = 50; - mMusicMaxVolume = 100; mHdmiControlService.setHdmiCecVolumeControlEnabledInternal( HdmiControlManager.VOLUME_CONTROL_DISABLED); mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index beba9c64a88f..40c762c28194 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -31,7 +31,6 @@ import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiPortInfo; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.media.AudioManager; import android.os.Looper; import android.os.RemoteException; import android.os.test.TestLooper; @@ -46,7 +45,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -88,8 +86,6 @@ public class HdmiCecLocalDevicePlaybackTest { private boolean mActiveMediaSessionsPaused; private FakePowerManagerInternalWrapper mPowerManagerInternal = new FakePowerManagerInternalWrapper(); - @Mock - protected AudioManager mAudioManager; @Before public void setUp() { @@ -98,10 +94,12 @@ public class HdmiCecLocalDevicePlaybackTest { Context context = InstrumentationRegistry.getTargetContext(); mMyLooper = mTestLooper.getLooper(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK), - new FakeAudioDeviceVolumeManagerWrapper()) { + audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override void wakeUp() { @@ -110,11 +108,6 @@ public class HdmiCecLocalDevicePlaybackTest { } @Override - AudioManager getAudioManager() { - return mAudioManager; - } - - @Override void pauseActiveMediaSessions() { mActiveMediaSessionsPaused = true; } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java index 9c5c0d4dd66f..9882670432ae 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java @@ -33,6 +33,7 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -53,8 +54,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; @@ -128,18 +127,17 @@ public class HdmiCecLocalDeviceTest { private boolean isControlEnabled; private int mPowerStatus; - @Mock - private AudioManager mAudioManager; + private AudioManagerWrapper mAudioManager; @Before public void SetUp() { - MockitoAnnotations.initMocks(this); - Context context = InstrumentationRegistry.getTargetContext(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mAudioManager = spy(audioFramework.getAudioManager()); mHdmiControlService = new HdmiControlService(context, Collections.emptyList(), - new FakeAudioDeviceVolumeManagerWrapper()) { + mAudioManager, audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isCecControlEnabled() { return isControlEnabled; @@ -171,11 +169,6 @@ public class HdmiCecLocalDeviceTest { void wakeUp() { mWakeupMessageReceived = true; } - - @Override - AudioManager getAudioManager() { - return mAudioManager; - } }; mHdmiControlService.setIoLooper(mTestLooper.getLooper()); mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context)); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java index d2b1bdd127d2..d52b7ea38725 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -33,9 +33,9 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.content.Context; import android.hardware.hdmi.HdmiControlManager; @@ -55,8 +55,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Collections; @@ -122,20 +120,21 @@ public class HdmiCecLocalDeviceTvTest { } } - @Mock - private AudioManager mAudioManager; + private FakeAudioFramework mAudioFramework; + private AudioManagerWrapper mAudioManager; @Before public void setUp() { - MockitoAnnotations.initMocks(this); - Context context = InstrumentationRegistry.getTargetContext(); mMyLooper = mTestLooper.getLooper(); + mAudioFramework = new FakeAudioFramework(); + mAudioManager = spy(mAudioFramework.getAudioManager()); + mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), Collections.singletonList(HdmiDeviceInfo.DEVICE_TV), - new FakeAudioDeviceVolumeManagerWrapper()) { + mAudioManager, mAudioFramework.getAudioDeviceVolumeManager()) { @Override void wakeUp() { mWokenUp = true; @@ -167,11 +166,6 @@ public class HdmiCecLocalDeviceTvTest { } @Override - AudioManager getAudioManager() { - return mAudioManager; - } - - @Override void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) { mDeviceEventListeners.add(new DeviceEventListener(device, status)); } @@ -967,7 +961,7 @@ public class HdmiCecLocalDeviceTvTest { @Test public void receiveSetAudioVolumeLevel_samNotActivated_noFeatureAbort_volumeChanges() { - when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)).thenReturn(25); + mAudioFramework.setStreamMaxVolume(AudioManager.STREAM_MUSIC, 25); // Max volume of STREAM_MUSIC is retrieved on boot mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java index 81cfdbee7831..bdf3a5ffbd84 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java @@ -58,9 +58,11 @@ public class HdmiCecMessageValidatorTest { @Before public void setUp() throws Exception { + FakeAudioFramework audioFramework = new FakeAudioFramework(); + HdmiControlService mHdmiControlService = new HdmiControlService( InstrumentationRegistry.getTargetContext(), Collections.emptyList(), - new FakeAudioDeviceVolumeManagerWrapper()); + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()); mHdmiControlService.setIoLooper(mTestLooper.getLooper()); } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java index d341153ac0ce..1ad9ce02daa3 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java @@ -67,8 +67,11 @@ public class HdmiCecNetworkTest { @Before public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); + + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(mContext, Collections.emptyList(), - new FakeAudioDeviceVolumeManagerWrapper()) { + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()) { @Override void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) { mDeviceEventListenerStatuses.add(status); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java index 55e8b20ca7f0..c002067ae9e7 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java @@ -64,9 +64,11 @@ public class HdmiCecPowerStatusControllerTest { Context contextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); Looper myLooper = mTestLooper.getLooper(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(contextSpy, Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK), - new FakeAudioDeviceVolumeManagerWrapper()) { + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isCecControlEnabled() { return true; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java index fd6eb9286651..0e6b412e330d 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java @@ -49,7 +49,6 @@ import android.hardware.hdmi.HdmiPortInfo; import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener; import android.hardware.hdmi.IHdmiControlStatusChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; -import android.media.AudioManager; import android.os.Binder; import android.os.Looper; import android.os.RemoteException; @@ -64,9 +63,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; @@ -96,19 +93,17 @@ public class HdmiControlServiceTest { private HdmiPortInfo[] mHdmiPortInfo; private ArrayList<Integer> mLocalDeviceTypes = new ArrayList<>(); - @Mock protected AudioManager mAudioManager; - @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy); mLocalDeviceTypes.add(HdmiDeviceInfo.DEVICE_PLAYBACK); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlServiceSpy = spy(new HdmiControlService(mContextSpy, mLocalDeviceTypes, - new FakeAudioDeviceVolumeManagerWrapper())); + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager())); doNothing().when(mHdmiControlServiceSpy) .writeStringSystemProperty(anyString(), anyString()); @@ -171,7 +166,6 @@ public class HdmiControlServiceTest { mPowerManager = new FakePowerManagerWrapper(mContextSpy); mHdmiControlServiceSpy.setPowerManager(mPowerManager); mHdmiControlServiceSpy.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); - mHdmiControlServiceSpy.setAudioManager(mAudioManager); mHdmiControlServiceSpy.setEarcSupported(true); mTestLooper.dispatchAll(); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java index c3aec841ac3d..185f90f4e803 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java @@ -28,6 +28,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -35,7 +36,6 @@ import android.content.Context; import android.hardware.hdmi.HdmiDeviceInfo; import android.media.AudioDescriptor; import android.media.AudioDeviceAttributes; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -49,7 +49,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.Captor; -import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @@ -78,8 +77,7 @@ public class HdmiEarcLocalDeviceTxTest { private Looper mMyLooper; private TestLooper mTestLooper = new TestLooper(); - @Mock - private AudioManager mAudioManager; + private AudioManagerWrapper mAudioManager; @Captor ArgumentCaptor<AudioDeviceAttributes> mAudioAttributesCaptor; @@ -91,10 +89,13 @@ public class HdmiEarcLocalDeviceTxTest { Context context = InstrumentationRegistry.getTargetContext(); mMyLooper = mTestLooper.getLooper(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mAudioManager = spy(audioFramework.getAudioManager()); + mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), Collections.singletonList(HdmiDeviceInfo.DEVICE_TV), - new FakeAudioDeviceVolumeManagerWrapper()) { + mAudioManager, audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isCecControlEnabled() { return true; @@ -114,11 +115,6 @@ public class HdmiEarcLocalDeviceTxTest { boolean isPowerStandby() { return false; } - - @Override - AudioManager getAudioManager() { - return mAudioManager; - } }; mHdmiControlService.setIoLooper(mMyLooper); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java index b0e8ca75d2d8..1172a8744da7 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java @@ -31,7 +31,6 @@ import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -88,20 +87,11 @@ public class OneTouchPlayActionTest { mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); mHdmiCecConfig = new FakeHdmiCecConfig(mContextSpy); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(mContextSpy, Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK), - new FakeAudioDeviceVolumeManagerWrapper()) { - @Override - AudioManager getAudioManager() { - return new AudioManager() { - @Override - public void setWiredDeviceConnectionState( - int type, int state, String address, String name) { - // Do nothing. - } - }; - } - + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isPowerStandby() { return false; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/PlaybackDeviceToAudioSystemAvcTest.java b/services/tests/servicestests/src/com/android/server/hdmi/PlaybackDeviceToAudioSystemAvbTest.java index 64186028e6ed..43ab804e04be 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/PlaybackDeviceToAudioSystemAvcTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/PlaybackDeviceToAudioSystemAvbTest.java @@ -16,10 +16,12 @@ package com.android.server.hdmi; +import static com.google.common.truth.Truth.assertThat; + import android.hardware.hdmi.DeviceFeatures; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; -import android.media.AudioDeviceAttributes; +import android.media.AudioManager; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -33,33 +35,13 @@ import org.junit.runners.JUnit4; import java.util.Arrays; /** - * Tests for Absolute Volume Control where the local device is a Playback device and the + * Tests for absolute volume behavior where the local device is a Playback device and the * System Audio device is an Audio System. */ @SmallTest @Presubmit @RunWith(JUnit4.class) -public class PlaybackDeviceToAudioSystemAvcTest extends BaseAbsoluteVolumeControlTest { - - @Override - protected HdmiCecLocalDevice createLocalDevice(HdmiControlService hdmiControlService) { - return new HdmiCecLocalDevicePlayback(hdmiControlService); - } - - @Override - protected int getPhysicalAddress() { - return 0x1100; - } - - @Override - protected int getDeviceType() { - return HdmiDeviceInfo.DEVICE_PLAYBACK; - } - - @Override - protected AudioDeviceAttributes getAudioOutputDevice() { - return HdmiControlService.AUDIO_OUTPUT_DEVICE_HDMI; - } +public class PlaybackDeviceToAudioSystemAvbTest extends BasePlaybackDeviceAvbTest { @Override protected int getSystemAudioDeviceLogicalAddress() { @@ -72,17 +54,18 @@ public class PlaybackDeviceToAudioSystemAvcTest extends BaseAbsoluteVolumeContro } /** - * AVC is disabled if the Audio System disables System Audio mode, and the TV has unknown + * AVB is disabled if the Audio System disables System Audio mode, and the TV has unknown * support for <Set Audio Volume Level>. It is enabled once the TV confirms support for * <Set Audio Volume Level> and sends <Report Audio Status>. */ @Test public void switchToTv_absoluteVolumeControlDisabledUntilAllConditionsMet() { - enableAbsoluteVolumeControl(); + enableAbsoluteVolumeBehavior(); - // Audio System disables System Audio Mode. AVC should be disabled. + // Audio System disables System Audio Mode. AVB should be disabled. receiveSetSystemAudioMode(false); - verifyAbsoluteVolumeDisabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); // TV reports support for <Set Audio Volume Level> mNativeWrapper.onCecMessage(ReportFeaturesMessage.build( @@ -102,6 +85,7 @@ public class PlaybackDeviceToAudioSystemAvcTest extends BaseAbsoluteVolumeContro false)); mTestLooper.dispatchAll(); - verifyAbsoluteVolumeEnabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/PlaybackDeviceToTvAvcTest.java b/services/tests/servicestests/src/com/android/server/hdmi/PlaybackDeviceToTvAvbTest.java index 504c3bc2626a..9b343e34706a 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/PlaybackDeviceToTvAvcTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/PlaybackDeviceToTvAvbTest.java @@ -16,12 +16,14 @@ package com.android.server.hdmi; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.clearInvocations; import android.hardware.hdmi.DeviceFeatures; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; -import android.media.AudioDeviceAttributes; +import android.media.AudioManager; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -34,33 +36,13 @@ import java.util.Arrays; import java.util.Collections; /** - * Tests for Absolute Volume Control where the local device is a Playback device and the + * Tests for absolute volume behavior where the local device is a Playback device and the * System Audio device is a TV. */ @SmallTest @Presubmit @RunWith(JUnit4.class) -public class PlaybackDeviceToTvAvcTest extends BaseAbsoluteVolumeControlTest { - - @Override - protected HdmiCecLocalDevice createLocalDevice(HdmiControlService hdmiControlService) { - return new HdmiCecLocalDevicePlayback(hdmiControlService); - } - - @Override - protected int getPhysicalAddress() { - return 0x1100; - } - - @Override - protected int getDeviceType() { - return HdmiDeviceInfo.DEVICE_PLAYBACK; - } - - @Override - protected AudioDeviceAttributes getAudioOutputDevice() { - return HdmiControlService.AUDIO_OUTPUT_DEVICE_HDMI; - } +public class PlaybackDeviceToTvAvbTest extends BasePlaybackDeviceAvbTest { @Override protected int getSystemAudioDeviceLogicalAddress() { @@ -73,17 +55,18 @@ public class PlaybackDeviceToTvAvcTest extends BaseAbsoluteVolumeControlTest { } /** - * AVC is disabled when an Audio System with unknown support for <Set Audio Volume Level> + * AVB is disabled when an Audio System with unknown support for <Set Audio Volume Level> * becomes the System Audio device. It is enabled once the Audio System reports that it * supports <Set Audio Volume Level> and sends <Report Audio Status>. */ @Test public void switchToAudioSystem_absoluteVolumeControlDisabledUntilAllConditionsMet() { - enableAbsoluteVolumeControl(); + enableAbsoluteVolumeBehavior(); - // Audio System enables System Audio Mode. AVC should be disabled. + // Audio System enables System Audio Mode. AVB should be disabled. receiveSetSystemAudioMode(true); - verifyAbsoluteVolumeDisabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); clearInvocations(mAudioManager, mAudioDeviceVolumeManager); @@ -105,6 +88,7 @@ public class PlaybackDeviceToTvAvcTest extends BaseAbsoluteVolumeControlTest { false)); mTestLooper.dispatchAll(); - verifyAbsoluteVolumeEnabled(); + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/PowerStatusMonitorActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/PowerStatusMonitorActionTest.java index 89743cdeabf5..9f0a44ce008a 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/PowerStatusMonitorActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/PowerStatusMonitorActionTest.java @@ -30,7 +30,6 @@ import android.content.ContextWrapper; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiPortInfo; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -65,20 +64,11 @@ public class PowerStatusMonitorActionTest { public void setUp() throws Exception { mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(mContextSpy, Collections.singletonList(HdmiDeviceInfo.DEVICE_TV), - new FakeAudioDeviceVolumeManagerWrapper()) { - @Override - AudioManager getAudioManager() { - return new AudioManager() { - @Override - public void setWiredDeviceConnectionState( - int type, int state, String address, String name) { - // Do nothing. - } - }; - } - + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isPowerStandby() { return false; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java index 1c193411b932..043db1eb298d 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java @@ -95,9 +95,12 @@ public class RequestSadActionTest { Context context = InstrumentationRegistry.getTargetContext(); mMyLooper = mTestLooper.getLooper(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(context, Collections.singletonList(HdmiDeviceInfo.DEVICE_TV), - new FakeAudioDeviceVolumeManagerWrapper()) { + audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isCecControlEnabled() { return true; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/RoutingControlActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/RoutingControlActionTest.java index 5b1bdf6916da..1bc99b6b8ffb 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/RoutingControlActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/RoutingControlActionTest.java @@ -146,10 +146,13 @@ public class RoutingControlActionTest { HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(InstrumentationRegistry.getTargetContext(), Collections.singletonList(HdmiDeviceInfo.DEVICE_TV), - new FakeAudioDeviceVolumeManagerWrapper()) { + audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isCecControlEnabled() { return true; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SetAudioVolumeLevelDiscoveryActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SetAudioVolumeLevelDiscoveryActionTest.java index cac781509a93..a73f4aa35cf9 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/SetAudioVolumeLevelDiscoveryActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/SetAudioVolumeLevelDiscoveryActionTest.java @@ -80,9 +80,11 @@ public class SetAudioVolumeLevelDiscoveryActionTest { mContextSpy = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlServiceSpy = spy(new HdmiControlService(mContextSpy, Collections.singletonList(HdmiDeviceInfo.DEVICE_PLAYBACK), - new FakeAudioDeviceVolumeManagerWrapper())); + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager())); doNothing().when(mHdmiControlServiceSpy) .writeStringSystemProperty(anyString(), anyString()); @@ -152,11 +154,11 @@ public class SetAudioVolumeLevelDiscoveryActionTest { mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); mTestLooper.dispatchAll(); - @DeviceFeatures.FeatureSupportStatus int avcSupport = + @DeviceFeatures.FeatureSupportStatus int savlSupport = mHdmiControlServiceSpy.getHdmiCecNetwork().getCecDeviceInfo(Constants.ADDR_TV) .getDeviceFeatures().getSetAudioVolumeLevelSupport(); - assertThat(avcSupport).isEqualTo(FEATURE_SUPPORTED); + assertThat(savlSupport).isEqualTo(FEATURE_SUPPORTED); assertThat(mTestCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS); } @@ -172,11 +174,11 @@ public class SetAudioVolumeLevelDiscoveryActionTest { Constants.ABORT_UNRECOGNIZED_OPCODE)); mTestLooper.dispatchAll(); - @DeviceFeatures.FeatureSupportStatus int avcSupport = + @DeviceFeatures.FeatureSupportStatus int savlSupport = mHdmiControlServiceSpy.getHdmiCecNetwork().getCecDeviceInfo(Constants.ADDR_TV) .getDeviceFeatures().getSetAudioVolumeLevelSupport(); - assertThat(avcSupport).isEqualTo(FEATURE_NOT_SUPPORTED); + assertThat(savlSupport).isEqualTo(FEATURE_NOT_SUPPORTED); assertThat(mTestCallback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS); } @@ -189,11 +191,11 @@ public class SetAudioVolumeLevelDiscoveryActionTest { mPlaybackDevice.addAndStartAction(mAction); mTestLooper.dispatchAll(); - @DeviceFeatures.FeatureSupportStatus int avcSupport = + @DeviceFeatures.FeatureSupportStatus int savlSupport = mHdmiControlServiceSpy.getHdmiCecNetwork().getCecDeviceInfo(Constants.ADDR_TV) .getDeviceFeatures().getSetAudioVolumeLevelSupport(); - assertThat(avcSupport).isEqualTo(FEATURE_SUPPORT_UNKNOWN); + assertThat(savlSupport).isEqualTo(FEATURE_SUPPORT_UNKNOWN); assertThat(mTestCallback.getResult()).isEqualTo( HdmiControlManager.RESULT_COMMUNICATION_FAILED); } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioAutoInitiationActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioAutoInitiationActionTest.java index c40cd0eeaf7e..c3beff74ca1c 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioAutoInitiationActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioAutoInitiationActionTest.java @@ -29,7 +29,6 @@ import android.content.Context; import android.content.ContextWrapper; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiPortInfo; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -68,20 +67,11 @@ public class SystemAudioAutoInitiationActionTest { Looper myLooper = mTestLooper.getLooper(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + mHdmiControlService = new HdmiControlService(mContextSpy, Collections.singletonList(HdmiDeviceInfo.DEVICE_TV), - new FakeAudioDeviceVolumeManagerWrapper()) { - @Override - AudioManager getAudioManager() { - return new AudioManager() { - @Override - public void setWiredDeviceConnectionState( - int type, int state, String address, String name) { - // Do nothing. - } - }; - } - + audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()) { @Override boolean isPowerStandby() { return false; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java index b13ef4fa7014..f801f8853980 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java @@ -24,7 +24,6 @@ import android.annotation.Nullable; import android.content.Context; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.tv.cec.V1_0.SendMessageResult; -import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -68,8 +67,11 @@ public class SystemAudioInitiationActionFromAvrTest { Context context = InstrumentationRegistry.getTargetContext(); + FakeAudioFramework audioFramework = new FakeAudioFramework(); + HdmiControlService hdmiControlService = new HdmiControlService(context, - Collections.emptyList(), new FakeAudioDeviceVolumeManagerWrapper()) { + Collections.emptyList(), audioFramework.getAudioManager(), + audioFramework.getAudioDeviceVolumeManager()) { @Override void sendCecCommand( HdmiCecMessage command, @Nullable SendMessageCallback callback) { @@ -100,36 +102,6 @@ public class SystemAudioInitiationActionFromAvrTest { } @Override - AudioManager getAudioManager() { - return new AudioManager() { - - @Override - public int setHdmiSystemAudioSupported(boolean on) { - return 0; - } - - @Override - public int getStreamVolume(int streamType) { - return 0; - } - - @Override - public boolean isStreamMute(int streamType) { - return false; - } - - @Override - public int getStreamMaxVolume(int streamType) { - return 100; - } - - @Override - public void adjustStreamVolume( - int streamType, int direction, int flags) {} - }; - } - - @Override boolean isPowerStandby() { return false; } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java b/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java new file mode 100644 index 000000000000..079ef2e36673 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvbTest.java @@ -0,0 +1,265 @@ +/* + * 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.server.hdmi; + +import static com.android.server.hdmi.HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.hardware.hdmi.DeviceFeatures; +import android.hardware.hdmi.HdmiControlManager; +import android.hardware.hdmi.HdmiDeviceInfo; +import android.media.AudioDeviceAttributes; +import android.media.AudioDeviceVolumeManager; +import android.media.AudioManager; +import android.media.VolumeInfo; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests for absolute volume behavior where the local device is a TV and the System Audio device + * is an Audio System. Assumes that the TV uses ARC (rather than eARC). + */ +@SmallTest +@Presubmit +@RunWith(JUnit4.class) +public class TvToAudioSystemAvbTest extends BaseAbsoluteVolumeBehaviorTest { + + @Override + protected HdmiCecLocalDevice createLocalDevice(HdmiControlService hdmiControlService) { + return new HdmiCecLocalDeviceTv(hdmiControlService); + } + + @Override + protected int getPhysicalAddress() { + return 0x0000; + } + + @Override + protected int getDeviceType() { + return HdmiDeviceInfo.DEVICE_TV; + } + + @Override + protected AudioDeviceAttributes getAudioOutputDevice() { + return HdmiControlService.AUDIO_OUTPUT_DEVICE_HDMI_ARC; + } + + @Override + protected int getSystemAudioDeviceLogicalAddress() { + return Constants.ADDR_AUDIO_SYSTEM; + } + + @Override + protected int getSystemAudioDeviceType() { + return HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM; + } + + /** + * TVs start the process for adopting adjust-only AVB if the System Audio device doesn't + * support <Set Audio Volume Level> + */ + @Test + public void savlNotSupported_allOtherConditionsMet_giveAudioStatusSent() { + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); + enableSystemAudioModeIfNeeded(); + verifyGiveAudioStatusNeverSent(); + + receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_NOT_SUPPORTED); + verifyGiveAudioStatusSent(); + } + + @Test + public void savlNotSupported_systemAudioDeviceSendsReportAudioStatus_adjustOnlyAvbEnabled() { + mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(), + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED); + enableSystemAudioModeIfNeeded(); + receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_NOT_SUPPORTED); + + // Adjust-only AVB should not be enabled before receiving <Report Audio Status> + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL); + + receiveReportAudioStatus(20, false); + + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY); + + verify(mAudioDeviceVolumeManager).setDeviceAbsoluteVolumeAdjustOnlyBehavior( + eq(getAudioOutputDevice()), + eq(new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) + .setVolumeIndex(20) + .setMuted(false) + .setMaxVolumeIndex(AudioStatus.MAX_VOLUME) + .setMinVolumeIndex(AudioStatus.MIN_VOLUME) + .build()), + any(), any(), anyBoolean()); + } + + + @Test + public void avbEnabled_savlNotSupported_receiveReportAudioStatus_switchToAdjustOnlyAvb() { + enableAbsoluteVolumeBehavior(); + + receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_NOT_SUPPORTED); + + receiveReportAudioStatus(40, true); + + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY); + + verify(mAudioDeviceVolumeManager).setDeviceAbsoluteVolumeAdjustOnlyBehavior( + eq(getAudioOutputDevice()), + eq(new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) + .setVolumeIndex(40) + .setMuted(true) + .setMaxVolumeIndex(AudioStatus.MAX_VOLUME) + .setMinVolumeIndex(AudioStatus.MIN_VOLUME) + .build()), + any(), any(), anyBoolean()); + } + + @Test + public void avbEnabled_savlFeatureAborted_receiveReportAudioStatus_switchToAdjustOnlyAvb() { + enableAbsoluteVolumeBehavior(); + + mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildFeatureAbortCommand( + getSystemAudioDeviceLogicalAddress(), getLogicalAddress(), + Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL, Constants.ABORT_UNRECOGNIZED_OPCODE)); + mTestLooper.dispatchAll(); + + receiveReportAudioStatus(40, true); + + assertThat(mAudioManager.getDeviceVolumeBehavior(getAudioOutputDevice())).isEqualTo( + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY); + + verify(mAudioDeviceVolumeManager).setDeviceAbsoluteVolumeAdjustOnlyBehavior( + eq(getAudioOutputDevice()), + eq(new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) + .setVolumeIndex(40) + .setMuted(true) + .setMaxVolumeIndex(AudioStatus.MAX_VOLUME) + .setMinVolumeIndex(AudioStatus.MIN_VOLUME) + .build()), + any(), any(), anyBoolean()); + } + + @Test + public void adjustOnlyAvbEnabled_receiveReportAudioStatus_notifiesVolumeOrMuteChanges() { + enableAdjustOnlyAbsoluteVolumeBehavior(); + + // New volume and mute status: sets both + receiveReportAudioStatus(20, true); + verify(mAudioManager).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(5), + anyInt()); + verify(mAudioManager).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + eq(AudioManager.ADJUST_MUTE), anyInt()); + clearInvocations(mAudioManager); + + // New volume only: sets volume only + receiveReportAudioStatus(32, true); + verify(mAudioManager).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), + anyInt()); + verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + eq(AudioManager.ADJUST_MUTE), anyInt()); + clearInvocations(mAudioManager); + + // New mute status only: sets mute only + receiveReportAudioStatus(32, false); + verify(mAudioManager, never()).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), + anyInt()); + verify(mAudioManager).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + eq(AudioManager.ADJUST_UNMUTE), anyInt()); + clearInvocations(mAudioManager); + + // Repeat of earlier message: sets neither volume nor mute + receiveReportAudioStatus(32, false); + verify(mAudioManager, never()).setStreamVolume(eq(AudioManager.STREAM_MUSIC), eq(8), + anyInt()); + verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), + eq(AudioManager.ADJUST_UNMUTE), anyInt()); + + // Volume not within range [0, 100]: sets neither volume nor mute + receiveReportAudioStatus(127, true); + verify(mAudioManager, never()).setStreamVolume(eq(AudioManager.STREAM_MUSIC), anyInt(), + anyInt()); + verify(mAudioManager, never()).adjustStreamVolume(eq(AudioManager.STREAM_MUSIC), anyInt(), + anyInt()); + } + + @Test + public void adjustOnlyAvbEnabled_audioDeviceVolumeAdjusted_sendsUcpAndGiveAudioStatus() { + enableAdjustOnlyAbsoluteVolumeBehavior(); + mNativeWrapper.clearResultMessages(); + + mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeAdjusted( + getAudioOutputDevice(), + new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) + .setMaxVolumeIndex(AudioStatus.MAX_VOLUME) + .setMinVolumeIndex(AudioStatus.MIN_VOLUME) + .build(), + AudioManager.ADJUST_RAISE, + AudioDeviceVolumeManager.ADJUST_MODE_NORMAL + ); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).contains( + HdmiCecMessageBuilder.buildUserControlPressed(getLogicalAddress(), + getSystemAudioDeviceLogicalAddress(), CEC_KEYCODE_VOLUME_UP)); + assertThat(mNativeWrapper.getResultMessages()).contains( + HdmiCecMessageBuilder.buildUserControlReleased(getLogicalAddress(), + getSystemAudioDeviceLogicalAddress())); + assertThat(mNativeWrapper.getResultMessages()).contains( + HdmiCecMessageBuilder.buildGiveAudioStatus(getLogicalAddress(), + getSystemAudioDeviceLogicalAddress())); + } + + @Test + public void adjustOnlyAvbEnabled_audioDeviceVolumeChanged_doesNotSendSetAudioVolumeLevel() { + enableAdjustOnlyAbsoluteVolumeBehavior(); + + mNativeWrapper.clearResultMessages(); + + mHdmiControlService.getAbsoluteVolumeChangedListener().onAudioDeviceVolumeChanged( + getAudioOutputDevice(), + new VolumeInfo.Builder(AudioManager.STREAM_MUSIC) + .setVolumeIndex(20) + .setMaxVolumeIndex(AudioStatus.MAX_VOLUME) + .setMinVolumeIndex(AudioStatus.MIN_VOLUME) + .build() + ); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).isEmpty(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvcTest.java b/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvcTest.java deleted file mode 100644 index 41c0e0d29879..000000000000 --- a/services/tests/servicestests/src/com/android/server/hdmi/TvToAudioSystemAvcTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.server.hdmi; - -import android.hardware.hdmi.HdmiDeviceInfo; -import android.media.AudioDeviceAttributes; -import android.platform.test.annotations.Presubmit; - -import androidx.test.filters.SmallTest; - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Tests for Absolute Volume Control where the local device is a TV and the System Audio device - * is an Audio System. Assumes that the TV uses ARC (rather than eARC). - */ -@SmallTest -@Presubmit -@RunWith(JUnit4.class) -public class TvToAudioSystemAvcTest extends BaseAbsoluteVolumeControlTest { - - @Override - protected HdmiCecLocalDevice createLocalDevice(HdmiControlService hdmiControlService) { - return new HdmiCecLocalDeviceTv(hdmiControlService); - } - - @Override - protected int getPhysicalAddress() { - return 0x0000; - } - - @Override - protected int getDeviceType() { - return HdmiDeviceInfo.DEVICE_TV; - } - - @Override - protected AudioDeviceAttributes getAudioOutputDevice() { - return HdmiControlService.AUDIO_OUTPUT_DEVICE_HDMI_ARC; - } - - @Override - protected int getSystemAudioDeviceLogicalAddress() { - return Constants.ADDR_AUDIO_SYSTEM; - } - - @Override - protected int getSystemAudioDeviceType() { - return HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM; - } -} |