From 1c9002311e2615cd69e7f399409f7e6df3ab8821 Mon Sep 17 00:00:00 2001 From: Yan Han Date: Thu, 10 Sep 2020 18:42:10 +0200 Subject: [PATCH] Add method to compute the relationship between two paths. This is a helper function used to implement the initial set of Westworld atoms. Test: atest HdmiUtilsTest Bug: 159796477 Change-Id: Ic21fa1a9b7bd93e0ae7e125601e532468fae7928 --- .../com/android/server/hdmi/Constants.java | 24 +++++ .../com/android/server/hdmi/HdmiUtils.java | 56 ++++++++---- .../android/server/hdmi/HdmiUtilsTest.java | 90 +++++++++++++++++++ 3 files changed, 151 insertions(+), 19 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 713f8008e313c..425fbc5687ec6 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -329,6 +329,30 @@ final class Constants { static final int INVALID_PHYSICAL_ADDRESS = HdmiDeviceInfo.PATH_INVALID; static final int PATH_INTERNAL = HdmiDeviceInfo.PATH_INTERNAL; + // The relationship from one path (physical address) to another. + @IntDef({ + PATH_RELATIONSHIP_UNKNOWN, + PATH_RELATIONSHIP_DIFFERENT_BRANCH, + PATH_RELATIONSHIP_ANCESTOR, + PATH_RELATIONSHIP_DESCENDANT, + PATH_RELATIONSHIP_SIBLING, + PATH_RELATIONSHIP_SAME + }) + @interface PathRelationship {} + + // One or both of the paths is invalid + static final int PATH_RELATIONSHIP_UNKNOWN = 0; + // None of the relationships below holds + static final int PATH_RELATIONSHIP_DIFFERENT_BRANCH = 1; + // A path is either the TV, or between the TV and another path + static final int PATH_RELATIONSHIP_ANCESTOR = 2; + // A path is located somewhere below another path + static final int PATH_RELATIONSHIP_DESCENDANT = 3; + // A path has the same parent as another path + static final int PATH_RELATIONSHIP_SIBLING = 4; + // A path is equal to another path + static final int PATH_RELATIONSHIP_SAME = 5; + // Strategy for device polling. // Should use "OR(|) operation of POLL_STRATEGY_XXX and POLL_ITERATION_XXX. static final int POLL_STRATEGY_MASK = 0x3; // first and second bit. diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java index cd65db6055afd..a6951ef1958f0 100644 --- a/services/core/java/com/android/server/hdmi/HdmiUtils.java +++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java @@ -24,10 +24,11 @@ import android.util.Xml; import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; - import com.android.server.hdmi.Constants.AbortReason; import com.android.server.hdmi.Constants.AudioCodec; import com.android.server.hdmi.Constants.FeatureOpcode; +import com.android.server.hdmi.Constants.PathRelationship; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -311,26 +312,43 @@ final class HdmiUtils { * @return true if the new path in the active routing path */ static boolean isInActiveRoutingPath(int activePath, int newPath) { - // Check each nibble of the currently active path and the new path till the position - // where the active nibble is not zero. For (activePath, newPath), - // (1.1.0.0, 1.0.0.0) -> true, new path is a parent - // (1.2.1.0, 1.2.1.2) -> true, new path is a descendant - // (1.1.0.0, 1.2.0.0) -> false, new path is a sibling - // (1.0.0.0, 2.0.0.0) -> false, in a completely different path - for (int i = 12; i >= 0; i -= 4) { - int nibbleActive = (activePath >> i) & 0xF; - if (nibbleActive == 0) { - break; - } - int nibbleNew = (newPath >> i) & 0xF; - if (nibbleNew == 0) { - break; - } - if (nibbleActive != nibbleNew) { - return false; + @PathRelationship int pathRelationship = pathRelationship(newPath, activePath); + return (pathRelationship == Constants.PATH_RELATIONSHIP_ANCESTOR + || pathRelationship == Constants.PATH_RELATIONSHIP_DESCENDANT + || pathRelationship == Constants.PATH_RELATIONSHIP_SAME); + } + + /** + * Computes the relationship from the first path to the second path. + */ + static @PathRelationship int pathRelationship(int firstPath, int secondPath) { + if (firstPath == Constants.INVALID_PHYSICAL_ADDRESS + || secondPath == Constants.INVALID_PHYSICAL_ADDRESS) { + return Constants.PATH_RELATIONSHIP_UNKNOWN; + } + // Loop forwards through both paths, looking for the first nibble where the paths differ. + // Checking this nibble and the next one distinguishes between most possible relationships. + for (int nibbleIndex = 0; nibbleIndex <= 3; nibbleIndex++) { + int shift = 12 - nibbleIndex * 4; + int firstPathNibble = (firstPath >> shift) & 0xF; + int secondPathNibble = (secondPath >> shift) & 0xF; + // Found the first nibble where the paths differ. + if (firstPathNibble != secondPathNibble) { + int firstPathNextNibble = (firstPath >> (shift - 4)) & 0xF; + int secondPathNextNibble = (secondPath >> (shift - 4)) & 0xF; + if (firstPathNibble == 0) { + return Constants.PATH_RELATIONSHIP_ANCESTOR; + } else if (secondPathNibble == 0) { + return Constants.PATH_RELATIONSHIP_DESCENDANT; + } else if (nibbleIndex == 3 + || (firstPathNextNibble == 0 && secondPathNextNibble == 0)) { + return Constants.PATH_RELATIONSHIP_SIBLING; + } else { + return Constants.PATH_RELATIONSHIP_DIFFERENT_BRANCH; + } } } - return true; + return Constants.PATH_RELATIONSHIP_SAME; } /** diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java index f72dbf6ed0b0e..d8f5c4c8f58ce 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java @@ -17,6 +17,9 @@ package com.android.server.hdmi; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import android.platform.test.annotations.Presubmit; import android.util.Slog; @@ -145,4 +148,91 @@ public class HdmiUtilsTest { assertThat(config).isEqualTo(expectedConfig); } + + @Test + public void isAffectingActiveRoutingPath() { + // New path alters the parent + assertTrue(HdmiUtils.isAffectingActiveRoutingPath(0x1100, 0x2000)); + // New path is a sibling + assertTrue(HdmiUtils.isAffectingActiveRoutingPath(0x1100, 0x1200)); + // New path is the descendant of a sibling + assertFalse(HdmiUtils.isAffectingActiveRoutingPath(0x1100, 0x1210)); + // In a completely different path + assertFalse(HdmiUtils.isAffectingActiveRoutingPath(0x1000, 0x3200)); + } + + @Test + public void isInActiveRoutingPath() { + // New path is a parent + assertTrue(HdmiUtils.isInActiveRoutingPath(0x1100, 0x1000)); + // New path is a descendant + assertTrue(HdmiUtils.isInActiveRoutingPath(0x1210, 0x1212)); + // New path is a sibling + assertFalse(HdmiUtils.isInActiveRoutingPath(0x1100, 0x1200)); + // In a completely different path + assertFalse(HdmiUtils.isInActiveRoutingPath(0x1000, 0x2000)); + } + + @Test + public void pathRelationship_unknown() { + assertThat(HdmiUtils.pathRelationship(0x1234, Constants.INVALID_PHYSICAL_ADDRESS)) + .isEqualTo(Constants.PATH_RELATIONSHIP_UNKNOWN); + assertThat(HdmiUtils.pathRelationship(Constants.INVALID_PHYSICAL_ADDRESS, 0x1234)) + .isEqualTo(Constants.PATH_RELATIONSHIP_UNKNOWN); + assertThat(HdmiUtils.pathRelationship(Constants.INVALID_PHYSICAL_ADDRESS, + Constants.INVALID_PHYSICAL_ADDRESS)) + .isEqualTo(Constants.PATH_RELATIONSHIP_UNKNOWN); + } + + @Test + public void pathRelationship_differentBranch() { + assertThat(HdmiUtils.pathRelationship(0x1200, 0x2000)) + .isEqualTo(Constants.PATH_RELATIONSHIP_DIFFERENT_BRANCH); + assertThat(HdmiUtils.pathRelationship(0x1234, 0x1224)) + .isEqualTo(Constants.PATH_RELATIONSHIP_DIFFERENT_BRANCH); + assertThat(HdmiUtils.pathRelationship(0x1234, 0x1134)) + .isEqualTo(Constants.PATH_RELATIONSHIP_DIFFERENT_BRANCH); + assertThat(HdmiUtils.pathRelationship(0x1234, 0x2234)) + .isEqualTo(Constants.PATH_RELATIONSHIP_DIFFERENT_BRANCH); + } + + @Test + public void pathRelationship_ancestor() { + assertThat(HdmiUtils.pathRelationship(0x0000, 0x1230)) + .isEqualTo(Constants.PATH_RELATIONSHIP_ANCESTOR); + assertThat(HdmiUtils.pathRelationship(0x1000, 0x1230)) + .isEqualTo(Constants.PATH_RELATIONSHIP_ANCESTOR); + assertThat(HdmiUtils.pathRelationship(0x1200, 0x1230)) + .isEqualTo(Constants.PATH_RELATIONSHIP_ANCESTOR); + } + + @Test + public void pathRelationship_descendant() { + assertThat(HdmiUtils.pathRelationship(0x1230, 0x0000)) + .isEqualTo(Constants.PATH_RELATIONSHIP_DESCENDANT); + assertThat(HdmiUtils.pathRelationship(0x1230, 0x1000)) + .isEqualTo(Constants.PATH_RELATIONSHIP_DESCENDANT); + assertThat(HdmiUtils.pathRelationship(0x1230, 0x1200)) + .isEqualTo(Constants.PATH_RELATIONSHIP_DESCENDANT); + } + + @Test + public void pathRelationship_sibling() { + assertThat(HdmiUtils.pathRelationship(0x1000, 0x2000)) + .isEqualTo(Constants.PATH_RELATIONSHIP_SIBLING); + assertThat(HdmiUtils.pathRelationship(0x1200, 0x1100)) + .isEqualTo(Constants.PATH_RELATIONSHIP_SIBLING); + assertThat(HdmiUtils.pathRelationship(0x1230, 0x1220)) + .isEqualTo(Constants.PATH_RELATIONSHIP_SIBLING); + assertThat(HdmiUtils.pathRelationship(0x1234, 0x1233)) + .isEqualTo(Constants.PATH_RELATIONSHIP_SIBLING); + } + + @Test + public void pathRelationship_same() { + assertThat(HdmiUtils.pathRelationship(0x0000, 0x0000)) + .isEqualTo(Constants.PATH_RELATIONSHIP_SAME); + assertThat(HdmiUtils.pathRelationship(0x1234, 0x1234)) + .isEqualTo(Constants.PATH_RELATIONSHIP_SAME); + } }