diff --git a/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java b/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java index 444d74dadd4a8..9437c4f5aee8a 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java @@ -27,7 +27,8 @@ import com.android.internal.util.FrameworkStatsLog; @VisibleForTesting public class HdmiCecAtomWriter { - private static final int FEATURE_ABORT_OPCODE_UNKNOWN = 0x100; + @VisibleForTesting + protected static final int FEATURE_ABORT_OPCODE_UNKNOWN = 0x100; private static final int ERROR_CODE_UNKNOWN = -1; /** @@ -103,26 +104,32 @@ public class HdmiCecAtomWriter { HdmiCecMessage message) { MessageReportedSpecialArgs specialArgs = new MessageReportedSpecialArgs(); - int keycode = message.getParams()[0]; - if (keycode >= 0x1E && keycode <= 0x29) { - specialArgs.mUserControlPressedCommand = HdmiStatsEnums.NUMBER; - } else { - specialArgs.mUserControlPressedCommand = keycode + 0x100; + if (message.getParams().length > 0) { + int keycode = message.getParams()[0]; + if (keycode >= 0x1E && keycode <= 0x29) { + specialArgs.mUserControlPressedCommand = HdmiStatsEnums.NUMBER; + } else { + specialArgs.mUserControlPressedCommand = keycode + 0x100; + } } return specialArgs; } /** - * Constructs method for constructing the special arguments for a message. + * Constructs the special arguments for a message. * * @param message The HDMI CEC message to log */ private MessageReportedSpecialArgs createFeatureAbortSpecialArgs(HdmiCecMessage message) { MessageReportedSpecialArgs specialArgs = new MessageReportedSpecialArgs(); - specialArgs.mFeatureAbortOpcode = message.getParams()[0] & 0xFF; // Unsigned byte - specialArgs.mFeatureAbortReason = message.getParams()[1] + 10; + if (message.getParams().length > 0) { + specialArgs.mFeatureAbortOpcode = message.getParams()[0] & 0xFF; // Unsigned byte + if (message.getParams().length > 1) { + specialArgs.mFeatureAbortReason = message.getParams()[1] + 10; + } + } return specialArgs; } @@ -135,8 +142,7 @@ public class HdmiCecAtomWriter { */ private void messageReportedBase(MessageReportedGenericArgs genericArgs, MessageReportedSpecialArgs specialArgs) { - FrameworkStatsLog.write( - FrameworkStatsLog.HDMI_CEC_MESSAGE_REPORTED, + writeHdmiCecMessageReportedAtom( genericArgs.mUid, genericArgs.mDirection, genericArgs.mInitiatorLogicalAddress, @@ -148,6 +154,26 @@ public class HdmiCecAtomWriter { specialArgs.mFeatureAbortReason); } + /** + * Writes a HdmiCecMessageReported atom representing an incoming or outgoing HDMI-CEC message. + */ + @VisibleForTesting + protected void writeHdmiCecMessageReportedAtom(int uid, int direction, + int initiatorLogicalAddress, int destinationLogicalAddress, int opcode, + int sendMessageResult, int userControlPressedCommand, int featureAbortOpcode, + int featureAbortReason) { + FrameworkStatsLog.write( + FrameworkStatsLog.HDMI_CEC_MESSAGE_REPORTED, + uid, + direction, + initiatorLogicalAddress, + destinationLogicalAddress, + opcode, + sendMessageResult, + userControlPressedCommand, + featureAbortOpcode, + featureAbortReason); + } /** * Writes a HdmiCecActiveSourceChanged atom representing a change in the active source. diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java index b903b1649fc8d..f30e97a98b70d 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java @@ -42,7 +42,7 @@ import android.os.Looper; import android.os.RemoteException; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; -import android.stats.hdmi.nano.HdmiStatsEnums; +import android.stats.hdmi.HdmiStatsEnums; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -53,6 +53,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; import java.util.ArrayList; import java.util.Collections; @@ -134,6 +135,8 @@ public class HdmiCecAtomLoggingTest { mHdmiControlServiceSpy.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); mTestLooper.dispatchAll(); + + Mockito.reset(mHdmiCecAtomWriterSpy); } @Test @@ -149,6 +152,7 @@ public class HdmiCecAtomLoggingTest { mPhysicalAddress); mHdmiCecController.sendCommand(message); + mTestLooper.dispatchAll(); verify(mHdmiCecAtomWriterSpy, times(1)).messageReported( eq(message), @@ -193,4 +197,109 @@ public class HdmiCecAtomLoggingTest { eq(callerUid), anyInt()); } + + @Test + public void testMessageReported_writesAtom_userControlPressed() { + HdmiCecMessage message = HdmiCecMessageBuilder.buildUserControlPressed( + Constants.ADDR_TV, + Constants.ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_MUTE + ); + + mHdmiCecAtomWriterSpy.messageReported( + message, + HdmiStatsEnums.INCOMING, + 1234); + + verify(mHdmiCecAtomWriterSpy, times(1)) + .writeHdmiCecMessageReportedAtom( + 1234, + HdmiStatsEnums.INCOMING, + Constants.ADDR_TV, + Constants.ADDR_PLAYBACK_1, + Constants.MESSAGE_USER_CONTROL_PRESSED, + HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN, + HdmiStatsEnums.VOLUME_MUTE, + HdmiCecAtomWriter.FEATURE_ABORT_OPCODE_UNKNOWN, + HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN); + } + + @Test + public void testMessageReported_writesAtom_userControlPressed_noParams() { + HdmiCecMessage message = new HdmiCecMessage( + Constants.ADDR_TV, + Constants.ADDR_PLAYBACK_1, + Constants.MESSAGE_USER_CONTROL_PRESSED, + new byte[0]); + + mHdmiCecAtomWriterSpy.messageReported( + message, + HdmiStatsEnums.INCOMING, + 1234); + + verify(mHdmiCecAtomWriterSpy, times(1)) + .writeHdmiCecMessageReportedAtom( + 1234, + HdmiStatsEnums.INCOMING, + Constants.ADDR_TV, + Constants.ADDR_PLAYBACK_1, + Constants.MESSAGE_USER_CONTROL_PRESSED, + HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN, + HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN, + HdmiCecAtomWriter.FEATURE_ABORT_OPCODE_UNKNOWN, + HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN); + } + + @Test + public void testMessageReported_writesAtom_featureAbort() { + HdmiCecMessage message = HdmiCecMessageBuilder.buildFeatureAbortCommand( + Constants.ADDR_TV, + Constants.ADDR_PLAYBACK_1, + Constants.MESSAGE_RECORD_ON, + Constants.ABORT_UNRECOGNIZED_OPCODE + ); + + mHdmiCecAtomWriterSpy.messageReported( + message, + HdmiStatsEnums.INCOMING, + 1234); + + verify(mHdmiCecAtomWriterSpy, times(1)) + .writeHdmiCecMessageReportedAtom( + 1234, + HdmiStatsEnums.INCOMING, + Constants.ADDR_TV, + Constants.ADDR_PLAYBACK_1, + Constants.MESSAGE_FEATURE_ABORT, + HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN, + HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN, + Constants.MESSAGE_RECORD_ON, + HdmiStatsEnums.UNRECOGNIZED_OPCODE); + } + + @Test + public void testMessageReported_writesAtom_featureAbort_noParams() { + HdmiCecMessage message = new HdmiCecMessage( + Constants.ADDR_TV, + Constants.ADDR_PLAYBACK_1, + Constants.MESSAGE_FEATURE_ABORT, + new byte[0]); + + mHdmiCecAtomWriterSpy.messageReported( + message, + HdmiStatsEnums.INCOMING, + 1234); + + verify(mHdmiCecAtomWriterSpy, times(1)) + .writeHdmiCecMessageReportedAtom( + 1234, + HdmiStatsEnums.INCOMING, + Constants.ADDR_TV, + Constants.ADDR_PLAYBACK_1, + Constants.MESSAGE_FEATURE_ABORT, + HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN, + HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN, + HdmiCecAtomWriter.FEATURE_ABORT_OPCODE_UNKNOWN, + HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN); + } }