Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71afeaa6 authored by Yan Han's avatar Yan Han
Browse files

Add wrapper for AudioManager, allowing it to be faked in tests

Makes HdmiControlService's test constructor take a wrapper for
AudioManager, allowing it to be to be faked in unit tests in a similar
way to AudioDeviceVolumeManager.

Adds the FakeAudioFramework class, which exposes a fake for both
AudioManager and AudioDeviceVolumeManager. FakeAudioFramework stores
the shared internal state for both managers, simulating AudioService.

Renames the existing wrapper and wrapper interface for
AudioDeviceVolumeManager to make it more consistent with
PowerManagerInternal. For example, instead of ThingWrapper and
FakeThingWrapper implementing ThingWrapperInterface, we have
DefaultThingWrapper and FakeThingWrapper implementing ThingWrapper.

Bug: 217923086
Test: atest com.android.server.hdmi

Change-Id: Ia9d5f7aa382223d523771b8d0382d40d622aa292
parent 091b2e2e
Loading
Loading
Loading
Loading
+27 −30
Original line number Diff line number Diff line
@@ -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,37 @@ 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 {

    private static final String TAG = "AudioDeviceVolumeManagerWrapper";

    private final AudioDeviceVolumeManager mAudioDeviceVolumeManager;
public interface AudioDeviceVolumeManagerWrapper {

    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);
}
+0 −61
Original line number Diff line number Diff line
/*
 * 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);
}
+105 −0
Original line number Diff line number Diff line
/*
 * 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);
}
+21 −23
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 * 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.
@@ -16,44 +16,45 @@

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.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.
 * "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 FakeAudioDeviceVolumeManagerWrapper implements
        AudioDeviceVolumeManagerWrapperInterface {
public class DefaultAudioDeviceVolumeManagerWrapper
        implements AudioDeviceVolumeManagerWrapper {

    private final Set<OnDeviceVolumeBehaviorChangedListener> mVolumeBehaviorListeners;
    private static final String TAG = "AudioDeviceVolumeManagerWrapper";

    public FakeAudioDeviceVolumeManagerWrapper() {
        mVolumeBehaviorListeners = new HashSet<>();
    private final AudioDeviceVolumeManager mAudioDeviceVolumeManager;

    public DefaultAudioDeviceVolumeManagerWrapper(Context context) {
        mAudioDeviceVolumeManager = new AudioDeviceVolumeManager(context);
    }

    @Override
    public void addOnDeviceVolumeBehaviorChangedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnDeviceVolumeBehaviorChangedListener listener)
            @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener)
            throws SecurityException {
        mVolumeBehaviorListeners.add(listener);
        mAudioDeviceVolumeManager.addOnDeviceVolumeBehaviorChangedListener(executor, listener);
    }

    @Override
    public void removeOnDeviceVolumeBehaviorChangedListener(
            @NonNull OnDeviceVolumeBehaviorChangedListener listener) {
        mVolumeBehaviorListeners.remove(listener);
            @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener) {
        mAudioDeviceVolumeManager.removeOnDeviceVolumeBehaviorChangedListener(listener);
    }

    @Override
@@ -61,12 +62,9 @@ public class FakeAudioDeviceVolumeManagerWrapper implements
            @NonNull AudioDeviceAttributes device,
            @NonNull VolumeInfo volume,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnAudioDeviceVolumeChangedListener vclistener,
            @NonNull AudioDeviceVolumeManager.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);
        }
        mAudioDeviceVolumeManager.setDeviceAbsoluteVolumeBehavior(device, volume, executor,
                vclistener, handlesVolumeAdjustment);
    }
}
+115 −0
Original line number Diff line number Diff line
/*
 * 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);
    }

}
Loading