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

Commit ea1e84b8 authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Android (Google) Code Review
Browse files

Merge "Implement some apis for TV Input Framework and HdmiControlService"

parents 517cc7f9 9c37e1f5
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);