diff options
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/HdmiClient.java | 2 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/HdmiTvClient.java | 145 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/IHdmiControlService.aidl | 3 | ||||
-rw-r--r-- | core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl | 27 | ||||
-rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiControlService.java | 200 |
6 files changed, 259 insertions, 119 deletions
@@ -156,6 +156,7 @@ LOCAL_SRC_FILES += \ 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/IHdmiMhlScratchpadCommandListener.aidl \ core/java/android/hardware/hdmi/IHdmiRecordListener.aidl \ core/java/android/hardware/hdmi/IHdmiSystemAudioModeChangeListener.aidl \ core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl \ diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java index f95ed0f..aba90e4 100644 --- a/core/java/android/hardware/hdmi/HdmiClient.java +++ b/core/java/android/hardware/hdmi/HdmiClient.java @@ -50,7 +50,7 @@ public abstract class HdmiClient { try { mService.sendKeyEvent(getDeviceType(), keyCode, isPressed); } catch (RemoteException e) { - Log.e(TAG, "queryDisplayStatus threw exception ", e); + Log.e(TAG, "sendKeyEvent threw exception ", e); } } diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java index 354c05e..c37fb5b 100644 --- a/core/java/android/hardware/hdmi/HdmiTvClient.java +++ b/core/java/android/hardware/hdmi/HdmiTvClient.java @@ -35,6 +35,11 @@ import libcore.util.EmptyArray; public final class HdmiTvClient extends HdmiClient { private static final String TAG = "HdmiTvClient"; + /** + * Size of MHL scratchpad register. + */ + public static final int SCRATCHPAD_DATA_SIZE = 16; + HdmiTvClient(IHdmiControlService service) { super(service); } @@ -80,6 +85,15 @@ public final class HdmiTvClient extends HdmiClient { } } + private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) { + return new IHdmiControlCallback.Stub() { + @Override + public void onComplete(int result) { + callback.onComplete(result); + } + }; + } + /** * Select a HDMI port to be a new route path. * @@ -126,6 +140,15 @@ public final class HdmiTvClient extends HdmiClient { } } + private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) { + return new IHdmiInputChangeListener.Stub() { + @Override + public void onChanged(HdmiDeviceInfo info) { + listener.onChanged(info); + } + }; + } + /** * Set system audio volume * @@ -170,6 +193,38 @@ public final class HdmiTvClient extends HdmiClient { } } + private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) { + return new IHdmiRecordListener.Stub() { + @Override + public byte[] getOneTouchRecordSource(int recorderAddress) { + HdmiRecordSources.RecordSource source = + callback.getOneTouchRecordSource(recorderAddress); + if (source == null) { + return EmptyArray.BYTE; + } + byte[] data = new byte[source.getDataSize(true)]; + source.toByteArray(true, data, 0); + return data; + } + + @Override + public void onOneTouchRecordResult(int result) { + callback.onOneTouchRecordResult(result); + } + + @Override + public void onTimerRecordingResult(int result) { + callback.onTimerRecordingResult( + HdmiRecordListener.TimerStatusData.parseFrom(result)); + } + + @Override + public void onClearTimerRecordingResult(int result) { + callback.onClearTimerRecordingResult(result); + } + }; + } + /** * Start one touch recording with the given recorder address and recorder source. * <p> @@ -276,53 +331,63 @@ public final class HdmiTvClient extends HdmiClient { } } - private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) { - return new IHdmiControlCallback.Stub() { - @Override - public void onComplete(int result) { - callback.onComplete(result); - } - }; + /** + * Interface used to get incoming MHL scratchpad command. + */ + public interface HdmiMhlScratchpadCommandListener { + void onReceived(int portId, int offset, int length, byte[] data); } - private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) { - return new IHdmiInputChangeListener.Stub() { - @Override - public void onChanged(HdmiDeviceInfo info) { - listener.onChanged(info); - } - }; + /** + * Set {@link HdmiMhlScratchpadCommandListener} to get incoming MHL sSratchpad command. + * + * @param listener to receive incoming MHL Scratchpad command + */ + public void setHdmiMhlScratchpadCommandListener(HdmiMhlScratchpadCommandListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null."); + } + try { + mService.addHdmiMhlScratchpadCommandListener(getListenerWrapper(listener)); + } catch (RemoteException e) { + Log.e(TAG, "failed to set hdmi mhl scratchpad command listener: ", e); + } } - private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) { - return new IHdmiRecordListener.Stub() { + private IHdmiMhlScratchpadCommandListener getListenerWrapper( + final HdmiMhlScratchpadCommandListener listener) { + return new IHdmiMhlScratchpadCommandListener.Stub() { @Override - public byte[] getOneTouchRecordSource(int recorderAddress) { - HdmiRecordSources.RecordSource source = - callback.getOneTouchRecordSource(recorderAddress); - if (source == null) { - return EmptyArray.BYTE; - } - byte[] data = new byte[source.getDataSize(true)]; - source.toByteArray(true, data, 0); - return data; - } - - @Override - public void onOneTouchRecordResult(int result) { - callback.onOneTouchRecordResult(result); + public void onReceived(int portId, int offset, int length, byte[] data) { + listener.onReceived(portId, offset, length, data); } + }; + } - @Override - public void onTimerRecordingResult(int result) { - callback.onTimerRecordingResult( - HdmiRecordListener.TimerStatusData.parseFrom(result)); - } + /** + * Send MHL Scratchpad command to the device connected to a port of the given portId. + * + * @param portId id of port to send MHL Scratchpad command + * @param offset offset in the in given data + * @param length length of data. offset + length should be bound to length of data. + * @param data container for Scratchpad data. It should be 16 bytes. + * @throws IllegalArgumentException if the given parameters are invalid + */ + public void sendScratchpadCommand(int portId, int offset, int length, byte[] data) { + if (data == null || data.length != SCRATCHPAD_DATA_SIZE) { + throw new IllegalArgumentException("Invalid scratchpad data."); + } + if (offset < 0 || offset >= SCRATCHPAD_DATA_SIZE) { + throw new IllegalArgumentException("Invalid offset:" + offset); + } + if (length < 0 || offset + length > SCRATCHPAD_DATA_SIZE) { + throw new IllegalArgumentException("Invalid length:" + length); + } - @Override - public void onClearTimerRecordingResult(int result) { - callback.onClearTimerRecordingResult(result); - } - }; + try { + mService.sendScratchpadCommand(portId, offset, length, data); + } catch (RemoteException e) { + Log.e(TAG, "failed to send scratchpad command: ", e); + } } } diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 17f290b..3bd45ed 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -22,6 +22,7 @@ import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.hdmi.IHdmiDeviceEventListener; import android.hardware.hdmi.IHdmiHotplugEventListener; import android.hardware.hdmi.IHdmiInputChangeListener; +import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener; import android.hardware.hdmi.IHdmiRecordListener; import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; @@ -66,4 +67,6 @@ interface IHdmiControlService { void stopOneTouchRecord(int recorderAddress); void startTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource); void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource); + void sendScratchpadCommand(int portId, int offset, int length, in byte[] data); + void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener); } diff --git a/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl b/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl new file mode 100644 index 0000000..4176597 --- /dev/null +++ b/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.hdmi; + + /** + * Callback interface definition for MHL client to get the scratchpad + * command. + * + * @hide + */ + oneway interface IHdmiMhlScratchpadCommandListener { + void onReceived(int portId, int offset, int length, in byte[] data); + } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 888ceec..fc8d7c3 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -43,6 +43,7 @@ import android.hardware.hdmi.IHdmiControlService; import android.hardware.hdmi.IHdmiDeviceEventListener; import android.hardware.hdmi.IHdmiHotplugEventListener; import android.hardware.hdmi.IHdmiInputChangeListener; +import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener; import android.hardware.hdmi.IHdmiRecordListener; import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; @@ -159,41 +160,30 @@ public final class HdmiControlService extends SystemService { // Type of logical devices hosted in the system. Stored in the unmodifiable list. private final List<Integer> mLocalDevices; - // List of listeners registered by callers that want to get notified of - // hotplug events. - @GuardedBy("mLock") - private final ArrayList<IHdmiHotplugEventListener> mHotplugEventListeners = new ArrayList<>(); - // List of records for hotplug event listener to handle the the caller killed in action. @GuardedBy("mLock") private final ArrayList<HotplugEventListenerRecord> mHotplugEventListenerRecords = new ArrayList<>(); - // List of listeners registered by callers that want to get notified of - // device status events. - @GuardedBy("mLock") - private final ArrayList<IHdmiDeviceEventListener> mDeviceEventListeners = new ArrayList<>(); - - // List of records for device event listener to handle the the caller killed in action. + // List of records for device event listener to handle the caller killed in action. @GuardedBy("mLock") private final ArrayList<DeviceEventListenerRecord> mDeviceEventListenerRecords = new ArrayList<>(); - // List of records for vendor command listener to handle the the caller killed in action. + // List of records for vendor command listener to handle the caller killed in action. @GuardedBy("mLock") private final ArrayList<VendorCommandListenerRecord> mVendorCommandListenerRecords = new ArrayList<>(); + // List of records for MHL Scratchpad command listener to handle the caller killed in action. @GuardedBy("mLock") - private IHdmiInputChangeListener mInputChangeListener; + private final ArrayList<HdmiMhlScratchpadCommandListenerRecord> + mScratchpadCommandListenerRecords = new ArrayList<>(); @GuardedBy("mLock") private InputChangeListenerRecord mInputChangeListenerRecord; @GuardedBy("mLock") - private IHdmiRecordListener mRecordListener; - - @GuardedBy("mLock") private HdmiRecordListenerRecord mRecordListenerRecord; // Set to true while HDMI control is enabled. If set to false, HDMI-CEC/MHL protocol @@ -214,10 +204,6 @@ public final class HdmiControlService extends SystemService { @GuardedBy("mLock") private List<HdmiDeviceInfo> mMhlDevices; - // List of listeners registered by callers that want to get notified of - // system audio mode changes. - private final ArrayList<IHdmiSystemAudioModeChangeListener> - mSystemAudioModeChangeListeners = new ArrayList<>(); // List of records for system audio mode change to handle the the caller killed in action. private final ArrayList<SystemAudioModeChangeListenerRecord> mSystemAudioModeChangeListenerRecords = new ArrayList<>(); @@ -227,6 +213,9 @@ public final class HdmiControlService extends SystemService { private final SettingsObserver mSettingsObserver; + private final HdmiControlBroadcastReceiver + mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver(); + @Nullable private HdmiCecController mCecController; @@ -248,9 +237,6 @@ public final class HdmiControlService extends SystemService { private HdmiCecMessageValidator mMessageValidator; - private final HdmiControlBroadcastReceiver - mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver(); - @ServiceThreadOnly private int mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; @@ -788,8 +774,11 @@ public final class HdmiControlService extends SystemService { } void announceSystemAudioModeChange(boolean enabled) { - for (IHdmiSystemAudioModeChangeListener listener : mSystemAudioModeChangeListeners) { - invokeSystemAudioModeChange(listener, enabled); + synchronized (mLock) { + for (SystemAudioModeChangeListenerRecord record : + mSystemAudioModeChangeListenerRecords) { + invokeSystemAudioModeChangeLocked(record.mListener, enabled); + } } } @@ -914,7 +903,6 @@ public final class HdmiControlService extends SystemService { public void binderDied() { synchronized (mLock) { mHotplugEventListenerRecords.remove(this); - mHotplugEventListeners.remove(mListener); } } } @@ -930,7 +918,6 @@ public final class HdmiControlService extends SystemService { public void binderDied() { synchronized (mLock) { mDeviceEventListenerRecords.remove(this); - mDeviceEventListeners.remove(mListener); } } } @@ -946,7 +933,6 @@ public final class HdmiControlService extends SystemService { public void binderDied() { synchronized (mLock) { mSystemAudioModeChangeListenerRecords.remove(this); - mSystemAudioModeChangeListeners.remove(mListener); } } } @@ -969,14 +955,33 @@ public final class HdmiControlService extends SystemService { } private class HdmiRecordListenerRecord implements IBinder.DeathRecipient { + private final IHdmiRecordListener mListener; + + public HdmiRecordListenerRecord(IHdmiRecordListener listener) { + mListener = listener; + } + @Override public void binderDied() { synchronized (mLock) { - mRecordListener = null; + mRecordListenerRecord = null; } } } + private class HdmiMhlScratchpadCommandListenerRecord implements IBinder.DeathRecipient { + private final IHdmiMhlScratchpadCommandListener mListener; + + public HdmiMhlScratchpadCommandListenerRecord(IHdmiMhlScratchpadCommandListener listener) { + mListener = listener; + } + + @Override + public void binderDied() { + mScratchpadCommandListenerRecords.remove(this); + } + } + private void enforceAccessPermission() { getContext().enforceCallingOrSelfPermission(PERMISSION, TAG); } @@ -1120,34 +1125,19 @@ public final class HdmiControlService extends SystemService { @Override public void addHotplugEventListener(final IHdmiHotplugEventListener listener) { enforceAccessPermission(); - runOnServiceThread(new Runnable() { - @Override - public void run() { - HdmiControlService.this.addHotplugEventListener(listener); - } - }); + HdmiControlService.this.addHotplugEventListener(listener); } @Override public void removeHotplugEventListener(final IHdmiHotplugEventListener listener) { enforceAccessPermission(); - runOnServiceThread(new Runnable() { - @Override - public void run() { - HdmiControlService.this.removeHotplugEventListener(listener); - } - }); + HdmiControlService.this.removeHotplugEventListener(listener); } @Override public void addDeviceEventListener(final IHdmiDeviceEventListener listener) { enforceAccessPermission(); - runOnServiceThread(new Runnable() { - @Override - public void run() { - HdmiControlService.this.addDeviceEventListener(listener); - } - }); + HdmiControlService.this.addDeviceEventListener(listener); } @Override @@ -1288,12 +1278,7 @@ public final class HdmiControlService extends SystemService { public void addVendorCommandListener(final IHdmiVendorCommandListener listener, final int deviceType) { enforceAccessPermission(); - runOnServiceThread(new Runnable() { - @Override - public void run() { - HdmiControlService.this.addVendorCommandListener(listener, deviceType); - } - }); + HdmiControlService.this.addVendorCommandListener(listener, deviceType); } @Override @@ -1382,6 +1367,38 @@ public final class HdmiControlService extends SystemService { } }); } + + @Override + public void sendScratchpadCommand(final int portId, final int offset, final int length, + final byte[] data) { + enforceAccessPermission(); + runOnServiceThread(new Runnable() { + @Override + public void run() { + if (mMhlController == null) { + Slog.w(TAG, "No Mhl controller available."); + return; + } + if (!isControlEnabled()) { + Slog.w(TAG, "Hdmi control is disabled."); + return ; + } + HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId); + if (device == null) { + Slog.w(TAG, "Invalid port id:" + portId); + return; + } + mMhlController.sendScratchpadCommand(portId, offset, length, data); + } + }); + } + + @Override + public void addHdmiMhlScratchpadCommandListener( + IHdmiMhlScratchpadCommandListener listener) { + enforceAccessPermission(); + HdmiControlService.this.addHdmiMhlScratchpadCommandListener(listener); + } } @ServiceThreadOnly @@ -1418,7 +1435,6 @@ public final class HdmiControlService extends SystemService { } synchronized (mLock) { mHotplugEventListenerRecords.add(record); - mHotplugEventListeners.add(listener); } } @@ -1431,7 +1447,6 @@ public final class HdmiControlService extends SystemService { break; } } - mHotplugEventListeners.remove(listener); } } @@ -1444,16 +1459,15 @@ public final class HdmiControlService extends SystemService { return; } synchronized (mLock) { - mDeviceEventListeners.add(listener); mDeviceEventListenerRecords.add(record); } } void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) { synchronized (mLock) { - for (IHdmiDeviceEventListener listener : mDeviceEventListeners) { + for (DeviceEventListenerRecord record : mDeviceEventListenerRecords) { try { - listener.onStatusChanged(device, status); + record.mListener.onStatusChanged(device, status); } catch (RemoteException e) { Slog.e(TAG, "Failed to report device event:" + e); } @@ -1471,7 +1485,6 @@ public final class HdmiControlService extends SystemService { return; } synchronized (mLock) { - mSystemAudioModeChangeListeners.add(listener); mSystemAudioModeChangeListenerRecords.add(record); } } @@ -1486,37 +1499,41 @@ public final class HdmiControlService extends SystemService { break; } } - mSystemAudioModeChangeListeners.remove(listener); } } private final class InputChangeListenerRecord implements IBinder.DeathRecipient { + private final IHdmiInputChangeListener mListener; + + public InputChangeListenerRecord(IHdmiInputChangeListener listener) { + mListener = listener; + } + @Override public void binderDied() { synchronized (mLock) { - mInputChangeListener = null; + mInputChangeListenerRecord = null; } } } private void setInputChangeListener(IHdmiInputChangeListener listener) { synchronized (mLock) { - mInputChangeListenerRecord = new InputChangeListenerRecord(); + mInputChangeListenerRecord = new InputChangeListenerRecord(listener); try { listener.asBinder().linkToDeath(mInputChangeListenerRecord, 0); } catch (RemoteException e) { Slog.w(TAG, "Listener already died"); return; } - mInputChangeListener = listener; } } void invokeInputChangeListener(HdmiDeviceInfo info) { synchronized (mLock) { - if (mInputChangeListener != null) { + if (mInputChangeListenerRecord != null) { try { - mInputChangeListener.onChanged(info); + mInputChangeListenerRecord.mListener.onChanged(info); } catch (RemoteException e) { Slog.w(TAG, "Exception thrown by IHdmiInputChangeListener: " + e); } @@ -1526,21 +1543,20 @@ public final class HdmiControlService extends SystemService { private void setHdmiRecordListener(IHdmiRecordListener listener) { synchronized (mLock) { - mRecordListenerRecord = new HdmiRecordListenerRecord(); + mRecordListenerRecord = new HdmiRecordListenerRecord(listener); try { listener.asBinder().linkToDeath(mRecordListenerRecord, 0); } catch (RemoteException e) { Slog.w(TAG, "Listener already died.", e); } - mRecordListener = listener; } } byte[] invokeRecordRequestListener(int recorderAddress) { synchronized (mLock) { - if (mRecordListener != null) { + if (mRecordListenerRecord != null) { try { - return mRecordListener.getOneTouchRecordSource(recorderAddress); + return mRecordListenerRecord.mListener.getOneTouchRecordSource(recorderAddress); } catch (RemoteException e) { Slog.w(TAG, "Failed to start record.", e); } @@ -1551,9 +1567,9 @@ public final class HdmiControlService extends SystemService { void invokeOneTouchRecordResult(int result) { synchronized (mLock) { - if (mRecordListener != null) { + if (mRecordListenerRecord != null) { try { - mRecordListener.onOneTouchRecordResult(result); + mRecordListenerRecord.mListener.onOneTouchRecordResult(result); } catch (RemoteException e) { Slog.w(TAG, "Failed to call onOneTouchRecordResult.", e); } @@ -1563,9 +1579,9 @@ public final class HdmiControlService extends SystemService { void invokeTimerRecordingResult(int result) { synchronized (mLock) { - if (mRecordListener != null) { + if (mRecordListenerRecord != null) { try { - mRecordListener.onTimerRecordingResult(result); + mRecordListenerRecord.mListener.onTimerRecordingResult(result); } catch (RemoteException e) { Slog.w(TAG, "Failed to call onTimerRecordingResult.", e); } @@ -1575,9 +1591,9 @@ public final class HdmiControlService extends SystemService { void invokeClearTimerRecordingResult(int result) { synchronized (mLock) { - if (mRecordListener != null) { + if (mRecordListenerRecord != null) { try { - mRecordListener.onClearTimerRecordingResult(result); + mRecordListenerRecord.mListener.onClearTimerRecordingResult(result); } catch (RemoteException e) { Slog.w(TAG, "Failed to call onClearTimerRecordingResult.", e); } @@ -1593,7 +1609,7 @@ public final class HdmiControlService extends SystemService { } } - private void invokeSystemAudioModeChange(IHdmiSystemAudioModeChangeListener listener, + private void invokeSystemAudioModeChangeLocked(IHdmiSystemAudioModeChangeListener listener, boolean enabled) { try { listener.onStatusChanged(enabled); @@ -1605,8 +1621,8 @@ public final class HdmiControlService extends SystemService { private void announceHotplugEvent(int portId, boolean connected) { HdmiHotplugEvent event = new HdmiHotplugEvent(portId, connected); synchronized (mLock) { - for (IHdmiHotplugEventListener listener : mHotplugEventListeners) { - invokeHotplugEventListenerLocked(listener, event); + for (HotplugEventListenerRecord record : mHotplugEventListenerRecords) { + invokeHotplugEventListenerLocked(record.mListener, event); } } } @@ -1805,6 +1821,34 @@ public final class HdmiControlService extends SystemService { } } + private void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener) { + HdmiMhlScratchpadCommandListenerRecord record = + new HdmiMhlScratchpadCommandListenerRecord(listener); + try { + listener.asBinder().linkToDeath(record, 0); + } catch (RemoteException e) { + Slog.w(TAG, "Listener already died."); + return; + } + + synchronized (mLock) { + mScratchpadCommandListenerRecords.add(record); + } + } + + void invokeScratchpadCommandListeners(int portId, int offest, int length, byte[] data) { + synchronized (mLock) { + for (HdmiMhlScratchpadCommandListenerRecord record : + mScratchpadCommandListenerRecords) { + try { + record.mListener.onReceived(portId, offest, length, data); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to notify scratchpad command", e); + } + } + } + } + boolean isProhibitMode() { synchronized (mLock) { return mProhibitMode; |