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
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 713f800..425fbc5 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 @@
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 cd65db6..a6951ef 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 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 @@
* @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 f72dbf6..d8f5c4c 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 @@
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 @@
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);
+ }
}