From 79db52fbc634632a02f03511a72842660fc7a43c Mon Sep 17 00:00:00 2001 From: Amy Date: Tue, 23 Oct 2018 12:45:17 -0700 Subject: [PATCH 1/5] Complete the HDMI_SYSTEM_AUDIO_CONTROL_ENABLED control logic in Audio System device. ag/5338944 Note that we should init system audio mode again when this property is turned back on. Test: local tested. Bug: 118275908 Change-Id: I120801fdacedaea74d311064e6bf66d30992c8ba --- .../hdmi/HdmiCecLocalDeviceAudioSystem.java | 22 +++++++++++++------ .../server/hdmi/HdmiControlService.java | 3 +++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index cd0653f164e96..6ac8b54b4f10b 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -89,12 +89,10 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { protected HdmiCecLocalDeviceAudioSystem(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mSystemAudioControlFeatureEnabled = true; - // TODO(amyjojo) make System Audio Control controllable by users - /*mSystemAudioControlFeatureEnabled = - mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true);*/ mRoutingControlFeatureEnabled = mService.readBooleanSetting(Global.HDMI_CEC_SWITCH_ENABLED, true); + mSystemAudioControlFeatureEnabled = + mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true); // TODO(amyjojo): make the map ro property. mTvInputs.put(Constants.CEC_SWITCH_HDMI1, "com.droidlogic.tvinput/.services.Hdmi1InputService/HW5"); @@ -275,7 +273,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { int systemAudioOnPowerOnProp, boolean lastSystemAudioControlStatus) { if ((systemAudioOnPowerOnProp == ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON) || ((systemAudioOnPowerOnProp == USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON) - && lastSystemAudioControlStatus)) { + && lastSystemAudioControlStatus && isSystemAudioControlFeatureEnabled())) { addAndStartAction(new SystemAudioInitiationActionFromAvr(this)); } } @@ -408,8 +406,11 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { @ServiceThreadOnly protected boolean handleGiveAudioStatus(HdmiCecMessage message) { assertRunOnServiceThread(); - - reportAudioStatus(message.getSource()); + if (isSystemAudioControlFeatureEnabled()) { + reportAudioStatus(message.getSource()); + } else { + mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED); + } return true; } @@ -776,6 +777,13 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { HdmiLogger.debug("[A]UpdateSystemAudio mode[on=%b] output=[%X]", on, device); } + void onSystemAduioControlFeatureSupportChanged(boolean enabled) { + setSystemAudioControlFeatureEnabled(enabled); + if (enabled) { + addAndStartAction(new SystemAudioInitiationActionFromAvr(this)); + } + } + @ServiceThreadOnly void setSystemAudioControlFeatureEnabled(boolean enabled) { assertRunOnServiceThread(); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index fcfb0664ea957..c291c1cde0348 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -610,6 +610,9 @@ public class HdmiControlService extends SystemService { if (isTvDeviceEnabled()) { tv().setSystemAudioControlFeatureEnabled(enabled); } + if (isAudioSystemDevice()) { + audioSystem().onSystemAduioControlFeatureSupportChanged(enabled); + } break; case Global.HDMI_CEC_SWITCH_ENABLED: if (isAudioSystemDevice()) { From b9e48e2ff86c26711eb57a850d4080079967feba Mon Sep 17 00:00:00 2001 From: Nick Chalko Date: Tue, 23 Oct 2018 06:59:39 -0700 Subject: [PATCH 2/5] Improve CEC logging ag/5338580 Include details for HdmiCecLocalDeviceAudioSystem Increase the number of CEC messages kept dump history from 20 to 200. Many CEC devices are chatty. This increase the memory used for CEC message history from about 600 bytes to a max of 6K bytes. Bug:117991662 Change-Id: Ib21162d7c166b927db1e6fd0e51de87c13e538f9 Test: m -j; flashall; adb shell dumpsys hdmi_control --- .../server/hdmi/HdmiCecController.java | 4 +- .../hdmi/HdmiCecLocalDeviceAudioSystem.java | 17 +++++ .../server/hdmi/HdmiControlService.java | 27 +++---- .../com/android/server/hdmi/HdmiUtils.java | 74 +++++++++++++++++++ 4 files changed, 107 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java index e777ce8166acf..86be585e5d23f 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecController.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java @@ -77,7 +77,7 @@ final class HdmiCecController { private static final int NUM_LOGICAL_ADDRESS = 16; - private static final int MAX_CEC_MESSAGE_HISTORY = 20; + private static final int MAX_CEC_MESSAGE_HISTORY = 200; // Predicate for whether the given logical address is remote device's one or not. private final Predicate mRemoteDeviceAddressPredicate = new Predicate() { @@ -682,7 +682,7 @@ final class HdmiCecController { void dump(final IndentingPrintWriter pw) { for (int i = 0; i < mLocalDevices.size(); ++i) { - pw.println("HdmiCecLocalDevice #" + i + ":"); + pw.println("HdmiCecLocalDevice #" + mLocalDevices.keyAt(i) + ":"); pw.increaseIndent(); mLocalDevices.valueAt(i).dump(pw); pw.decreaseIndent(); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 6ac8b54b4f10b..5c1b3deb99556 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -37,6 +37,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.Constants.AudioCodec; import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; @@ -1086,4 +1087,20 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } mDeviceInfos.clear(); } + + @Override + protected void dump(IndentingPrintWriter pw) { + pw.println("HdmiCecLocalDeviceAudioSystem:"); + pw.increaseIndent(); + pw.println("mSystemAudioActivated: " + mSystemAudioActivated); + pw.println("mSystemAudioControlFeatureEnabled: " + mSystemAudioControlFeatureEnabled); + pw.println("mTvSystemAudioModeSupport: " + mTvSystemAudioModeSupport); + pw.println("mArcEstablished: " + mArcEstablished); + pw.println("mArcIntentUsed: " + mArcIntentUsed); + HdmiUtils.dumpMap(pw, "mTvInputs:", mTvInputs); + HdmiUtils.dumpSparseArray(pw, "mDeviceInfos:", mDeviceInfos); + pw.decreaseIndent(); + super.dump(pw); + } + } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index c291c1cde0348..343a7ab0e9451 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -1890,27 +1890,28 @@ public class HdmiControlService extends SystemService { if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) return; final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); - pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled); pw.println("mProhibitMode: " + mProhibitMode); - if (mCecController != null) { - pw.println("mCecController: "); - pw.increaseIndent(); - mCecController.dump(pw); - pw.decreaseIndent(); - } + pw.println("mPowerStatus: " + mPowerStatus); + + // System settings + pw.println("System_settings:"); + pw.increaseIndent(); + pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled); + pw.println("mMhlInputChangeEnabled: " + mMhlInputChangeEnabled); + pw.decreaseIndent(); pw.println("mMhlController: "); pw.increaseIndent(); mMhlController.dump(pw); pw.decreaseIndent(); - pw.println("mPortInfo: "); - pw.increaseIndent(); - for (HdmiPortInfo hdmiPortInfo : mPortInfo) { - pw.println("- " + hdmiPortInfo); + HdmiUtils.dumpIterable(pw, "mPortInfo:", mPortInfo); + if (mCecController != null) { + pw.println("mCecController: "); + pw.increaseIndent(); + mCecController.dump(pw); + pw.decreaseIndent(); } - pw.decreaseIndent(); - pw.println("mPowerStatus: " + mPowerStatus); } } diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java index 2a8117fac68da..21106828d43f6 100644 --- a/services/core/java/com/android/server/hdmi/HdmiUtils.java +++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java @@ -20,9 +20,13 @@ import android.hardware.hdmi.HdmiDeviceInfo; import android.util.Slog; import android.util.SparseArray; +import com.android.internal.util.IndentingPrintWriter; + import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; + /** * Various utilities to handle HDMI CEC messages. @@ -317,4 +321,74 @@ final class HdmiUtils { info.getPhysicalAddress(), info.getPortId(), info.getDeviceType(), info.getVendorId(), info.getDisplayName(), newPowerStatus); } + + /** + * Dump a {@link SparseArray} to the print writer. + * + *

The dump is formatted: + *

+     *     name:
+     *        key = value
+     *        key = value
+     *        ...
+     * 
+ */ + static void dumpSparseArray(IndentingPrintWriter pw, String name, + SparseArray sparseArray) { + printWithTrailingColon(pw, name); + pw.increaseIndent(); + int size = sparseArray.size(); + for (int i = 0; i < size; i++) { + int key = sparseArray.keyAt(i); + T value = sparseArray.get(key); + pw.printPair(Integer.toString(key), value); + pw.println(); + } + pw.decreaseIndent(); + } + + private static void printWithTrailingColon(IndentingPrintWriter pw, String name) { + pw.println(name.endsWith(":") ? name : name.concat(":")); + } + + /** + * Dump a {@link Map} to the print writer. + * + *

The dump is formatted: + *

+     *     name:
+     *        key = value
+     *        key = value
+     *        ...
+     * 
+ */ + static void dumpMap(IndentingPrintWriter pw, String name, Map map) { + printWithTrailingColon(pw, name); + pw.increaseIndent(); + for (Map.Entry entry: map.entrySet()) { + pw.printPair(entry.getKey().toString(), entry.getValue()); + pw.println(); + } + pw.decreaseIndent(); + } + + /** + * Dump a {@link Map} to the print writer. + * + *

The dump is formatted: + *

+     *     name:
+     *        value
+     *        value
+     *        ...
+     * 
+ */ + static void dumpIterable(IndentingPrintWriter pw, String name, Iterable values) { + printWithTrailingColon(pw, name); + pw.increaseIndent(); + for (T value : values) { + pw.println(value); + } + pw.decreaseIndent(); + } } From 476e546b9eeac4721c0d8d54c8a65feda3a40083 Mon Sep 17 00:00:00 2001 From: Nick Chalko Date: Tue, 23 Oct 2018 13:36:04 -0700 Subject: [PATCH 3/5] Use : hex format for HdmiCecMessage.toString ag/5340977 This format is used by both cec-client and www.cec-o-matic.com Bug:117991662 Test: m -j; flashall; adb shell dumpsys hdmi_control Change-Id: Icaf172a54eb776ca848d16f5e8384f17ae236207 --- .../core/java/com/android/server/hdmi/HdmiCecMessage.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java index 4052c8a87c4e4..f8b39627f2360 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java @@ -112,12 +112,11 @@ public final class HdmiCecMessage { @Override public String toString() { StringBuffer s = new StringBuffer(); - s.append(String.format("<%s> src: %d, dst: %d", - opcodeToString(mOpcode), mSource, mDestination)); + s.append(String.format("<%s> %X%X:%02X", + opcodeToString(mOpcode), mSource, mDestination, mOpcode)); if (mParams.length > 0) { - s.append(", params:"); for (byte data : mParams) { - s.append(String.format(" %02X", data)); + s.append(String.format(":%02X", data)); } } return s.toString(); From 3288f8af6065c1f0ed94062bbb28de37d5f32743 Mon Sep 17 00:00:00 2001 From: Amy Date: Tue, 23 Oct 2018 18:55:34 -0700 Subject: [PATCH 4/5] When device reboots, it should not go to real standby. ag/5340093 This means the device should not do onStandby in HdmiControlService so that it does not disable device or send out Inactive Source or turn off system audio mode, etc. Test: local tested. Bug: 117106186, 116125794 Change-Id: I454a6d2266a35a223dd5d32338799d39e1e83ef7 --- .../java/com/android/server/hdmi/HdmiControlService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 343a7ab0e9451..aabe1ad659d6a 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -26,6 +26,7 @@ import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE; import static com.android.server.hdmi.Constants.OPTION_MHL_INPUT_SWITCHING; import static com.android.server.hdmi.Constants.OPTION_MHL_POWER_CHARGE; import static com.android.server.hdmi.Constants.OPTION_MHL_SERVICE_CONTROL; +import static com.android.server.power.ShutdownThread.SHUTDOWN_ACTION_PROPERTY; import android.annotation.Nullable; import android.content.BroadcastReceiver; @@ -184,9 +185,10 @@ public class HdmiControlService extends SystemService { @Override public void onReceive(Context context, Intent intent) { assertRunOnServiceThread(); + boolean isReboot = SystemProperties.get(SHUTDOWN_ACTION_PROPERTY).contains("1"); switch (intent.getAction()) { case Intent.ACTION_SCREEN_OFF: - if (isPowerOnOrTransient()) { + if (isPowerOnOrTransient() && !isReboot) { onStandby(STANDBY_SCREEN_OFF); } break; @@ -202,7 +204,7 @@ public class HdmiControlService extends SystemService { } break; case Intent.ACTION_SHUTDOWN: - if (isPowerOnOrTransient()) { + if (isPowerOnOrTransient() && !isReboot) { onStandby(STANDBY_SHUTDOWN); } break; From 2fc3ab6d6f5ea882746846f08011089f4bece1c1 Mon Sep 17 00:00:00 2001 From: Amy Date: Wed, 24 Oct 2018 12:40:42 -0700 Subject: [PATCH 5/5] Fix crash on TV device from casting error. ag/5347939 Test: local tested Bug: 118389063 Change-Id: I9d4649ee00fb27983ce6f0a09a6c7879ca0aba2a --- .../java/com/android/server/hdmi/DeviceDiscoveryAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java index b640e7f757b6f..af716242210ed 100755 --- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java +++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java @@ -91,7 +91,7 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { private final DeviceDiscoveryCallback mCallback; private int mProcessedDeviceCount = 0; private int mTimeoutRetry = 0; - private boolean mIsTvDevice = source().mService.isTvDevice(); + private boolean mIsTvDevice = localDevice().mService.isTvDevice(); private final int mDelayPeriod; /**