/*
 * Copyright 2020 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 android.hdmicec.cts;

import static com.google.common.truth.Truth.assertWithMessage;

import static org.junit.Assume.assumeTrue;

import android.hdmicec.cts.HdmiCecConstants.CecDeviceType;
import android.hdmicec.cts.error.DumpsysParseException;

import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;

import org.junit.Before;
import org.junit.rules.TestRule;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** Base class for all HDMI CEC CTS tests. */
@OptionClass(alias="hdmi-cec-client-cts-test")
public class BaseHdmiCecCtsTest extends BaseHostJUnit4Test {

    public static final String PROPERTY_LOCALE = "persist.sys.locale";
    private static final String POWER_CONTROL_MODE = "power_control_mode";
    private static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST =
            "power_state_change_on_active_source_lost";
    private static final String SET_MENU_LANGUAGE = "set_menu_language";
    private static final String SET_MENU_LANGUAGE_ENABLED = "1";

    /** Enum contains the list of possible address types. */
    private enum AddressType {
        DUMPSYS_AS_LOGICAL_ADDRESS("activeSourceLogicalAddress"),
        DUMPSYS_PHYSICAL_ADDRESS("physicalAddress");

        private String address;

        public String getAddressType() {
            return this.address;
        }

        private AddressType(String address) {
            this.address = address;
        }
    }

    public final HdmiCecClientWrapper hdmiCecClient;
    public List<LogicalAddress> mDutLogicalAddresses = new ArrayList<>();
    public @CecDeviceType int mTestDeviceType;

    /**
     * Constructor for BaseHdmiCecCtsTest.
     */
    public BaseHdmiCecCtsTest() {
        this(HdmiCecConstants.CEC_DEVICE_TYPE_UNKNOWN);
    }

    /**
     * Constructor for BaseHdmiCecCtsTest.
     *
     * @param clientParams Extra parameters to use when launching cec-client
     */
    public BaseHdmiCecCtsTest(String ...clientParams) {
        this(HdmiCecConstants.CEC_DEVICE_TYPE_UNKNOWN, clientParams);
    }

    /**
     * Constructor for BaseHdmiCecCtsTest.
     *
     * @param testDeviceType The primary test device type. This is used to determine to which
     *     logical address of the DUT messages should be sent.
     * @param clientParams Extra parameters to use when launching cec-client
     */
    public BaseHdmiCecCtsTest(@CecDeviceType int testDeviceType, String... clientParams) {
        this.hdmiCecClient = new HdmiCecClientWrapper(clientParams);
        mTestDeviceType = testDeviceType;
    }

    @Before
    public void setUp() throws Exception {
        setCec14();

        mDutLogicalAddresses = getDumpsysLogicalAddresses();
        hdmiCecClient.setTargetLogicalAddress(getTargetLogicalAddress());
        boolean startAsTv = !hasDeviceType(HdmiCecConstants.CEC_DEVICE_TYPE_TV);
        hdmiCecClient.init(startAsTv, getDevice());
    }

    /** Class with predefined rules which can be used by HDMI CEC CTS tests. */
    public static class CecRules {

        public static TestRule requiresCec(BaseHostJUnit4Test testPointer) {
            return new RequiredFeatureRule(testPointer, HdmiCecConstants.HDMI_CEC_FEATURE);
        }

        public static TestRule requiresLeanback(BaseHostJUnit4Test testPointer) {
            return new RequiredFeatureRule(testPointer, HdmiCecConstants.LEANBACK_FEATURE);
        }

        public static TestRule requiresDeviceType(
                BaseHostJUnit4Test testPointer, @CecDeviceType int dutDeviceType) {
            return RequiredPropertyRule.asCsvContainsValue(
                    testPointer,
                    HdmiCecConstants.HDMI_DEVICE_TYPE_PROPERTY,
                    Integer.toString(dutDeviceType));
        }

        /** This rule will skip the test if the DUT belongs to the HDMI device type deviceType. */
        public static TestRule skipDeviceType(
                BaseHostJUnit4Test testPointer, @CecDeviceType int deviceType) {
            return RequiredPropertyRule.asCsvDoesNotContainsValue(
                    testPointer,
                    HdmiCecConstants.HDMI_DEVICE_TYPE_PROPERTY,
                    Integer.toString(deviceType));
        }
    }

    @Option(name = HdmiCecConstants.PHYSICAL_ADDRESS_NAME,
        description = "HDMI CEC physical address of the DUT",
        mandatory = false)
    public static int dutPhysicalAddress = HdmiCecConstants.DEFAULT_PHYSICAL_ADDRESS;

    /** Gets the physical address of the DUT by parsing the dumpsys hdmi_control. */
    public int getDumpsysPhysicalAddress() throws DumpsysParseException {
        return getDumpsysPhysicalAddress(getDevice());
    }

    /** Gets the physical address of the specified device by parsing the dumpsys hdmi_control. */
    public static int getDumpsysPhysicalAddress(ITestDevice device) throws DumpsysParseException {
        return parseRequiredAddressFromDumpsys(device, AddressType.DUMPSYS_PHYSICAL_ADDRESS);
    }

    /** Gets the list of logical addresses of the DUT by parsing the dumpsys hdmi_control. */
    public List<LogicalAddress> getDumpsysLogicalAddresses() throws DumpsysParseException {
        return getDumpsysLogicalAddresses(getDevice());
    }

    /** Gets the list of logical addresses of the device by parsing the dumpsys hdmi_control. */
    public static List<LogicalAddress> getDumpsysLogicalAddresses(ITestDevice device)
            throws DumpsysParseException {
        List<LogicalAddress> logicalAddressList = new ArrayList<>();
        String line;
        String pattern =
                "(.*?)"
                        + "(mDeviceInfo:)(.*)(logical_address: )"
                        + "(?<"
                        + "logicalAddress"
                        + ">0x\\p{XDigit}{2})"
                        + "(.*?)";
        Pattern p = Pattern.compile(pattern);
        try {
            String dumpsys = device.executeShellCommand("dumpsys hdmi_control");
            BufferedReader reader = new BufferedReader(new StringReader(dumpsys));
            while ((line = reader.readLine()) != null) {
                Matcher m = p.matcher(line);
                if (m.matches()) {
                    int address = Integer.decode(m.group("logicalAddress"));
                    LogicalAddress logicalAddress = LogicalAddress.getLogicalAddress(address);
                    logicalAddressList.add(logicalAddress);
                }
            }
            if (!logicalAddressList.isEmpty()) {
                return logicalAddressList;
            }
        } catch (IOException | DeviceNotAvailableException e) {
            throw new DumpsysParseException(
                    "Could not parse logicalAddress from dumpsys.", e);
        }
        throw new DumpsysParseException(
                "Could not parse logicalAddress from dumpsys.");
    }

    /**
     * Gets the system audio mode status of the device by parsing the dumpsys hdmi_control. Returns
     * true when system audio mode is on and false when system audio mode is off
     */
    public boolean isSystemAudioModeOn(ITestDevice device) throws DumpsysParseException {
        List<LogicalAddress> logicalAddressList = new ArrayList<>();
        String line;
        String pattern =
                "(.*?)"
                        + "(mSystemAudioActivated: )"
                        + "(?<"
                        + "systemAudioModeStatus"
                        + ">[true|false])"
                        + "(.*?)";
        Pattern p = Pattern.compile(pattern);
        try {
            String dumpsys = device.executeShellCommand("dumpsys hdmi_control");
            BufferedReader reader = new BufferedReader(new StringReader(dumpsys));
            while ((line = reader.readLine()) != null) {
                Matcher m = p.matcher(line);
                if (m.matches()) {
                    return m.group("systemAudioModeStatus").equals("true");
                }
            }
        } catch (IOException | DeviceNotAvailableException e) {
            throw new DumpsysParseException("Could not parse system audio mode from dumpsys.", e);
        }
        throw new DumpsysParseException("Could not parse system audio mode from dumpsys.");
    }

    /** Gets the DUT's logical address to which messages should be sent */
    public LogicalAddress getTargetLogicalAddress() throws DumpsysParseException {
        return getTargetLogicalAddress(getDevice(), mTestDeviceType);
    }

    /** Gets the given device's logical address to which messages should be sent */
    public static LogicalAddress getTargetLogicalAddress(ITestDevice device) throws DumpsysParseException {
        return getTargetLogicalAddress(device, HdmiCecConstants.CEC_DEVICE_TYPE_UNKNOWN);
    }

    /** Gets the given device's logical address to which messages should be sent, based on the test
     * device type.
     *
     * When the test doesn't specify a device type, or the device doesn't have a logical address
     * that matches the specified device type, use the first logical address.
     *
     */
    public static LogicalAddress getTargetLogicalAddress(ITestDevice device, int testDeviceType)
            throws DumpsysParseException {
        List<LogicalAddress> logicalAddressList = getDumpsysLogicalAddresses(device);
        for (LogicalAddress address : logicalAddressList) {
            if (address.getDeviceType() == testDeviceType) {
                return address;
            }
        }
        return logicalAddressList.get(0);
    }

    /**
     * Parses the dumpsys hdmi_control to get the logical address of the current device registered
     * as active source.
     */
    public LogicalAddress getDumpsysActiveSourceLogicalAddress() throws DumpsysParseException {
        ITestDevice device = getDevice();
        int address =
                parseRequiredAddressFromDumpsys(device, AddressType.DUMPSYS_AS_LOGICAL_ADDRESS);
        return LogicalAddress.getLogicalAddress(address);
    }

    private static int parseRequiredAddressFromDumpsys(ITestDevice device, AddressType addressType)
            throws DumpsysParseException {
        Matcher m;
        String line;
        String pattern;
        switch (addressType) {
            case DUMPSYS_PHYSICAL_ADDRESS:
                pattern =
                        "(.*?)"
                                + "(physical_address: )"
                                + "(?<"
                                + addressType.getAddressType()
                                + ">0x\\p{XDigit}{4})"
                                + "(.*?)";
                break;
            case DUMPSYS_AS_LOGICAL_ADDRESS:
                pattern =
                        "(.*?)"
                                + "(mActiveSource: )"
                                + "(\\(0x)"
                                + "(?<"
                                + addressType.getAddressType()
                                + ">\\d+)"
                                + "(, )"
                                + "(0x)"
                                + "(?<physicalAddress>\\d+)"
                                + "(\\))"
                                + "(.*?)";
                break;
            default:
                throw new DumpsysParseException(
                        "Incorrect parameters", new IllegalArgumentException());
        }

        try {
            Pattern p = Pattern.compile(pattern);
            String dumpsys = device.executeShellCommand("dumpsys hdmi_control");
            BufferedReader reader = new BufferedReader(new StringReader(dumpsys));
            while ((line = reader.readLine()) != null) {
                m = p.matcher(line);
                if (m.matches()) {
                    int address = Integer.decode(m.group(addressType.getAddressType()));
                    return address;
                }
            }
        } catch (IOException | DeviceNotAvailableException e) {
            throw new DumpsysParseException(
                    "Could not parse " + addressType.getAddressType() + " from dumpsys.", e);
        }
        throw new DumpsysParseException(
                "Could not parse " + addressType.getAddressType() + " from dumpsys.");
    }

    public boolean hasDeviceType(@CecDeviceType int deviceType) {
        for (LogicalAddress address : mDutLogicalAddresses) {
            if (address.getDeviceType() == deviceType) {
                return true;
            }
        }
        return false;
    }

    public boolean hasLogicalAddress(LogicalAddress address) {
        return mDutLogicalAddresses.contains(address);
    }

    private static void setCecVersion(ITestDevice device, int cecVersion) throws Exception {
        device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_version " +
                cecVersion);

        TimeUnit.SECONDS.sleep(HdmiCecConstants.TIMEOUT_CEC_REINIT_SECONDS);
    }

    /**
     * Configures the device to use CEC 2.0. Skips the test if the device does not support CEC 2.0.
     * @throws Exception
     */
    public void setCec20() throws Exception {
        setCecVersion(getDevice(), HdmiCecConstants.CEC_VERSION_2_0);
        hdmiCecClient.sendCecMessage(hdmiCecClient.getSelfDevice(), CecOperand.GET_CEC_VERSION);
        String reportCecVersion = hdmiCecClient.checkExpectedOutput(hdmiCecClient.getSelfDevice(),
                CecOperand.CEC_VERSION);
        boolean supportsCec2 = CecMessage.getParams(reportCecVersion)
                >= HdmiCecConstants.CEC_VERSION_2_0;

        // Device still reports a CEC version < 2.0.
        assumeTrue(supportsCec2);
    }

    public void setCec14() throws Exception {
        setCecVersion(getDevice(), HdmiCecConstants.CEC_VERSION_1_4);
    }

    public String getSystemLocale() throws Exception {
        ITestDevice device = getDevice();
        return device.executeShellCommand("getprop " + PROPERTY_LOCALE).trim();
    }

    public static String extractLanguage(String locale) {
        return locale.split("[^a-zA-Z]")[0];
    }

    public void setSystemLocale(String locale) throws Exception {
        ITestDevice device = getDevice();
        device.executeShellCommand("setprop " + PROPERTY_LOCALE + " " + locale);
    }

    public boolean isLanguageEditable() throws Exception {
        return getSettingsValue(SET_MENU_LANGUAGE).equals(SET_MENU_LANGUAGE_ENABLED);
    }

    public static String getSettingsValue(ITestDevice device, String setting) throws Exception {
        return device.executeShellCommand("cmd hdmi_control cec_setting get " + setting)
                .replace(setting + " = ", "").trim();
    }

    public String getSettingsValue(String setting) throws Exception {
        return getSettingsValue(getDevice(), setting);
    }

    public static String setSettingsValue(ITestDevice device, String setting, String value)
            throws Exception {
        String val = getSettingsValue(device, setting);
        device.executeShellCommand("cmd hdmi_control cec_setting set " + setting + " " +
                value);
        return val;
    }

    public String setSettingsValue(String setting, String value) throws Exception {
        return setSettingsValue(getDevice(), setting, value);
    }

    public String getDeviceList() throws Exception {
        return getDevice().executeShellCommand(
                "dumpsys hdmi_control | sed -n '/mDeviceInfos/,/mCecController/{//!p;}'");
    }

    public void sendDeviceToSleepAndValidate() throws Exception {
        sendDeviceToSleep();
        assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
    }

    public void waitForTransitionTo(int finalState) throws Exception {
        int powerStatus;
        int waitTimeSeconds = 0;
        LogicalAddress cecClientDevice = hdmiCecClient.getSelfDevice();
        int transitionState;
        if (finalState == HdmiCecConstants.CEC_POWER_STATUS_STANDBY) {
            transitionState = HdmiCecConstants.CEC_POWER_STATUS_IN_TRANSITION_TO_STANDBY;
        } else if (finalState == HdmiCecConstants.CEC_POWER_STATUS_ON) {
            transitionState = HdmiCecConstants.CEC_POWER_STATUS_IN_TRANSITION_TO_ON;
        } else {
            throw new Exception("Unsupported final power state!");
        }
        do {
            TimeUnit.SECONDS.sleep(HdmiCecConstants.SLEEP_TIMESTEP_SECONDS);
            waitTimeSeconds += HdmiCecConstants.SLEEP_TIMESTEP_SECONDS;
            hdmiCecClient.sendCecMessage(cecClientDevice, CecOperand.GIVE_POWER_STATUS);
            powerStatus =
                    CecMessage.getParams(
                            hdmiCecClient.checkExpectedOutput(
                                    cecClientDevice, CecOperand.REPORT_POWER_STATUS));
            if (powerStatus == finalState) {
                return;
            }
        } while (powerStatus == transitionState
                && waitTimeSeconds <= HdmiCecConstants.MAX_SLEEP_TIME_SECONDS);
        if (powerStatus != finalState) {
            // Transition not complete even after wait, throw an Exception.
            throw new Exception("Power status did not change to expected state.");
        }
    }

    public void sendDeviceToSleepWithoutWait() throws Exception {
        ITestDevice device = getDevice();
        WakeLockHelper.acquirePartialWakeLock(device);
        device.executeShellCommand("input keyevent KEYCODE_SLEEP");
    }

    public void sendDeviceToSleep() throws Exception {
        sendDeviceToSleepWithoutWait();
        assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
        waitForTransitionTo(HdmiCecConstants.CEC_POWER_STATUS_STANDBY);
    }

    public void sendDeviceToSleepAndValidateUsingStandbyMessage(boolean directlyAddressed)
            throws Exception {
        ITestDevice device = getDevice();
        WakeLockHelper.acquirePartialWakeLock(device);
        if (directlyAddressed) {
            hdmiCecClient.sendCecMessage(LogicalAddress.TV, CecOperand.STANDBY);
        } else {
            hdmiCecClient.sendCecMessage(
                    LogicalAddress.TV, LogicalAddress.BROADCAST, CecOperand.STANDBY);
        }
        waitForTransitionTo(HdmiCecConstants.CEC_POWER_STATUS_STANDBY);
    }

    public void wakeUpDevice() throws Exception {
        ITestDevice device = getDevice();
        device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
        assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_AWAKE);
        waitForTransitionTo(HdmiCecConstants.CEC_POWER_STATUS_ON);
        WakeLockHelper.releasePartialWakeLock(device);
    }

    public void wakeUpDeviceWithoutWait() throws Exception {
        ITestDevice device = getDevice();
        device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
        assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_AWAKE);
        WakeLockHelper.releasePartialWakeLock(device);
    }

    public void checkStandbyAndWakeUp() throws Exception {
        assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
        wakeUpDevice();
    }

    public void assertDeviceWakefulness(String wakefulness) throws Exception {
        ITestDevice device = getDevice();
        String actualWakefulness;
        int waitTimeSeconds = 0;

        do {
            TimeUnit.SECONDS.sleep(HdmiCecConstants.SLEEP_TIMESTEP_SECONDS);
            waitTimeSeconds += HdmiCecConstants.SLEEP_TIMESTEP_SECONDS;
            actualWakefulness =
                    device.executeShellCommand("dumpsys power | grep mWakefulness=")
                            .trim().replace("mWakefulness=", "");
        } while (!actualWakefulness.equals(wakefulness)
                && waitTimeSeconds <= HdmiCecConstants.MAX_SLEEP_TIME_SECONDS);
        assertWithMessage(
                "Device wakefulness is "
                        + actualWakefulness
                        + " but expected to be "
                        + wakefulness)
                .that(actualWakefulness)
                .isEqualTo(wakefulness);
    }

    /**
     * Checks a given condition once every {@link HdmiCecConstants.SLEEP_TIMESTEP_SECONDS} seconds
     * until it is true, or {@link HdmiCecConstants.MAX_SLEEP_TIME_SECONDS} seconds have passed.
     * Triggers an assertion failure if the condition remains false after the time limit.
     * @param condition Callable that returns whether the condition is met
     * @param errorMessage The message to print if the condition is false
     */
    public void waitForCondition(Callable<Boolean> condition, String errorMessage)
            throws Exception {
        int waitTimeSeconds = 0;
        boolean conditionState;
        do {
            TimeUnit.SECONDS.sleep(HdmiCecConstants.SLEEP_TIMESTEP_SECONDS);
            waitTimeSeconds += HdmiCecConstants.SLEEP_TIMESTEP_SECONDS;
            conditionState = condition.call();
        } while (!conditionState && waitTimeSeconds <= HdmiCecConstants.MAX_SLEEP_TIME_SECONDS);
        assertWithMessage(errorMessage).that(conditionState).isTrue();
    }

    public void sendOtp() throws Exception {
        ITestDevice device = getDevice();
        device.executeShellCommand("cmd hdmi_control onetouchplay");
    }

    public String setPowerControlMode(String valToSet) throws Exception {
        return setSettingsValue(POWER_CONTROL_MODE, valToSet);
    }

    public String setPowerStateChangeOnActiveSourceLost(String valToSet) throws Exception {
        return setSettingsValue(POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, valToSet);
    }

    public boolean isDeviceActiveSource(ITestDevice device) throws DumpsysParseException {
        final String activeSource = "activeSource";
        final String pattern =
                "(.*?)"
                        + "(isActiveSource\\(\\): )"
                        + "(?<"
                        + activeSource
                        + ">\\btrue\\b|\\bfalse\\b)"
                        + "(.*?)";
        try {
            Pattern p = Pattern.compile(pattern);
            String dumpsys = device.executeShellCommand("dumpsys hdmi_control");
            BufferedReader reader = new BufferedReader(new StringReader(dumpsys));
            String line;
            while ((line = reader.readLine()) != null) {
                Matcher matcher = p.matcher(line);
                if (matcher.matches()) {
                    return matcher.group(activeSource).equals("true");
                }
            }
        } catch (IOException | DeviceNotAvailableException e) {
            throw new DumpsysParseException("Could not fetch 'dumpsys hdmi_control' output.", e);
        }
        throw new DumpsysParseException("Could not parse isActiveSource() from dumpsys.");
    }

    /**
     * For source devices, simulate that a sink is connected by responding to the
     * {@code Give Power Status} message that is sent when re-enabling CEC.
     * Validate that HdmiControlService#mIsCecAvailable is set to true as a result.
     */
    public void simulateCecSinkConnected(ITestDevice device, LogicalAddress source)
            throws Exception {
        hdmiCecClient.clearClientOutput();
        device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 0");
        waitForCondition(() -> !isCecAvailable(device), "Could not disable CEC");
        device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 1");
        // When a CEC device has just become available, the CEC adapter isn't able to send it
        // messages right away. Therefore we let the first <Give Power Status> message time-out, and
        // only respond to the retry.
        hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
        hdmiCecClient.clearClientOutput();
        hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
        hdmiCecClient.sendCecMessage(LogicalAddress.TV, source, CecOperand.REPORT_POWER_STATUS,
                CecMessage.formatParams(HdmiCecConstants.CEC_POWER_STATUS_STANDBY));
        waitForCondition(() -> isCecAvailable(device),
                "Simulating that a sink is connected, failed.");
    }

    boolean isCecAvailable(ITestDevice device) throws Exception {
        return device.executeShellCommand("dumpsys hdmi_control | grep mIsCecAvailable:")
                .replace("mIsCecAvailable:", "").trim().equals("true");
    }

    /**
     * Returns whether an audio output device is using full volume behavior by checking if it is in
     * the "mFullVolumeDevices" line in audio dumpsys. Example: "mFullVolumeDevices=0x400,0x40001".
     */
    public boolean isFullVolumeDevice(int audioOutputDevice) throws Exception {
        String[] splitLine = getDevice().executeShellCommand(
                "dumpsys audio | grep mFullVolumeDevices").split("=");
        if (splitLine.length < 2) {
            // No full volume devices
            return false;
        }
        String[] deviceStrings = splitLine[1].trim().split(",");
        for (String deviceString : deviceStrings) {
            try {
                if (Integer.decode(deviceString) == audioOutputDevice) {
                    return true;
                }
            } catch (NumberFormatException e) {
                // Ignore this device and continue
            }
        }
        return false;
    }
}
