Adds the text output parameter and a partial manifest to the action key for ApkManifestAction, so that the key correctly changes when the structure of the manifest changes.

--
MOS_MIGRATED_REVID=121058425
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApkManifestAction.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApkManifestAction.java
index d78f976..a378988 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApkManifestAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApkManifestAction.java
@@ -16,10 +16,10 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
+import com.google.common.primitives.Ints;
 import com.google.devtools.build.lib.actions.ActionExecutionContext;
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.actions.cache.MetadataHandler;
 import com.google.devtools.build.lib.analysis.FilesToRunProvider;
 import com.google.devtools.build.lib.analysis.actions.AbstractFileWriteAction;
 import com.google.devtools.build.lib.collect.CollectionUtils;
@@ -105,10 +105,15 @@
   }
 
   @Override
-  public DeterministicWriter newDeterministicWriter(ActionExecutionContext ctx) throws IOException {
+  public DeterministicWriter newDeterministicWriter(final ActionExecutionContext ctx)
+      throws IOException {
 
-    ApkManifestCreator manifestCreator = new ApkManifestCreator(
-        ctx.getMetadataHandler());
+    ApkManifestCreator manifestCreator = new ApkManifestCreator(new ArtifactDigester() {
+        @Override
+        public byte[] getDigest(Artifact artifact) throws IOException {
+          return ctx.getMetadataHandler().getMetadata(artifact).digest;
+        }
+    });
 
     final ApkManifest manifest = manifestCreator.createManifest();
 
@@ -126,17 +131,45 @@
 
   @Override
   protected String computeKey() {
+
+    // Use fake hashes for the purposes of the action's key, because the hashes are retrieved from
+    // the MetadataHandler, which is available at only action-execution time. This should be ok
+    // because if an input artifact changes (and hence its hash changes), the action should be rerun
+    // anyway. This is more for the purpose of putting the structure of the output data into the
+    // key.
+    ApkManifestCreator manifestCreator = new ApkManifestCreator(new ArtifactDigester() {
+        @Override
+        public byte[] getDigest(Artifact artifact) {
+          return Ints.toByteArray(artifact.getExecPathString().hashCode());
+        }
+    });
+
+    ApkManifest manifest;
+    try {
+      manifest = manifestCreator.createManifest();
+    } catch (IOException e) {
+      // The ArtifactDigester shouldn't actually throw IOException, that's just for the
+      // ArtifactDigester that uses the MetadataHandler.
+      throw new IllegalStateException(e);
+    }
+
     return new Fingerprint()
         .addString(GUID)
+        .addBoolean(textOutput)
+        .addBytes(manifest.toByteArray())
         .hexDigestAndReset();
   }
 
+  private interface ArtifactDigester {
+    byte[] getDigest(Artifact artifact) throws IOException;
+  }
+
   private class ApkManifestCreator {
 
-    private final MetadataHandler metadataHandler;
+    private final ArtifactDigester artifactDigester;
 
-    private ApkManifestCreator(MetadataHandler metadataHandler) {
-      this.metadataHandler = metadataHandler;
+    private ApkManifestCreator(ArtifactDigester artifactDigester) {
+      this.artifactDigester = artifactDigester;
     }
 
     private ApkManifest createManifest() throws IOException {
@@ -171,9 +204,9 @@
       }
       return protoArtifacts.build();
     }
-  
+
     private ApkManifestOuterClass.Artifact makeArtifactProto(Artifact artifact) throws IOException {
-      byte[] digest = metadataHandler.getMetadata(artifact).digest;
+      byte[] digest = artifactDigester.getDigest(artifact);
       return ApkManifestOuterClass.Artifact.newBuilder()
           .setExecRootPath(artifact.getExecPathString())
           .setHash(ByteString.copyFrom(digest))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
index dd0df22..3790799 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/NativeLibs.java
@@ -13,6 +13,7 @@
 // limitations under the License.
 package com.google.devtools.build.lib.rules.android;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -108,9 +109,11 @@
 
   // Map from architecture (CPU folder to place the library in) to libraries for that CPU
   private final ImmutableMap<String, Iterable<Artifact>> nativeLibs;
-  private final Artifact nativeLibsName;
+  @Nullable private final Artifact nativeLibsName;
 
-  private NativeLibs(ImmutableMap<String, Iterable<Artifact>> nativeLibs, Artifact nativeLibsName) {
+  @VisibleForTesting
+  NativeLibs(ImmutableMap<String, Iterable<Artifact>> nativeLibs,
+      @Nullable Artifact nativeLibsName) {
     this.nativeLibs = nativeLibs;
     this.nativeLibsName = nativeLibsName;
   }