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

Commit 3ff3dde6 authored by Shubang Lu's avatar Shubang Lu Committed by Android (Google) Code Review
Browse files

Merge "TIF: add cable detection for TV inputs"

parents 7d754b15 71d5c76f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -26618,11 +26618,15 @@ package android.media.tv {
    method public int describeContents();
    method public java.lang.String getAudioAddress();
    method public int getAudioType();
    method public int getCableConnectionStatus();
    method public int getDeviceId();
    method public int getHdmiPortId();
    method public int getType();
    method public void readFromParcel(android.os.Parcel);
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int CABLE_CONNECTION_STATUS_CONNECTED = 1; // 0x1
    field public static final int CABLE_CONNECTION_STATUS_DISCONNECTED = 2; // 0x2
    field public static final int CABLE_CONNECTION_STATUS_UNKNOWN = 0; // 0x0
    field public static final android.os.Parcelable.Creator<android.media.tv.TvInputHardwareInfo> CREATOR;
    field public static final int TV_INPUT_TYPE_COMPONENT = 6; // 0x6
    field public static final int TV_INPUT_TYPE_COMPOSITE = 3; // 0x3
@@ -26641,6 +26645,7 @@ package android.media.tv {
    method public android.media.tv.TvInputHardwareInfo.Builder audioAddress(java.lang.String);
    method public android.media.tv.TvInputHardwareInfo.Builder audioType(int);
    method public android.media.tv.TvInputHardwareInfo build();
    method public android.media.tv.TvInputHardwareInfo.Builder cableConnectionStatus(int);
    method public android.media.tv.TvInputHardwareInfo.Builder deviceId(int);
    method public android.media.tv.TvInputHardwareInfo.Builder hdmiPortId(int);
    method public android.media.tv.TvInputHardwareInfo.Builder type(int);
+54 −0
Original line number Diff line number Diff line
@@ -16,11 +16,15 @@

package android.media.tv;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.media.AudioManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import java.lang.annotation.Retention;

/**
 * Simple container for information about TV input hardware.
@@ -44,6 +48,28 @@ public final class TvInputHardwareInfo implements Parcelable {
    public static final int TV_INPUT_TYPE_HDMI           = 9;
    public static final int TV_INPUT_TYPE_DISPLAY_PORT   = 10;

    /** @hide */
    @Retention(SOURCE)
    @IntDef({CABLE_CONNECTION_STATUS_UNKNOWN, CABLE_CONNECTION_STATUS_CONNECTED,
        CABLE_CONNECTION_STATUS_DISCONNECTED})
    public @interface CableConnectionStatus {}

    // Match hardware/interfaces/tv/input/1.0/types.hal
    /**
     * The hardware is unsure about the connection status or does not support cable detection.
     */
    public static final int CABLE_CONNECTION_STATUS_UNKNOWN = 0;

    /**
     * Cable is connected to the hardware.
     */
    public static final int CABLE_CONNECTION_STATUS_CONNECTED = 1;

    /**
     * Cable is disconnected to the hardware.
     */
    public static final int CABLE_CONNECTION_STATUS_DISCONNECTED = 2;

    public static final Parcelable.Creator<TvInputHardwareInfo> CREATOR =
            new Parcelable.Creator<TvInputHardwareInfo>() {
        @Override
@@ -69,6 +95,8 @@ public final class TvInputHardwareInfo implements Parcelable {
    private int mAudioType;
    private String mAudioAddress;
    private int mHdmiPortId;
    @CableConnectionStatus
    private int mCableConnectionStatus;

    private TvInputHardwareInfo() {
    }
@@ -96,6 +124,19 @@ public final class TvInputHardwareInfo implements Parcelable {
        return mHdmiPortId;
    }

    /**
     * Gets the cable connection status of the hardware.
     *
     * @return {@code CABLE_CONNECTION_STATUS_CONNECTED} if cable is connected.
     *         {@code CABLE_CONNECTION_STATUS_DISCONNECTED} if cable is disconnected.
     *         {@code CABLE_CONNECTION_STATUS_UNKNOWN} if the hardware is unsure about the
     *         connection status or does not support cable detection.
     */
    @CableConnectionStatus
    public int getCableConnectionStatus() {
        return mCableConnectionStatus;
    }

    @Override
    public String toString() {
        StringBuilder b = new StringBuilder(128);
@@ -106,6 +147,7 @@ public final class TvInputHardwareInfo implements Parcelable {
        if (mType == TV_INPUT_TYPE_HDMI) {
            b.append(", hdmi_port=").append(mHdmiPortId);
        }
        b.append(", cable_connection_status=").append(mCableConnectionStatus);
        b.append("}");
        return b.toString();
    }
@@ -125,6 +167,7 @@ public final class TvInputHardwareInfo implements Parcelable {
        if (mType == TV_INPUT_TYPE_HDMI) {
            dest.writeInt(mHdmiPortId);
        }
        dest.writeInt(mCableConnectionStatus);
    }

    public void readFromParcel(Parcel source) {
@@ -135,6 +178,7 @@ public final class TvInputHardwareInfo implements Parcelable {
        if (mType == TV_INPUT_TYPE_HDMI) {
            mHdmiPortId = source.readInt();
        }
        mCableConnectionStatus = source.readInt();
    }

    public static final class Builder {
@@ -143,6 +187,7 @@ public final class TvInputHardwareInfo implements Parcelable {
        private int mAudioType = AudioManager.DEVICE_NONE;
        private String mAudioAddress = "";
        private Integer mHdmiPortId = null;
        private Integer mCableConnectionStatus = CABLE_CONNECTION_STATUS_UNKNOWN;

        public Builder() {
        }
@@ -172,6 +217,14 @@ public final class TvInputHardwareInfo implements Parcelable {
            return this;
        }

        /**
         * Sets cable connection status.
         */
        public Builder cableConnectionStatus(@CableConnectionStatus int cableConnectionStatus) {
            mCableConnectionStatus = cableConnectionStatus;
            return this;
        }

        public TvInputHardwareInfo build() {
            if (mDeviceId == null || mType == null) {
                throw new UnsupportedOperationException();
@@ -191,6 +244,7 @@ public final class TvInputHardwareInfo implements Parcelable {
            if (mHdmiPortId != null) {
                info.mHdmiPortId = mHdmiPortId;
            }
            info.mCableConnectionStatus = mCableConnectionStatus;
            return info;
        }
    }
+4 −4
Original line number Diff line number Diff line
@@ -224,9 +224,8 @@ public final class TvInputManager {
     * {@link TvInputCallback#onInputStateChanged(String, int)}: The input source is connected.
     *
     * <p>This state indicates that a source device is connected to the input port and is in the
     * normal operation mode. It is mostly relevant to hardware inputs such as HDMI input. This is
     * the default state for any hardware inputs where their states are unknown. Non-hardware inputs
     * are considered connected all the time.
     * normal operation mode. It is mostly relevant to hardware inputs such as HDMI input.
     * Non-hardware inputs are considered connected all the time.
     */
    public static final int INPUT_STATE_CONNECTED = 0;

@@ -236,7 +235,8 @@ public final class TvInputManager {
     * in standby mode.
     *
     * <p>This state indicates that a source device is connected to the input port but is in standby
     * mode. It is mostly relevant to hardware inputs such as HDMI input.
     * or low power mode. It is mostly relevant to hardware inputs such as HDMI input and Component
     * inputs.
     */
    public static final int INPUT_STATE_CONNECTED_STANDBY = 1;

+43 −19
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.tv;

import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY;
import static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED;

import android.content.BroadcastReceiver;
@@ -109,7 +110,6 @@ class TvInputHardwareManager implements TvInputHal.Callback {
    private int mCurrentIndex = 0;
    private int mCurrentMaxIndex = 0;

    // TODO: Should handle STANDBY case.
    private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray();
    private final List<Message> mPendingHdmiDeviceEvents = new LinkedList<>();

@@ -209,11 +209,13 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                        + deviceId);
                return;
            }
            int previousConfigsLength = connection.getConfigsLengthLocked();
            connection.updateConfigsLocked(configs);
            String inputId = mHardwareInputIdMap.get(deviceId);
            if (inputId != null) {
            if (inputId != null
                    && (previousConfigsLength == 0) != (connection.getConfigsLengthLocked() == 0)) {
                mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
                        convertConnectedToState(configs.length > 0), 0, inputId).sendToTarget();
                    connection.getInputStateLocked(), 0, inputId).sendToTarget();
            }
            ITvInputHardwareCallback callback = connection.getCallbackLocked();
            if (callback != null) {
@@ -263,14 +265,6 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                || connectionCallingUid != callingUid || connectionResolvedUserId != resolvedUserId;
    }

    private int convertConnectedToState(boolean connected) {
        if (connected) {
            return INPUT_STATE_CONNECTED;
        } else {
            return INPUT_STATE_DISCONNECTED;
        }
    }

    public void addHardwareInput(int deviceId, TvInputInfo info) {
        synchronized (mLock) {
            String oldInputId = mHardwareInputIdMap.get(deviceId);
@@ -293,18 +287,22 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                }
                String inputId = mHardwareInputIdMap.get(hardwareInfo.getDeviceId());
                if (inputId != null && inputId.equals(info.getId())) {
                    mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
                            convertConnectedToState(mHdmiStateMap.valueAt(i)), 0,
                            inputId).sendToTarget();
                    // No HDMI hotplug does not necessarily mean disconnected, as old devices may
                    // not report hotplug state correctly. Using INPUT_STATE_CONNECTED_STANDBY to
                    // denote unknown state.
                    int state = mHdmiStateMap.valueAt(i)
                            ? INPUT_STATE_CONNECTED
                            : INPUT_STATE_CONNECTED_STANDBY;
                    mHandler.obtainMessage(
                        ListenerHandler.STATE_CHANGED, state, 0, inputId).sendToTarget();
                    return;
                }
            }
            // For the rest of the devices, we can tell by the number of available streams.
            // For the rest of the devices, we can tell by the cable connection status.
            Connection connection = mConnections.get(deviceId);
            if (connection != null) {
                mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
                        convertConnectedToState(connection.getConfigsLocked().length > 0), 0,
                        info.getId()).sendToTarget();
                    connection.getInputStateLocked(), 0, info.getId()).sendToTarget();
            }
        }
    }
@@ -716,6 +714,26 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                    + ", mResolvedUserId: " + mResolvedUserId
                    + " }";
        }

        private int getConfigsLengthLocked() {
            return mConfigs == null ? 0 : mConfigs.length;
        }

        private int getInputStateLocked() {
            int configsLength = getConfigsLengthLocked();
            if (configsLength > 0) {
                return INPUT_STATE_CONNECTED;
            }
            switch (mHardwareInfo.getCableConnectionStatus()) {
                case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_CONNECTED:
                    return INPUT_STATE_CONNECTED;
                case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_DISCONNECTED:
                    return INPUT_STATE_DISCONNECTED;
                case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_UNKNOWN:
                default:
                    return INPUT_STATE_CONNECTED_STANDBY;
            }
        }
    }

    private class TvInputHardwareImpl extends ITvInputHardware.Stub {
@@ -1199,8 +1217,14 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                if (inputId == null) {
                    return;
                }
                mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
                        convertConnectedToState(event.isConnected()), 0, inputId).sendToTarget();
                // No HDMI hotplug does not necessarily mean disconnected, as old devices may
                // not report hotplug state correctly. Using INPUT_STATE_CONNECTED_STANDBY to
                // denote unknown state.
                int state = event.isConnected()
                        ? INPUT_STATE_CONNECTED
                        : INPUT_STATE_CONNECTED_STANDBY;
                mHandler.obtainMessage(
                    ListenerHandler.STATE_CHANGED, state, 0, inputId).sendToTarget();
            }
        }
    }
+5 −13
Original line number Diff line number Diff line
@@ -288,7 +288,7 @@ public final class TvInputManagerService extends SystemService {
                    userState.serviceStateMap.put(component, serviceState);
                    updateServiceConnectionLocked(component, userId);
                } else {
                    inputList.addAll(serviceState.hardwareInputList);
                    inputList.addAll(serviceState.hardwareInputMap.values());
                }
            } else {
                try {
@@ -2105,7 +2105,7 @@ public final class TvInputManagerService extends SystemService {
        private final ServiceConnection connection;
        private final ComponentName component;
        private final boolean isHardware;
        private final List<TvInputInfo> hardwareInputList = new ArrayList<>();
        private final Map<String, TvInputInfo> hardwareInputMap = new HashMap<>();

        private ITvInputService service;
        private ServiceCallback callback;
@@ -2216,7 +2216,7 @@ public final class TvInputManagerService extends SystemService {
                }

                if (serviceState.isHardware) {
                    serviceState.hardwareInputList.clear();
                    serviceState.hardwareInputMap.clear();
                    for (TvInputHardwareInfo hardware : mTvInputHardwareManager.getHardwareList()) {
                        try {
                            serviceState.service.notifyHardwareAdded(hardware);
@@ -2283,7 +2283,7 @@ public final class TvInputManagerService extends SystemService {

        private void addHardwareInputLocked(TvInputInfo inputInfo) {
            ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
            serviceState.hardwareInputList.add(inputInfo);
            serviceState.hardwareInputMap.put(inputInfo.getId(), inputInfo);
            buildTvInputListLocked(mUserId, null);
        }

@@ -2309,15 +2309,7 @@ public final class TvInputManagerService extends SystemService {
            ensureHardwarePermission();
            synchronized (mLock) {
                ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
                boolean removed = false;
                for (Iterator<TvInputInfo> it = serviceState.hardwareInputList.iterator();
                        it.hasNext(); ) {
                    if (it.next().getId().equals(inputId)) {
                        it.remove();
                        removed = true;
                        break;
                    }
                }
                boolean removed = serviceState.hardwareInputMap.remove(inputId) != null;
                if (removed) {
                    buildTvInputListLocked(mUserId, null);
                    mTvInputHardwareManager.removeHardwareInput(inputId);
Loading