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

Commit 9c37e1f5 authored by Jinsuk Kim's avatar Jinsuk Kim
Browse files

Implement some apis for TV Input Framework and HdmiControlService

- setInputChangeListener()
- getInputDevices()

Change-Id: I6f7d6d9c7094018e2b6b5ba37f63c8ee5df00e37
parent c769c1c8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ LOCAL_SRC_FILES += \
	core/java/android/hardware/hdmi/IHdmiControlService.aidl \
	core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl \
	core/java/android/hardware/hdmi/IHdmiHotplugEventListener.aidl \
	core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl \
	core/java/android/hardware/hdmi/IHdmiSystemAudioModeChangeListener.aidl \
	core/java/android/hardware/input/IInputManager.aidl \
	core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
+9 −0
Original line number Diff line number Diff line
@@ -104,6 +104,15 @@ public final class HdmiCecDeviceInfo implements Parcelable {
        return mDeviceType;
    }

    /**
     * Return {@code true} if the device is of a type that can be an input source.
     */
    public boolean isSourceType() {
        return mDeviceType == HdmiCec.DEVICE_PLAYBACK
                || mDeviceType == HdmiCec.DEVICE_RECORDER
                || mDeviceType == HdmiCec.DEVICE_TUNER;
    }

    /**
     * Return display (OSD) name of the device.
     */
+3 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;

import java.util.List;
@@ -53,4 +54,6 @@ interface IHdmiControlService {
    void setOption(int option, int value);
    oneway void setSystemAudioVolume(int oldIndex, int newIndex, int maxIndex);
    oneway void setSystemAudioMute(boolean mute);
    void setInputChangeListener(IHdmiInputChangeListener listener);
    List<HdmiCecDeviceInfo> getInputDevices();
}
+29 −13
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.hardware.hdmi.HdmiCecMessage;
import android.hardware.hdmi.IHdmiControlCallback;
import android.media.AudioSystem;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.util.SparseArray;
@@ -69,9 +70,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    // Copy of mDeviceInfos to guarantee thread-safety.
    @GuardedBy("mLock")
    private List<HdmiCecDeviceInfo> mSafeAllDeviceInfos = Collections.emptyList();
    // All external cec device which excludes local devices.
    // All external cec input(source) devices. Does not include system audio device.
    @GuardedBy("mLock")
    private List<HdmiCecDeviceInfo> mSafeExternalDeviceInfos = Collections.emptyList();
    private List<HdmiCecDeviceInfo> mSafeExternalInputs = Collections.emptyList();

    // Map-like container of all cec devices including local ones.
    // A logical address of device is used as key of container.
@@ -186,6 +187,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
        setPrevPortId(portId);
        // TODO: Actually switch the physical port here. Handle PAP/PIP as well.
        //       Show OSD port change banner
        mService.invokeInputChangeListener(getActiveSource());
    }

    @ServiceThreadOnly
@@ -807,17 +809,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    }

    /**
     * Return a list of  {@link HdmiCecDeviceInfo}.
     *
     * @param includeLocalDevice whether to include local device in result.
     * Return external input devices.
     */
    List<HdmiCecDeviceInfo> getSafeDeviceInfoList(boolean includeLocalDevice) {
    List<HdmiCecDeviceInfo> getSafeExternalInputs() {
        synchronized (mLock) {
            if (includeLocalDevice) {
                return mSafeAllDeviceInfos;
            } else {
                return mSafeExternalDeviceInfos;
            }
            return mSafeExternalInputs;
        }
    }

@@ -825,11 +821,31 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    private void updateSafeDeviceInfoList() {
        assertRunOnServiceThread();
        List<HdmiCecDeviceInfo> copiedDevices = HdmiUtils.sparseArrayToList(mDeviceInfos);
        List<HdmiCecDeviceInfo> externalDeviceInfos = getDeviceInfoList(false);
        List<HdmiCecDeviceInfo> externalInputs = getInputDevices();
        synchronized (mLock) {
            mSafeAllDeviceInfos = copiedDevices;
            mSafeExternalDeviceInfos = externalDeviceInfos;
            mSafeExternalInputs = externalInputs;
        }
    }

    /**
     * Return a list of external cec input (source) devices.
     *
     * <p>Note that this effectively excludes non-source devices like system audio,
     * secondary TV.
     */
    private List<HdmiCecDeviceInfo> getInputDevices() {
        ArrayList<HdmiCecDeviceInfo> infoList = new ArrayList<>();
        for (int i = 0; i < mDeviceInfos.size(); ++i) {
            HdmiCecDeviceInfo info = mDeviceInfos.valueAt(i);
            if (isLocalDeviceAddress(i)) {
                continue;
            }
            if (info.isSourceType()) {
                infoList.add(info);
            }
        }
        return infoList;
    }

    @ServiceThreadOnly
+60 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.hdmi.IHdmiControlService;
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
import android.media.AudioManager;
import android.os.Build;
@@ -139,6 +140,12 @@ public final class HdmiControlService extends SystemService {
    private final ArrayList<DeviceEventListenerRecord> mDeviceEventListenerRecords =
            new ArrayList<>();

    @GuardedBy("mLock")
    private IHdmiInputChangeListener mInputChangeListener;

    @GuardedBy("mLock")
    private InputChangeListenerRecord mInputChangeListenerRecord;

    // Set to true while HDMI control is enabled. If set to false, HDMI-CEC/MHL protocol
    // handling will be disabled and no request will be handled.
    @GuardedBy("mLock")
@@ -772,6 +779,24 @@ public final class HdmiControlService extends SystemService {
            HdmiControlService.this.removeSystemAudioModeChangeListener(listener);
        }

        @Override
        public void setInputChangeListener(final IHdmiInputChangeListener listener) {
            enforceAccessPermission();
            HdmiControlService.this.setInputChangeListener(listener);
        }

        @Override
        public List<HdmiCecDeviceInfo> getInputDevices() {
            enforceAccessPermission();
            // No need to hold the lock for obtaining TV device as the local device instance
            // is preserved while the HDMI control is enabled.
            HdmiCecLocalDeviceTv tv = tv();
            if (tv == null) {
                return Collections.emptyList();
            }
            return tv.getSafeExternalInputs();
        }

        @Override
        public void setControlEnabled(final boolean enabled) {
            enforceAccessPermission();
@@ -981,6 +1006,41 @@ public final class HdmiControlService extends SystemService {
        }
    }

    private final class InputChangeListenerRecord implements IBinder.DeathRecipient {
        @Override
        public void binderDied() {
            synchronized (mLock) {
                mInputChangeListener = null;
            }
        }
    }

    private void setInputChangeListener(IHdmiInputChangeListener listener) {
        synchronized (mLock) {
            mInputChangeListenerRecord = new InputChangeListenerRecord();
            try {
                listener.asBinder().linkToDeath(mInputChangeListenerRecord, 0);
            } catch (RemoteException e) {
                Slog.w(TAG, "Listener already died");
                return;
            }
            mInputChangeListener = listener;
        }
    }

    void invokeInputChangeListener(int activeAddress) {
        synchronized (mLock) {
            if (mInputChangeListener != null) {
                HdmiCecDeviceInfo activeSource = getDeviceInfo(activeAddress);
                try {
                    mInputChangeListener.onChanged(activeSource);
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception thrown by IHdmiInputChangeListener: " + e);
                }
            }
        }
    }

    private void invokeCallback(IHdmiControlCallback callback, int result) {
        try {
            callback.onComplete(result);