Loading Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -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 \ Loading core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java +9 −0 Original line number Diff line number Diff line Loading @@ -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. */ Loading core/java/android/hardware/hdmi/IHdmiControlService.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +29 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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; } } Loading @@ -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 Loading services/core/java/com/android/server/hdmi/HdmiControlService.java +60 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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") Loading Loading @@ -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(); Loading Loading @@ -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); Loading Loading
Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -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 \ Loading
core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java +9 −0 Original line number Diff line number Diff line Loading @@ -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. */ Loading
core/java/android/hardware/hdmi/IHdmiControlService.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); }
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +29 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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; } } Loading @@ -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 Loading
services/core/java/com/android/server/hdmi/HdmiControlService.java +60 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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") Loading Loading @@ -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(); Loading Loading @@ -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); Loading