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

Commit ff115f16 authored by Amy's avatar Amy Committed by shubang
Browse files

Add an API for clients to know if a target device is connected to the

current device.

ag/5583395

Note the API also returns true if the current device itself is the
target device.

Test: manual
Change-Id: I30031fc98f4e6547bbe3492b22a65b6e11b6efda
parent 3e32f590
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -55,6 +55,10 @@ public final class HdmiControlManager {

    @Nullable private final IHdmiControlService mService;

    private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;

    private int mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;

    /**
     * Broadcast Action: Display OSD message.
     * <p>Send when the service has a message to display on screen for events
@@ -505,13 +509,40 @@ public final class HdmiControlManager {
     * @hide
     */
    public int getPhysicalAddress() {
        if (mPhysicalAddress != INVALID_PHYSICAL_ADDRESS) {
            return mPhysicalAddress;
        }
        try {
            return mService.getPhysicalAddress();
            mPhysicalAddress = mService.getPhysicalAddress();
            return mPhysicalAddress;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Check if the target device is connected to the current device. The
     * API also returns true if the current device is the target.
     *
     * @param targetDevice {@link HdmiDeviceInfo} of the target device.
     * @return true if {@code device} is directly or indirectly connected to the
     *
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public boolean isTargetDeviceConnected(HdmiDeviceInfo targetDevice) {
        mPhysicalAddress = getPhysicalAddress();
        if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
            return false;
        }
        int targetPhysicalAddress = targetDevice.getPhysicalAddress();
        if (targetPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
            return false;
        }
        return HdmiUtils.getLocalPortFromPhysicalAddress(targetPhysicalAddress, mPhysicalAddress)
            != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE;
    }

    /**
     * Listener used to get hotplug event from HDMI port.
     */
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.hardware.hdmi;

/**
 * Various utilities to handle HDMI CEC messages.
 *
 * TODO(b/110094868): unhide for Q
 * @hide
 */
public class HdmiUtils {

    /**
     * Return value of {@link #getLocalPortFromPhysicalAddress(int, int)}
     */
    static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1;
    static final int TARGET_SAME_PHYSICAL_ADDRESS = 0;

    private HdmiUtils() { /* cannot be instantiated */ }

    /**
     * Method to parse target physical address to the port number on the current device.
     *
     * <p>This check assumes target address is valid.
     *
     * @param targetPhysicalAddress is the physical address of the target device
     * @param myPhysicalAddress is the physical address of the current device
     * @return
     * If the target device is under the current device, return the port number of current device
     * that the target device is connected to. This also applies to the devices that are indirectly
     * connected to the current device.
     *
     * <p>If the target device has the same physical address as the current device, return
     * {@link #TARGET_SAME_PHYSICAL_ADDRESS}.
     *
     * <p>If the target device is not under the current device, return
     * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}.
     */
    public static int getLocalPortFromPhysicalAddress(
            int targetPhysicalAddress, int myPhysicalAddress) {
        if (myPhysicalAddress == targetPhysicalAddress) {
            return TARGET_SAME_PHYSICAL_ADDRESS;
        }

        int mask = 0xF000;
        int finalMask = 0xF000;
        int maskedAddress = myPhysicalAddress;

        while (maskedAddress != 0) {
            maskedAddress = myPhysicalAddress & mask;
            finalMask |= mask;
            mask >>= 4;
        }

        int portAddress = targetPhysicalAddress & finalMask;
        if ((portAddress & (finalMask << 4)) != myPhysicalAddress) {
            return TARGET_NOT_UNDER_LOCAL_DEVICE;
        }

        mask <<= 4;
        int port = portAddress & mask;
        while ((port >> 4) != 0) {
            port >>= 4;
        }
        return port;
    }
}
+82 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.hardware.hdmi;

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

import android.support.test.filters.SmallTest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@SmallTest
@RunWith(JUnit4.class)
/** Tests for {@link HdmiUtils} class. */
public class HdmiUtilsTest {

    @Test
    public void pathToPort_isMe() {
        int targetPhysicalAddress = 0x1000;
        int myPhysicalAddress = 0x1000;
        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
                HdmiUtils.TARGET_SAME_PHYSICAL_ADDRESS);
    }

    @Test
    public void pathToPort_isDirectlyBelow() {
        int targetPhysicalAddress = 0x1100;
        int myPhysicalAddress = 0x1000;
        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
            targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1);
    }

    @Test
    public void pathToPort_isBelow() {
        int targetPhysicalAddress = 0x1110;
        int myPhysicalAddress = 0x1000;
        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
            targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1);
    }

    @Test
    public void pathToPort_neitherMeNorBelow() {
        int targetPhysicalAddress = 0x3000;
        int myPhysicalAddress = 0x2000;
        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
                HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);

        targetPhysicalAddress = 0x2200;
        myPhysicalAddress = 0x3300;
        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
                HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);

        targetPhysicalAddress = 0x2213;
        myPhysicalAddress = 0x2212;
        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
                HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);

        targetPhysicalAddress = 0x2340;
        myPhysicalAddress = 0x2310;
        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
                HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
    }
}
+0 −46
Original line number Diff line number Diff line
@@ -56,11 +56,6 @@ abstract class HdmiCecLocalDevice {
    // Within the timer, a received <User Control Pressed> will start "Press and Hold" behavior.
    // When it expires, we can assume <User Control Release> is received.
    private static final int FOLLOWER_SAFETY_TIMEOUT = 550;
    /**
     * Return value of {@link #getLocalPortFromPhysicalAddress(int)}
     */
    private static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1;
    private static final int TARGET_SAME_PHYSICAL_ADDRESS = 0;

    protected final HdmiControlService mService;
    protected final int mDeviceType;
@@ -1061,47 +1056,6 @@ abstract class HdmiCecLocalDevice {
        pw.println(String.format("mActiveRoutingPath: 0x%04x", mActiveRoutingPath));
    }

    /**
     * Method to parse target physical address to the port number on the current device.
     *
     * <p>This check assumes target address is valid.
     * @param targetPhysicalAddress is the physical address of the target device
     * @return
     * If the target device is under the current device, return the port number of current device
     * that the target device is connected to.
     *
     * <p>If the target device has the same physical address as the current device, return
     * {@link #TARGET_SAME_PHYSICAL_ADDRESS}.
     *
     * <p>If the target device is not under the current device, return
     * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}.
     */
    protected int getLocalPortFromPhysicalAddress(int targetPhysicalAddress) {
        int myPhysicalAddress = mService.getPhysicalAddress();
        if (myPhysicalAddress == targetPhysicalAddress) {
            return TARGET_SAME_PHYSICAL_ADDRESS;
        }
        int finalMask = 0xF000;
        int mask;
        int port = 0;
        for (mask = 0x0F00; mask > 0x000F;  mask >>= 4) {
            if ((myPhysicalAddress & mask) == 0)  {
                port = mask & targetPhysicalAddress;
                break;
            } else {
                finalMask |= mask;
            }
        }
        if (finalMask != 0xFFFF && (finalMask & targetPhysicalAddress) == myPhysicalAddress) {
            while (mask != 0x000F) {
                mask >>= 4;
                port >>= 4;
            }
            return port;
        }
        return TARGET_NOT_UNDER_LOCAL_DEVICE;
    }

    /** Calculates the physical address for {@code activePortId}.
     *
     * <p>This method assumes current device physical address is valid.
+53 −0
Original line number Diff line number Diff line
@@ -69,6 +69,12 @@ final class HdmiUtils {
        "Secondary_TV",
    };

    /**
     * Return value of {@link #getLocalPortFromPhysicalAddress(int, int)}
     */
    static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1;
    static final int TARGET_SAME_PHYSICAL_ADDRESS = 0;

    private HdmiUtils() { /* cannot be instantiated */ }

    /**
@@ -392,6 +398,53 @@ final class HdmiUtils {
        pw.decreaseIndent();
    }

    /**
     * Method to parse target physical address to the port number on the current device.
     *
     * <p>This check assumes target address is valid.
     *
     * @param targetPhysicalAddress is the physical address of the target device
     * @param myPhysicalAddress is the physical address of the current device
     * @return
     * If the target device is under the current device, return the port number of current device
     * that the target device is connected to. This also applies to the devices that are indirectly
     * connected to the current device.
     *
     * <p>If the target device has the same physical address as the current device, return
     * {@link #TARGET_SAME_PHYSICAL_ADDRESS}.
     *
     * <p>If the target device is not under the current device, return
     * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}.
     */
    public static int getLocalPortFromPhysicalAddress(
            int targetPhysicalAddress, int myPhysicalAddress) {
        if (myPhysicalAddress == targetPhysicalAddress) {
            return TARGET_SAME_PHYSICAL_ADDRESS;
        }

        int mask = 0xF000;
        int finalMask = 0xF000;
        int maskedAddress = myPhysicalAddress;

        while (maskedAddress != 0) {
            maskedAddress = myPhysicalAddress & mask;
            finalMask |= mask;
            mask >>= 4;
        }

        int portAddress = targetPhysicalAddress & finalMask;
        if ((portAddress & (finalMask << 4)) != myPhysicalAddress) {
            return TARGET_NOT_UNDER_LOCAL_DEVICE;
        }

        mask <<= 4;
        int port = portAddress & mask;
        while ((port >> 4) != 0) {
            port >>= 4;
        }
        return port;
    }

    // Device configuration of its supported Codecs and their Short Audio Descriptors.
    public static class DeviceConfig {
        /** Name of the device. Should be {@link Constants.AudioDevice}. **/
Loading