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

Commit 2b152015 authored by Jinsuk Kim's avatar Jinsuk Kim
Browse files

Add portID information in HdmiCecDeviceInfo

This change makes it convenient to get the HDMI port ID from the device
info without having to look it up through a separate HdmiPortInfo, which
happens in many places.

Also removed port information lookup loop by introducing two maps variable
in Control Service: port path ->port ID, and port ID -> port info.

Bug: 16547583
Change-Id: Ibfff722a16b626230766058efcc819e9c8ca0663
parent 5f054cea
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ public final class HdmiCecDeviceInfo implements Parcelable {
    // are immutable value.
    private final int mLogicalAddress;
    private final int mPhysicalAddress;
    private final int mPortId;
    private final int mDeviceType;
    private final int mVendorId;
    private final String mDisplayName;
@@ -80,11 +81,12 @@ public final class HdmiCecDeviceInfo implements Parcelable {
                public HdmiCecDeviceInfo createFromParcel(Parcel source) {
                    int logicalAddress = source.readInt();
                    int physicalAddress = source.readInt();
                    int portId = source.readInt();
                    int deviceType = source.readInt();
                    int vendorId = source.readInt();
                    String displayName = source.readString();
                    return new HdmiCecDeviceInfo(logicalAddress, physicalAddress, deviceType,
                            vendorId, displayName);
                    return new HdmiCecDeviceInfo(logicalAddress, physicalAddress, portId,
                            deviceType, vendorId, displayName);
                }

                @Override
@@ -98,15 +100,17 @@ public final class HdmiCecDeviceInfo implements Parcelable {
     *
     * @param logicalAddress logical address of HDMI-CEC device
     * @param physicalAddress physical address of HDMI-CEC device
     * @param portId HDMI port ID (1 for HDMI1)
     * @param deviceType type of device
     * @param vendorId vendor id of device. Used for vendor specific command.
     * @param displayName name of device
     * @hide
     */
    public HdmiCecDeviceInfo(int logicalAddress, int physicalAddress, int deviceType,
    public HdmiCecDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType,
            int vendorId, String displayName) {
        mLogicalAddress = logicalAddress;
        mPhysicalAddress = physicalAddress;
        mPortId = portId;
        mDeviceType = deviceType;
        mDisplayName = displayName;
        mVendorId = vendorId;
@@ -126,6 +130,13 @@ public final class HdmiCecDeviceInfo implements Parcelable {
        return mPhysicalAddress;
    }

    /**
     * Return the port ID.
     */
    public int getPortId() {
        return mPortId;
    }

    /**
     * Return type of the device. For more details, refer constants between
     * {@link DEVICE_TV} and {@link DEVICE_INACTIVE}.
@@ -179,6 +190,7 @@ public final class HdmiCecDeviceInfo implements Parcelable {
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mLogicalAddress);
        dest.writeInt(mPhysicalAddress);
        dest.writeInt(mPortId);
        dest.writeInt(mDeviceType);
        dest.writeInt(mVendorId);
        dest.writeString(mDisplayName);
@@ -189,6 +201,7 @@ public final class HdmiCecDeviceInfo implements Parcelable {
        StringBuffer s = new StringBuffer();
        s.append("logical_address: ").append(mLogicalAddress).append(", ");
        s.append("physical_address: ").append(mPhysicalAddress).append(", ");
        s.append("port_id: ").append(mPortId).append(", ");
        s.append("device_type: ").append(mDeviceType).append(", ");
        s.append("vendor_id: ").append(mVendorId).append(", ");
        s.append("display_name: ").append(mDisplayName);
@@ -204,6 +217,7 @@ public final class HdmiCecDeviceInfo implements Parcelable {
        HdmiCecDeviceInfo other = (HdmiCecDeviceInfo) obj;
        return mLogicalAddress == other.mLogicalAddress
                && mPhysicalAddress == other.mPhysicalAddress
                && mPortId == other.mPortId
                && mDeviceType == other.mDeviceType
                && mVendorId == other.mVendorId
                && mDisplayName.equals(other.mDisplayName);
+8 −2
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ final class DeviceDiscoveryAction extends FeatureAction {
        private final int mLogicalAddress;

        private int mPhysicalAddress = Constants.INVALID_PHYSICAL_ADDRESS;
        private int mPortId = Constants.INVALID_PORT_ID;
        private int mVendorId = Constants.UNKNOWN_VENDOR_ID;
        private String mDisplayName = "";
        private int mDeviceType = HdmiCecDeviceInfo.DEVICE_INACTIVE;
@@ -78,8 +79,8 @@ final class DeviceDiscoveryAction extends FeatureAction {
        }

        private HdmiCecDeviceInfo toHdmiCecDeviceInfo() {
            return new HdmiCecDeviceInfo(mLogicalAddress, mPhysicalAddress, mDeviceType, mVendorId,
                    mDisplayName);
            return new HdmiCecDeviceInfo(mLogicalAddress, mPhysicalAddress, mPortId, mDeviceType,
                    mVendorId, mDisplayName);
        }
    }

@@ -252,12 +253,17 @@ final class DeviceDiscoveryAction extends FeatureAction {

        byte params[] = cmd.getParams();
        current.mPhysicalAddress = HdmiUtils.twoBytesToInt(params);
        current.mPortId = getPortId(current.mPhysicalAddress);
        current.mDeviceType = params[2] & 0xFF;

        increaseProcessedDeviceCount();
        checkAndProceedStage();
    }

    private int getPortId(int physicalAddress) {
        return tv().getPortId(physicalAddress);
    }

    private void handleSetOsdName(HdmiCecMessage cmd) {
        Preconditions.checkState(mProcessedDeviceCount < mDevices.size());

+6 −2
Original line number Diff line number Diff line
@@ -190,6 +190,10 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
        }
    }

    int getPortId(int physicalAddress) {
        return mService.pathToPortId(physicalAddress);
    }

    /**
     * Returns the previous port id kept to handle input switching on <Inactive Source>.
     */
@@ -512,8 +516,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
        }

        addCecDevice(new HdmiCecDeviceInfo(deviceInfo.getLogicalAddress(),
                deviceInfo.getPhysicalAddress(), deviceInfo.getDeviceType(),
                deviceInfo.getVendorId(), osdName));
                deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(),
                deviceInfo.getDeviceType(), deviceInfo.getVendorId(), osdName));
        return true;
    }

+48 −47
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings.Global;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -197,6 +198,12 @@ public final class HdmiControlService extends SystemService {
    // from being modified.
    private List<HdmiPortInfo> mPortInfo;

    // Map from path(physical address) to port ID.
    private SparseIntArray mPortIdMap = new SparseIntArray();

    // Map from port ID to HdmiPortInfo.
    private SparseArray<HdmiPortInfo> mPortInfoMap = new SparseArray<>();

    private HdmiCecMessageValidator mMessageValidator;

    private final PowerStateReceiver mPowerStateReceiver = new PowerStateReceiver();
@@ -238,7 +245,7 @@ public final class HdmiControlService extends SystemService {
        if (mMhlController == null) {
            Slog.i(TAG, "Device does not support MHL-control.");
        }
        mPortInfo = initPortInfo();
        initPortInfo();
        mMessageValidator = new HdmiCecMessageValidator(this);
        publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());

@@ -318,7 +325,7 @@ public final class HdmiControlService extends SystemService {
    // Initialize HDMI port information. Combine the information from CEC and MHL HAL and
    // keep them in one place.
    @ServiceThreadOnly
    private List<HdmiPortInfo> initPortInfo() {
    private void initPortInfo() {
        assertRunOnServiceThread();
        HdmiPortInfo[] cecPortInfo = null;

@@ -328,7 +335,12 @@ public final class HdmiControlService extends SystemService {
            cecPortInfo = mCecController.getPortInfos();
        }
        if (cecPortInfo == null) {
            return Collections.emptyList();
            return;
        }

        for (HdmiPortInfo info : cecPortInfo) {
            mPortIdMap.put(info.getAddress(), info.getId());
            mPortInfoMap.put(info.getId(), info);
        }

        HdmiPortInfo[] mhlPortInfo = new HdmiPortInfo[0];
@@ -337,27 +349,24 @@ public final class HdmiControlService extends SystemService {
            // mhlPortInfo = mMhlController.getPortInfos();
        }

        // Use the id (port number) to find the matched info between CEC and MHL to combine them
        // into one. Leave the field `mhlSupported` to false if matched MHL entry is not found.
        ArrayList<HdmiPortInfo> result = new ArrayList<>(cecPortInfo.length);
        for (int i = 0; i < cecPortInfo.length; ++i) {
            HdmiPortInfo cec = cecPortInfo[i];
            int id = cec.getId();
            boolean mhlInfoFound = false;
            for (HdmiPortInfo mhl : mhlPortInfo) {
                if (id == mhl.getId()) {
                    result.add(new HdmiPortInfo(id, cec.getType(), cec.getAddress(),
                            cec.isCecSupported(), mhl.isMhlSupported(), cec.isArcSupported()));
                    mhlInfoFound = true;
                    break;
        ArraySet<Integer> mhlSupportedPorts = new ArraySet<Integer>(mhlPortInfo.length);
        for (HdmiPortInfo info : mhlPortInfo) {
            if (info.isMhlSupported()) {
                mhlSupportedPorts.add(info.getId());
            }
        }
            if (!mhlInfoFound) {
                result.add(cec);

        // Build HDMI port info list with CEC port info plus MHL supported flag.
        ArrayList<HdmiPortInfo> result = new ArrayList<>(cecPortInfo.length);
        for (HdmiPortInfo info : cecPortInfo) {
            if (mhlSupportedPorts.contains(info.getId())) {
                result.add(new HdmiPortInfo(info.getId(), info.getType(), info.getAddress(),
                        info.isCecSupported(), true, info.isArcSupported()));
            } else {
                result.add(info);
            }
        }

        return Collections.unmodifiableList(result);
        mPortInfo = Collections.unmodifiableList(result);
    }

    /**
@@ -366,22 +375,19 @@ public final class HdmiControlService extends SystemService {
     * @param portId HDMI port id
     * @return {@link HdmiPortInfo} for the given port
     */
    @ServiceThreadOnly
    HdmiPortInfo getPortInfo(int portId) {
        // mPortInfo is an unmodifiable list and the only reference to its inner list.
        // No lock is necessary.
        for (HdmiPortInfo info : mPortInfo) {
            if (portId == info.getId()) {
                return info;
            }
        }
        return null;
        assertRunOnServiceThread();
        return mPortInfoMap.get(portId, null);
    }

    /**
     * Returns the routing path (physical address) of the HDMI port for the given
     * port id.
     */
    @ServiceThreadOnly
    int portIdToPath(int portId) {
        assertRunOnServiceThread();
        HdmiPortInfo portInfo = getPortInfo(portId);
        if (portInfo == null) {
            Slog.e(TAG, "Cannot find the port info: " + portId);
@@ -396,23 +402,17 @@ public final class HdmiControlService extends SystemService {
     * the port id to be returned is the ID associated with the port address
     * 0x1000 (1.0.0.0) which is the topmost path of the given routing path.
     */
    @ServiceThreadOnly
    int pathToPortId(int path) {
        assertRunOnServiceThread();
        int portAddress = path & Constants.ROUTING_PATH_TOP_MASK;
        for (HdmiPortInfo info : mPortInfo) {
            if (portAddress == info.getAddress()) {
                return info.getId();
            }
        }
        return Constants.INVALID_PORT_ID;
        return mPortIdMap.get(portAddress, Constants.INVALID_PORT_ID);
    }

    @ServiceThreadOnly
    boolean isValidPortId(int portId) {
        for (HdmiPortInfo info : mPortInfo) {
            if (portId == info.getId()) {
                return true;
            }
        }
        return false;
        assertRunOnServiceThread();
        return getPortInfo(portId) != null;
    }

    /**
@@ -468,12 +468,12 @@ public final class HdmiControlService extends SystemService {
    /**
     * Whether a device of the specified physical address is connected to ARC enabled port.
     */
    @ServiceThreadOnly
    boolean isConnectedToArcPort(int physicalAddress) {
        for (HdmiPortInfo portInfo : mPortInfo) {
            if (hasSameTopPort(portInfo.getAddress(), physicalAddress)
                    && portInfo.isArcSupported()) {
                return true;
            }
        assertRunOnServiceThread();
        int portId = mPortIdMap.get(physicalAddress);
        if (portId != Constants.INVALID_PORT_ID) {
            return mPortInfoMap.get(portId).isArcSupported();
        }
        return false;
    }
@@ -622,7 +622,8 @@ public final class HdmiControlService extends SystemService {
        // TODO: find better name instead of model name.
        String displayName = Build.MODEL;
        return new HdmiCecDeviceInfo(logicalAddress,
                getPhysicalAddress(), deviceType, getVendorId(), displayName);
                getPhysicalAddress(), pathToPortId(getPhysicalAddress()), deviceType,
                getVendorId(), displayName);
    }

    // Record class that monitors the event of the caller of being killed. Used to clean up
+1 −0
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ final class NewDeviceAction extends FeatureAction {
        }
        tv().addCecDevice(new HdmiCecDeviceInfo(
                mDeviceLogicalAddress, mDevicePhysicalAddress,
                tv().getPortId(mDevicePhysicalAddress),
                HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress),
                mVendorId, mDisplayName));