Merge changes from topic "hdmi-topology-reportpa" into main

* changes:
  HDMI: Upload physical address from Report PA in metrics
  HDMI: Declare flag for uploading physical address metrics
diff --git a/media/java/android/media/tv/flags/media_tv.aconfig b/media/java/android/media/tv/flags/media_tv.aconfig
index 4b832ae..572db97 100644
--- a/media/java/android/media/tv/flags/media_tv.aconfig
+++ b/media/java/android/media/tv/flags/media_tv.aconfig
@@ -112,3 +112,11 @@
     description : "Feature flag to enable APIs for applying picture profiles"
     bug: "337330263"
 }
+
+flag {
+    name: "hdmi_control_collect_physical_address"
+    is_exported: true
+    namespace: "media_tv"
+    description: "Collect physical address from HDMI-CEC messages in metrics"
+    bug: "376001043"
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java b/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java
index 53c0217..2e66fbc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java
@@ -16,6 +16,8 @@
 
 package com.android.server.hdmi;
 
+import static android.media.tv.flags.Flags.hdmiControlCollectPhysicalAddress;
+
 import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_ARC_PENDING;
 import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_EARC_CONNECTED;
 import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_EARC_PENDING;
@@ -35,6 +37,8 @@
     @VisibleForTesting
     protected static final int FEATURE_ABORT_OPCODE_UNKNOWN = 0x100;
     private static final int ERROR_CODE_UNKNOWN = -1;
+    @VisibleForTesting
+    protected static final int PHYSICAL_ADDRESS_INVALID = 0xFFFF;
 
     /**
      * Writes a HdmiCecMessageReported atom representing an HDMI CEC message.
@@ -95,6 +99,11 @@
                 return createUserControlPressedSpecialArgs(message);
             case Constants.MESSAGE_FEATURE_ABORT:
                 return createFeatureAbortSpecialArgs(message);
+            case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS:
+                if (hdmiControlCollectPhysicalAddress()) {
+                    return createReportPhysicalAddressSpecialArgs(message);
+                }
+                return new MessageReportedSpecialArgs();
             default:
                 return new MessageReportedSpecialArgs();
         }
@@ -140,6 +149,23 @@
     }
 
     /**
+     * Constructs the special arguments for a <Report Physical Address> message.
+     *
+     * @param message The HDMI CEC message to log
+     */
+    private MessageReportedSpecialArgs createReportPhysicalAddressSpecialArgs(
+            HdmiCecMessage message) {
+        MessageReportedSpecialArgs specialArgs = new MessageReportedSpecialArgs();
+
+        if (message.getParams().length > 1) {
+            int physicalAddress = (message.getParams()[0] << 8) | message.getParams()[1];
+            specialArgs.mPhysicalAddress = physicalAddress;
+        }
+
+        return specialArgs;
+    }
+
+    /**
      * Writes a HdmiCecMessageReported atom.
      *
      * @param genericArgs Generic arguments; shared by all HdmiCecMessageReported atoms
@@ -156,7 +182,8 @@
                 genericArgs.mSendMessageResult,
                 specialArgs.mUserControlPressedCommand,
                 specialArgs.mFeatureAbortOpcode,
-                specialArgs.mFeatureAbortReason);
+                specialArgs.mFeatureAbortReason,
+                specialArgs.mPhysicalAddress);
     }
 
     /**
@@ -166,7 +193,7 @@
     protected void writeHdmiCecMessageReportedAtom(int uid, int direction,
             int initiatorLogicalAddress, int destinationLogicalAddress, int opcode,
             int sendMessageResult, int userControlPressedCommand, int featureAbortOpcode,
-            int featureAbortReason) {
+            int featureAbortReason, int physicalAddress) {
         FrameworkStatsLog.write(
                 FrameworkStatsLog.HDMI_CEC_MESSAGE_REPORTED,
                 uid,
@@ -177,7 +204,8 @@
                 sendMessageResult,
                 userControlPressedCommand,
                 featureAbortOpcode,
-                featureAbortReason);
+                featureAbortReason,
+                physicalAddress);
     }
 
     /**
@@ -284,5 +312,6 @@
         int mUserControlPressedCommand = HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN;
         int mFeatureAbortOpcode = FEATURE_ABORT_OPCODE_UNKNOWN;
         int mFeatureAbortReason = HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN;
+        int mPhysicalAddress = PHYSICAL_ADDRESS_INVALID;
     }
 }
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 c7574bd..dd4101e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java
@@ -41,11 +41,14 @@
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.HdmiPortInfo;
 import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.media.tv.flags.Flags;
 import android.os.Binder;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.test.TestLooper;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.stats.hdmi.HdmiStatsEnums;
 
 import androidx.test.InstrumentationRegistry;
@@ -54,6 +57,7 @@
 import com.android.server.SystemService;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -83,6 +87,9 @@
     private HdmiEarcController mHdmiEarcController;
     private FakeEarcNativeWrapper mEarcNativeWrapper;
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Before
     public void setUp() throws RemoteException {
         mHdmiCecAtomWriterSpy = spy(new HdmiCecAtomWriter());
@@ -232,7 +239,8 @@
                         HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN,
                         HdmiStatsEnums.VOLUME_MUTE,
                         HdmiCecAtomWriter.FEATURE_ABORT_OPCODE_UNKNOWN,
-                        HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN);
+                        HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN,
+                        HdmiCecAtomWriter.PHYSICAL_ADDRESS_INVALID);
     }
 
     @Test
@@ -258,7 +266,8 @@
                         HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN,
                         HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN,
                         HdmiCecAtomWriter.FEATURE_ABORT_OPCODE_UNKNOWN,
-                        HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN);
+                        HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN,
+                        HdmiCecAtomWriter.PHYSICAL_ADDRESS_INVALID);
     }
 
     @Test
@@ -285,7 +294,8 @@
                         HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN,
                         HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN,
                         Constants.MESSAGE_RECORD_ON,
-                        HdmiStatsEnums.UNRECOGNIZED_OPCODE);
+                        HdmiStatsEnums.UNRECOGNIZED_OPCODE,
+                        HdmiCecAtomWriter.PHYSICAL_ADDRESS_INVALID);
     }
 
     @Test
@@ -311,7 +321,8 @@
                         HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN,
                         HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN,
                         HdmiCecAtomWriter.FEATURE_ABORT_OPCODE_UNKNOWN,
-                        HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN);
+                        HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN,
+                        HdmiCecAtomWriter.PHYSICAL_ADDRESS_INVALID);
     }
 
     @Test
@@ -337,6 +348,59 @@
     }
 
     @Test
+    @EnableFlags({Flags.FLAG_HDMI_CONTROL_COLLECT_PHYSICAL_ADDRESS})
+    public void testMessageReported_writesAtom_reportPhysicalAddress() {
+        HdmiCecMessage message = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+                ADDR_PLAYBACK_1, 0x1234, HdmiDeviceInfo.DEVICE_PLAYBACK);
+
+        mHdmiCecAtomWriterSpy.messageReported(
+                message,
+                HdmiStatsEnums.INCOMING,
+                1234);
+
+        verify(mHdmiCecAtomWriterSpy, times(1))
+                .writeHdmiCecMessageReportedAtom(
+                        1234,
+                        HdmiStatsEnums.INCOMING,
+                        Constants.ADDR_PLAYBACK_1,
+                        Constants.ADDR_BROADCAST,
+                        Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS,
+                        HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN,
+                        HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN,
+                        HdmiCecAtomWriter.FEATURE_ABORT_OPCODE_UNKNOWN,
+                        HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN,
+                        0x1234);
+    }
+
+    @Test
+    @EnableFlags({Flags.FLAG_HDMI_CONTROL_COLLECT_PHYSICAL_ADDRESS})
+    public void testMessageReported_writesAtom_reportPhysicalAddress_noParams() {
+        HdmiCecMessage message = HdmiCecMessage.build(
+                Constants.ADDR_PLAYBACK_1,
+                Constants.ADDR_BROADCAST,
+                Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS,
+                new byte[0]);
+
+        mHdmiCecAtomWriterSpy.messageReported(
+                message,
+                HdmiStatsEnums.INCOMING,
+                1234);
+
+        verify(mHdmiCecAtomWriterSpy, times(1))
+                .writeHdmiCecMessageReportedAtom(
+                        1234,
+                        HdmiStatsEnums.INCOMING,
+                        Constants.ADDR_PLAYBACK_1,
+                        Constants.ADDR_BROADCAST,
+                        Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS,
+                        HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN,
+                        HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN,
+                        HdmiCecAtomWriter.FEATURE_ABORT_OPCODE_UNKNOWN,
+                        HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN,
+                        HdmiCecAtomWriter.PHYSICAL_ADDRESS_INVALID);
+    }
+
+    @Test
     public void testDsmStatusChanged_onWakeUp_ArcSupported_writesAtom_logReasonWake() {
         mHdmiControlServiceSpy.setSoundbarMode(HdmiControlManager.SOUNDBAR_MODE_DISABLED);
         Mockito.clearInvocations(mHdmiCecAtomWriterSpy);