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

Commit 697fc4ca authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Deprecate isConnectedToHdmiSwitch"

parents e1e35057 19ccf613
Loading
Loading
Loading
Loading
+168 −4
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 * 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.
@@ -16,14 +16,18 @@

package android.hardware.hdmi;

import android.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

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

public final class HdmiUtils {
    /**
     * Return value of {@link #getLocalPortFromPhysicalAddress(int, int)}
     */
@@ -78,4 +82,164 @@ public class HdmiUtils {
        }
        return port;
    }

    /**
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({HDMI_RELATIVE_POSITION_UNKNOWN, HDMI_RELATIVE_POSITION_DIRECTLY_BELOW,
            HDMI_RELATIVE_POSITION_BELOW, HDMI_RELATIVE_POSITION_SAME,
            HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE, HDMI_RELATIVE_POSITION_ABOVE,
            HDMI_RELATIVE_POSITION_SIBLING, HDMI_RELATIVE_POSITION_DIFFERENT_BRANCH})
    public @interface HdmiAddressRelativePosition {}
    /**
     * HDMI relative position is not determined.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public static final int HDMI_RELATIVE_POSITION_UNKNOWN = 0;
    /**
     * HDMI relative position: directly blow the device.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public static final int HDMI_RELATIVE_POSITION_DIRECTLY_BELOW = 1;
    /**
     * HDMI relative position: indirectly below the device.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public static final int HDMI_RELATIVE_POSITION_BELOW = 2;
    /**
     * HDMI relative position: the same device.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public static final int HDMI_RELATIVE_POSITION_SAME = 3;
    /**
     * HDMI relative position: directly above the device.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public static final int HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE = 4;
    /**
     * HDMI relative position: indirectly above the device.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public static final int HDMI_RELATIVE_POSITION_ABOVE = 5;
    /**
     * HDMI relative position: directly below a same device.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public static final int HDMI_RELATIVE_POSITION_SIBLING = 6;
    /**
     * HDMI relative position: different branch.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public static final int HDMI_RELATIVE_POSITION_DIFFERENT_BRANCH = 7;

    private static final int NPOS = -1;

    /**
     * Check if the given physical address is valid.
     *
     * @param address physical address
     * @return {@code true} if the given address is valid
     */
    public static boolean isValidPhysicalAddress(int address) {
        if (address < 0 || address >= 0xFFFF) {
            return false;
        }
        int mask = 0xF000;
        boolean hasZero = false;
        for (int i = 0; i < 4; i++) {
            if ((address & mask) == 0) {
                hasZero = true;
            } else if (hasZero) {
                // only 0s are valid after a 0.
                // e.g. 0x1012 is not valid.
                return false;
            }
            mask >>= 4;
        }
        return true;
    }


    /**
     * Returns the relative position of two physical addresses.
     */
    @HdmiAddressRelativePosition
    public static int getHdmiAddressRelativePosition(int src, int dest) {
        if (src == 0xFFFF || dest == 0xFFFF) {
            // address not assigned
            return HDMI_RELATIVE_POSITION_UNKNOWN;
        }
        try {
            int firstDiffPos = physicalAddressFirstDifferentDigitPos(src, dest);
            if (firstDiffPos == NPOS) {
                return HDMI_RELATIVE_POSITION_SAME;
            }
            int mask = (0xF000 >> (firstDiffPos * 4));
            int nextPos = firstDiffPos + 1;
            if ((src & mask) == 0) {
                // src is above dest
                if (nextPos == 4) {
                    // last digits are different
                    return HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE;
                }
                if (((0xF000 >> (nextPos * 4)) & dest) == 0) {
                    // next digit is 0
                    return HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE;
                }
                return HDMI_RELATIVE_POSITION_ABOVE;
            }

            if ((dest & mask) == 0) {
                // src is below dest
                if (nextPos == 4) {
                    // last digits are different
                    return HDMI_RELATIVE_POSITION_DIRECTLY_BELOW;
                }
                if (((0xF000 >> (nextPos * 4)) & src) == 0) {
                    // next digit is 0
                    return HDMI_RELATIVE_POSITION_DIRECTLY_BELOW;
                }
                return HDMI_RELATIVE_POSITION_BELOW;
            }
            if (nextPos == 4) {
                // last digits are different
                return HDMI_RELATIVE_POSITION_SIBLING;
            }
            if (((0xF000 >> (nextPos * 4)) & src) == 0 && ((0xF000 >> (nextPos * 4)) & dest) == 0) {
                return HDMI_RELATIVE_POSITION_SIBLING;
            }
            return HDMI_RELATIVE_POSITION_DIFFERENT_BRANCH;
        } catch (IllegalArgumentException e) {
            // invalid address
            return HDMI_RELATIVE_POSITION_UNKNOWN;
        }
    }

    private static int physicalAddressFirstDifferentDigitPos(int address1, int address2)
            throws IllegalArgumentException {
        if (!isValidPhysicalAddress(address1)) {
            throw new IllegalArgumentException(address1 + " is not a valid address.");
        }
        if (!isValidPhysicalAddress(address2)) {
            throw new IllegalArgumentException(address2 + " is not a valid address.");
        }
        int mask = 0xF000;
        for (int i = 0; i < 4; i++) {
            if ((address1 & mask) != (address2 & mask)) {
                return i;
            }
            mask = mask >> 4;
        }
        return NPOS;
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ LOCAL_MODULE_TAGS := tests
# Include all test java files
LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules frameworks-base-testutils
LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules frameworks-base-testutils truth-prebuilt

LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := HdmiCecTests
+145 −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 androidx.test.filters.SmallTest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
 * Tests for {@link HdmiUtils}.
 */
@RunWith(JUnit4.class)
@SmallTest
public class HdmiUtilsTest {
    @Test
    public void testInvalidAddress() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0, -1))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN);
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0xFFFF, 0xFFFF))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN);
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0xFFFFF, 0))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN);
    }

    @Test
    public void testSameAddress() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x1000, 0x1000))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_SAME);
    }

    @Test
    public void testDirectlyAbove() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x1000, 0x1200))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE);
    }

    @Test
    public void testDirectlyAbove_rootDevice() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x0000, 0x2000))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE);
    }

    @Test
    public void testDirectlyAbove_leafDevice() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x1240, 0x1245))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE);
    }

    @Test
    public void testAbove() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x1000, 0x1210))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_ABOVE);
    }

    @Test
    public void testAbove_rootDevice() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x0000, 0x1200))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_ABOVE);
    }

    @Test
    public void testDirectlyBelow() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x2250, 0x2200))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_BELOW);
    }

    @Test
    public void testDirectlyBelow_rootDevice() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x5000, 0x0000))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_BELOW);
    }

    @Test
    public void testDirectlyBelow_leafDevice() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x3249, 0x3240))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_BELOW);
    }

    @Test
    public void testBelow() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x5143, 0x5100))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_BELOW);
    }

    @Test
    public void testBelow_rootDevice() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x3420, 0x0000))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_BELOW);
    }

    @Test
    public void testSibling() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x4000, 0x5000))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_SIBLING);
    }

    @Test
    public void testSibling_leafDevice() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x798A, 0x798F))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_SIBLING);
    }

    @Test
    public void testDifferentBranch() {
        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x798A, 0x7970))
                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIFFERENT_BRANCH);
    }

    @Test
    public void isValidPysicalAddress_true() {
        assertThat(HdmiUtils.isValidPhysicalAddress(0)).isTrue();
        assertThat(HdmiUtils.isValidPhysicalAddress(0xFFFE)).isTrue();
        assertThat(HdmiUtils.isValidPhysicalAddress(0x1200)).isTrue();
    }

    @Test
    public void isValidPysicalAddress_outOfRange() {
        assertThat(HdmiUtils.isValidPhysicalAddress(-1)).isFalse();
        assertThat(HdmiUtils.isValidPhysicalAddress(0xFFFF)).isFalse();
        assertThat(HdmiUtils.isValidPhysicalAddress(0x10000)).isFalse();
    }

    @Test
    public void isValidPysicalAddress_nonTrailingZeros() {
        assertThat(HdmiUtils.isValidPhysicalAddress(0x0001)).isFalse();
        assertThat(HdmiUtils.isValidPhysicalAddress(0x0213)).isFalse();
    }
}
+41 −4
Original line number Diff line number Diff line
@@ -33,7 +33,10 @@ import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiUtils;
import android.hardware.hdmi.HdmiUtils.HdmiAddressRelativePosition;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
@@ -49,7 +52,6 @@ import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
@@ -145,6 +147,8 @@ public final class TvInputInfo implements Parcelable {
    // Attributes specific to HDMI
    private final HdmiDeviceInfo mHdmiDeviceInfo;
    private final boolean mIsConnectedToHdmiSwitch;
    @HdmiAddressRelativePosition
    private final int mHdmiConnectionRelativePosition;
    private final String mParentId;

    private final Bundle mExtras;
@@ -260,7 +264,9 @@ public final class TvInputInfo implements Parcelable {
    private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
            CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
            String setupActivity, boolean canRecord, int tunerCount, HdmiDeviceInfo hdmiDeviceInfo,
            boolean isConnectedToHdmiSwitch, String parentId, Bundle extras) {
            boolean isConnectedToHdmiSwitch,
            @HdmiAddressRelativePosition int hdmiConnectionRelativePosition, String parentId,
            Bundle extras) {
        mService = service;
        mId = id;
        mType = type;
@@ -275,6 +281,7 @@ public final class TvInputInfo implements Parcelable {
        mTunerCount = tunerCount;
        mHdmiDeviceInfo = hdmiDeviceInfo;
        mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
        mHdmiConnectionRelativePosition = hdmiConnectionRelativePosition;
        mParentId = parentId;
        mExtras = extras;
    }
@@ -419,6 +426,7 @@ public final class TvInputInfo implements Parcelable {
    /**
     * Returns {@code true}, if a CEC device for this TV input is connected to an HDMI switch, i.e.,
     * the device isn't directly connected to a HDMI port.
     * TODO(b/110094868): add @Deprecated for Q
     * @hide
     */
    @SystemApi
@@ -426,6 +434,16 @@ public final class TvInputInfo implements Parcelable {
        return mIsConnectedToHdmiSwitch;
    }

    /**
     * Returns the relative position of this HDMI input.
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    @HdmiAddressRelativePosition
    public int getHdmiConnectionRelativePosition() {
        return mHdmiConnectionRelativePosition;
    }

    /**
     * Checks if this TV input is marked hidden by the user in the settings.
     *
@@ -555,6 +573,7 @@ public final class TvInputInfo implements Parcelable {
                && mTunerCount == obj.mTunerCount
                && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
                && mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch
                && mHdmiConnectionRelativePosition == obj.mHdmiConnectionRelativePosition
                && TextUtils.equals(mParentId, obj.mParentId)
                && Objects.equals(mExtras, obj.mExtras);
    }
@@ -589,6 +608,7 @@ public final class TvInputInfo implements Parcelable {
        dest.writeInt(mTunerCount);
        dest.writeParcelable(mHdmiDeviceInfo, flags);
        dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
        dest.writeInt(mHdmiConnectionRelativePosition);
        dest.writeString(mParentId);
        dest.writeBundle(mExtras);
    }
@@ -630,6 +650,7 @@ public final class TvInputInfo implements Parcelable {
        mTunerCount = in.readInt();
        mHdmiDeviceInfo = in.readParcelable(null);
        mIsConnectedToHdmiSwitch = in.readByte() == 1;
        mHdmiConnectionRelativePosition = in.readInt();
        mParentId = in.readString();
        mExtras = in.readBundle();
    }
@@ -883,12 +904,17 @@ public final class TvInputInfo implements Parcelable {
            int type;
            boolean isHardwareInput = false;
            boolean isConnectedToHdmiSwitch = false;
            @HdmiAddressRelativePosition
            int hdmiConnectionRelativePosition = HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN;

            if (mHdmiDeviceInfo != null) {
                id = generateInputId(componentName, mHdmiDeviceInfo);
                type = TYPE_HDMI;
                isHardwareInput = true;
                isConnectedToHdmiSwitch = (mHdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
                hdmiConnectionRelativePosition = getRelativePosition(mContext, mHdmiDeviceInfo);
                isConnectedToHdmiSwitch =
                        hdmiConnectionRelativePosition
                                != HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_BELOW;
            } else if (mTvInputHardwareInfo != null) {
                id = generateInputId(componentName, mTvInputHardwareInfo);
                type = sHardwareTypeToTvInputType.get(mTvInputHardwareInfo.getType(), TYPE_TUNER);
@@ -901,7 +927,8 @@ public final class TvInputInfo implements Parcelable {
            return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId,
                    mIcon, mIconStandby, mIconDisconnected, mSetupActivity,
                    mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
                    mHdmiDeviceInfo, isConnectedToHdmiSwitch, mParentId, mExtras);
                    mHdmiDeviceInfo, isConnectedToHdmiSwitch, hdmiConnectionRelativePosition,
                    mParentId, mExtras);
        }

        private static String generateInputId(ComponentName name) {
@@ -923,6 +950,16 @@ public final class TvInputInfo implements Parcelable {
                    + tvInputHardwareInfo.getDeviceId();
        }

        private static int getRelativePosition(Context context, HdmiDeviceInfo info) {
            HdmiControlManager hcm =
                    (HdmiControlManager) context.getSystemService(Context.HDMI_CONTROL_SERVICE);
            if (hcm == null) {
                return HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN;
            }
            return HdmiUtils.getHdmiAddressRelativePosition(
                    info.getPhysicalAddress(), hcm.getPhysicalAddress());
        }

        private void parseServiceMetadata(int inputType) {
            ServiceInfo si = mResolveInfo.serviceInfo;
            PackageManager pm = mContext.getPackageManager();