Merge changes from topic "adjust-only-avb" into udc-dev am: 457e90a46c am: 3b4848a63d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22959902 Change-Id: I500fa8a704f79d5e9dec1fd73ebad06e6a1f08e3 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
public AudioDeviceVolumeManagerWrapper(Context context) {
|
||||
mAudioDeviceVolumeManager = new AudioDeviceVolumeManager(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOnDeviceVolumeBehaviorChangedListener(
|
||||
/**
|
||||
* Wrapper for {@link AudioDeviceVolumeManager#addOnDeviceVolumeBehaviorChangedListener(
|
||||
* Executor, OnDeviceVolumeBehaviorChangedListener)}
|
||||
*/
|
||||
void addOnDeviceVolumeBehaviorChangedListener(
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener)
|
||||
throws SecurityException {
|
||||
mAudioDeviceVolumeManager.addOnDeviceVolumeBehaviorChangedListener(executor, listener);
|
||||
}
|
||||
@NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener);
|
||||
|
||||
@Override
|
||||
public void removeOnDeviceVolumeBehaviorChangedListener(
|
||||
@NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener) {
|
||||
mAudioDeviceVolumeManager.removeOnDeviceVolumeBehaviorChangedListener(listener);
|
||||
}
|
||||
/**
|
||||
* Wrapper for {@link AudioDeviceVolumeManager#removeOnDeviceVolumeBehaviorChangedListener(
|
||||
* OnDeviceVolumeBehaviorChangedListener)}
|
||||
*/
|
||||
void removeOnDeviceVolumeBehaviorChangedListener(
|
||||
@NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener);
|
||||
|
||||
@Override
|
||||
public void setDeviceAbsoluteVolumeBehavior(
|
||||
/**
|
||||
* 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) {
|
||||
mAudioDeviceVolumeManager.setDeviceAbsoluteVolumeBehavior(device, volume, executor,
|
||||
vclistener, handlesVolumeAdjustment);
|
||||
}
|
||||
boolean handlesVolumeAdjustment);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<>();
|
||||
|
||||
@@ -457,6 +457,9 @@ public class HdmiControlService extends SystemService {
|
||||
@ServiceThreadOnly
|
||||
private boolean mEarcTxFeatureFlagEnabled = false;
|
||||
|
||||
@ServiceThreadOnly
|
||||
private boolean mNumericSoundbarVolumeUiOnTvFeatureFlagEnabled = false;
|
||||
|
||||
@ServiceThreadOnly
|
||||
private boolean mTransitionFromArcToEarcTxEnabled = false;
|
||||
|
||||
@@ -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() {
|
||||
@@ -933,11 +951,6 @@ public class HdmiControlService extends SystemService {
|
||||
return HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
|
||||
}
|
||||
|
||||
@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>)
|
||||
* 4. The System Audio device supports the <Set Audio Volume Level> message
|
||||
*
|
||||
* If not all of these conditions are met, this method disables AVC if necessary.
|
||||
*
|
||||
* 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();
|
||||
/**
|
||||
* 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 = getAvcAudioOutputDevice();
|
||||
if (getDeviceVolumeBehavior(device) == AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE) {
|
||||
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()) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
@@ -220,16 +206,6 @@ public abstract class BaseAbsoluteVolumeControlTest {
|
||||
return mHdmiCecLocalDevice.getDeviceInfo().getLogicalAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -277,16 +253,6 @@ public abstract class BaseAbsoluteVolumeControlTest {
|
||||
mTestLooper.dispatchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
verifyAbsoluteVolumeEnabled();
|
||||
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 avcEnabled_cecVolumeDisabled_absoluteVolumeDisabled() {
|
||||
enableAbsoluteVolumeControl();
|
||||
public void giveAudioStatusSent_reportAudioStatusVolumeOutOfBounds_avbNotEnabled() {
|
||||
mAudioManager.setDeviceVolumeBehavior(getAudioOutputDevice(),
|
||||
AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL);
|
||||
setCecVolumeControlSetting(HdmiControlManager.VOLUME_CONTROL_ENABLED);
|
||||
enableSystemAudioModeIfNeeded();
|
||||
receiveSetAudioVolumeLevelSupport(DeviceFeatures.FEATURE_SUPPORTED);
|
||||
|
||||
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 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();
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
@@ -109,11 +107,6 @@ public class HdmiCecLocalDevicePlaybackTest {
|
||||
super.wakeUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
AudioManager getAudioManager() {
|
||||
return mAudioManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
void pauseActiveMediaSessions() {
|
||||
mActiveMediaSessionsPaused = true;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
@@ -166,11 +165,6 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
return false;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
@@ -99,36 +101,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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user