diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java index 9a9e945a91cf9..16adee9907ed1 100644 --- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java +++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java @@ -294,6 +294,16 @@ public final class HdmiControlServiceWrapper { HdmiControlServiceWrapper.this.removeHdmiCecVolumeControlFeatureListener(listener); } + @Override + public int getMessageHistorySize() { + return HdmiControlServiceWrapper.this.getMessageHistorySize(); + } + + @Override + public boolean setMessageHistorySize(int newSize) { + return HdmiControlServiceWrapper.this.setMessageHistorySize(newSize); + } + @Override public void addCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener) { @@ -522,6 +532,16 @@ public final class HdmiControlServiceWrapper { public void removeHdmiCecVolumeControlFeatureListener( IHdmiCecVolumeControlFeatureListener listener) {} + /** @hide */ + public int getMessageHistorySize() { + return 0; + } + + /** @hide */ + public boolean setMessageHistorySize(int newSize) { + return true; + } + /** @hide */ public void addCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener) {} diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 7f0e53ea2e680..6613397c8c0f8 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -88,6 +88,8 @@ interface IHdmiControlService { void setStandbyMode(boolean isStandbyModeOn); void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute); void setSystemAudioModeOnForAudioOnlySource(); + boolean setMessageHistorySize(int newSize); + int getMessageHistorySize(); void addCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener); void removeCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener); List getUserCecSettings(); diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java index 597ea14df56d4..f04a9f7358810 100644 --- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java +++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java @@ -375,6 +375,17 @@ public class HdmiAudioSystemClientTest { IHdmiCecVolumeControlFeatureListener listener) { } + @Override + public int getMessageHistorySize() { + return 0; + } + + @Override + public boolean setMessageHistorySize(int newSize) { + return true; + } + + @Override public List getUserCecSettings() { return new ArrayList<>(); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java index 05e764b927977..6736d2a227dda 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecController.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java @@ -90,7 +90,7 @@ final class HdmiCecController { private static final int MAX_DEDICATED_ADDRESS = 11; - private static final int MAX_HDMI_MESSAGE_HISTORY = 250; + private static final int INITIAL_HDMI_MESSAGE_HISTORY_SIZE = 250; private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF; @@ -138,8 +138,10 @@ final class HdmiCecController { private final HdmiControlService mService; // Stores recent CEC messages and HDMI Hotplug event history for debugging purpose. - private final ArrayBlockingQueue mMessageHistory = - new ArrayBlockingQueue<>(MAX_HDMI_MESSAGE_HISTORY); + private ArrayBlockingQueue mMessageHistory = + new ArrayBlockingQueue<>(INITIAL_HDMI_MESSAGE_HISTORY_SIZE); + + private final Object mMessageHistoryLock = new Object(); private final NativeWrapper mNativeWrapperImpl; @@ -750,12 +752,39 @@ final class HdmiCecController { } private void addEventToHistory(Dumpable event) { - if (!mMessageHistory.offer(event)) { - mMessageHistory.poll(); - mMessageHistory.offer(event); + synchronized (mMessageHistoryLock) { + if (!mMessageHistory.offer(event)) { + mMessageHistory.poll(); + mMessageHistory.offer(event); + } } } + int getMessageHistorySize() { + synchronized (mMessageHistoryLock) { + return mMessageHistory.size() + mMessageHistory.remainingCapacity(); + } + } + + boolean setMessageHistorySize(int newSize) { + if (newSize < INITIAL_HDMI_MESSAGE_HISTORY_SIZE) { + return false; + } + ArrayBlockingQueue newMessageHistory = new ArrayBlockingQueue<>(newSize); + + synchronized (mMessageHistoryLock) { + if (newSize < mMessageHistory.size()) { + for (int i = 0; i < mMessageHistory.size() - newSize; i++) { + mMessageHistory.poll(); + } + } + + newMessageHistory.addAll(mMessageHistory); + mMessageHistory = newMessageHistory; + } + return true; + } + void dump(final IndentingPrintWriter pw) { pw.println("CEC message history:"); pw.increaseIndent(); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 69270949b1935..6920c4b9ff4c0 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -2365,6 +2365,25 @@ public class HdmiControlService extends SystemService { } } + @Override + public boolean setMessageHistorySize(int newSize) { + enforceAccessPermission(); + if (mCecController == null) { + return false; + } + return mCecController.setMessageHistorySize(newSize); + } + + @Override + public int getMessageHistorySize() { + enforceAccessPermission(); + if (mCecController != null) { + return mCecController.getMessageHistorySize(); + } else { + return 0; + } + } + @Override public void addCecSettingChangeListener(String name, final IHdmiCecSettingChangeListener listener) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java index a9b52140a6db2..8949427634229 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java @@ -95,6 +95,11 @@ final class HdmiControlShellCommand extends ShellCommand { pw.println(" deviceselect "); pw.println(" Switch to device with given id"); pw.println(" The device's id is represented by its logical address."); + pw.println(" history_size get"); + pw.println(" Gets the number of messages that can be stored in dumpsys history"); + pw.println(" history_size set "); + pw.println(" Changes the number of messages that can be stored in dumpsys history to" + + " new_size"); } private int handleShellCommand(String cmd) throws RemoteException { @@ -115,6 +120,8 @@ final class HdmiControlShellCommand extends ShellCommand { return setArcMode(pw); case "deviceselect": return deviceSelect(pw); + case "history_size": + return historySize(pw); } getErrPrintWriter().println("Unhandled command: " + cmd); @@ -275,6 +282,41 @@ final class HdmiControlShellCommand extends ShellCommand { return 0; } + private int historySize(PrintWriter pw) throws RemoteException { + if (1 > getRemainingArgsCount()) { + throw new IllegalArgumentException("Use 'set' or 'get' for the command action"); + } + + String operation = getNextArgRequired(); + switch (operation) { + case "get": { + int value = mBinderService.getMessageHistorySize(); + pw.println("CEC dumpsys message history size = " + value); + return 0; + } + case "set": { + String arg = getNextArgRequired(); + int value; + try { + value = Integer.parseInt(arg); + } catch (NumberFormatException nfe) { + pw.println("Cannot set CEC dumpsys message history size to " + arg); + return 1; + } + if (mBinderService.setMessageHistorySize(value)) { + pw.println("Setting CEC dumpsys message history size to " + value); + } else { + pw.println( + "Message history size not changed, was it lower than the minimum " + + "size?"); + } + return 0; + } + default: + throw new IllegalArgumentException("Unknown operation: " + operation); + } + } + private boolean receiveCallback(String command) { try { if (!mLatch.await(HdmiConfig.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {