Prevent android_binary rule from overwriting the <compatible-screens> section in the AndroidManifest.xml when it already contains a <screen> tag for each density specified in the densities attribute.

RELNOTES: The <compatible-screens> section of the AndroidManifest.xml will not be overwritten if it already contains a <screen> tag for each of the densities specified on the android_binary rule.

--
MOS_MIGRATED_REVID=102691148
diff --git a/src/tools/android/java/com/google/devtools/build/android/DensitySpecificManifestProcessor.java b/src/tools/android/java/com/google/devtools/build/android/DensitySpecificManifestProcessor.java
index ae094ea..afd1254 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DensitySpecificManifestProcessor.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DensitySpecificManifestProcessor.java
@@ -13,6 +13,7 @@
 // limitations under the License.
 package com.google.devtools.build.android;
 
+import com.google.common.collect.ImmutableBiMap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
@@ -25,8 +26,10 @@
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
@@ -45,8 +48,8 @@
 
   static final ImmutableList<String> SCREEN_SIZES = ImmutableList.of(
       "small", "normal", "large", "xlarge");
-  static final ImmutableMap<String, String> SCREEN_DENSITIES =
-      ImmutableMap.<String, String>builder()
+  static final ImmutableBiMap<String, String> SCREEN_DENSITIES =
+      ImmutableBiMap.<String, String>builder()
       .put("ldpi", "ldpi")
       .put("mdpi", "mdpi")
       .put("tvdpi", "213")
@@ -94,8 +97,9 @@
 
   /**
    * Modifies the manifest to contain a &lt;compatible-screens&gt; section corresponding to the
-   * specified densities.
-   * 
+   * specified densities. If the manifest already contains a superset of the
+   * &lt;compatible-screens&gt; section to be created, it is left unchanged.
+   *
    * @throws ManifestProcessingException when the manifest cannot be properly modified.
    */
   public Path process(Path manifest) throws ManifestProcessingException {
@@ -114,6 +118,17 @@
       }
       Node manifestElement = manifestElements.item(0);
 
+      Set<String> existingDensities = new HashSet<>();
+      NodeList screenElements = doc.getElementsByTagName("screen");
+      for (int i = 0; i < screenElements.getLength(); i++) {
+        Node screen = screenElements.item(i);
+        existingDensities.add(SCREEN_DENSITIES.inverse().get(
+            screen.getAttributes().getNamedItem("android:screenDensity").getNodeValue()));
+      }
+      if (existingDensities.containsAll(densities)) {
+        return manifest;
+      }
+
       NodeList compatibleScreensElements = doc.getElementsByTagName("compatible-screens");
       for (int i = 0; i < compatibleScreensElements.getLength(); i++) {
         Node compatibleScreensElement = compatibleScreensElements.item(i);