Add support for symlink_preferred_arch in apex

Some modules rely on symlink_preferred_arch to have expected files
present. This change makes apexs include these symlinks.

Test: m com.android.runtime.debug
      pushd $(mktemp -d)
      mkdir mnt
      unzip $OUT/apex/system/com.android.runtime.debug.apex
      sudo mount -o loop,ro apex_payload.img mnt
      Ensure that mnt/bin/dalvikvm and mnt/bin/dex2oatd both exist and
      are symlinks to mnt/bin/dalvikvm64 and mnt/bin/dex2oatd32
      respectively.

Bug: 119942078
Bug: 122373634
Bug: 123079311
Change-Id: I47868fbedc5bdd3141a836c488f79e91e0a6ddfe
diff --git a/apex/apex.go b/apex/apex.go
index 321e2e8..96a4bd5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -333,6 +333,7 @@
 	installDir string
 	class      apexFileClass
 	module     android.Module
+	symlinks   []string
 }
 
 type apexBundle struct {
@@ -396,7 +397,8 @@
 			a.properties.Multilib.Both.Binaries, target.String(),
 			a.getImageVariation(config))
 
-		if i == 0 {
+		isPrimaryAbi := i == 0
+		if isPrimaryAbi {
 			// When multilib.* is omitted for binaries, it implies
 			// multilib.first.
 			ctx.AddFarVariationDependencies([]blueprint.Variation{
@@ -571,7 +573,7 @@
 			case sharedLibTag:
 				if cc, ok := child.(*cc.Module); ok {
 					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc})
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc, nil})
 					return true
 				} else {
 					ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
@@ -584,7 +586,7 @@
 						return true
 					}
 					fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeExecutable, cc})
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeExecutable, cc, cc.Symlinks()})
 					return true
 				} else {
 					ctx.PropertyErrorf("binaries", "%q is not a cc_binary module", depName)
@@ -595,7 +597,7 @@
 					if fileToCopy == nil {
 						ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
 					} else {
-						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, java.Arch().ArchType, dirInApex, javaSharedLib, java})
+						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, java.Arch().ArchType, dirInApex, javaSharedLib, java, nil})
 					}
 					return true
 				} else {
@@ -604,7 +606,7 @@
 			case prebuiltTag:
 				if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
 					fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, prebuilt.Arch().ArchType, dirInApex, etc, prebuilt})
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, prebuilt.Arch().ArchType, dirInApex, etc, prebuilt, nil})
 					return true
 				} else {
 					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
@@ -639,7 +641,7 @@
 					}
 					depName := ctx.OtherModuleName(child)
 					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc})
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc, nil})
 					return true
 				}
 			}
@@ -732,6 +734,10 @@
 		dest_path := filepath.Join(android.PathForModuleOut(ctx, "image"+suffix).String(), dest)
 		copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path))
 		copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
+		for _, sym := range a.filesInfo[i].symlinks {
+			symlinkDest := filepath.Join(filepath.Dir(dest_path), sym)
+			copyCommands = append(copyCommands, "ln -s "+filepath.Base(dest)+" "+symlinkDest)
+		}
 	}
 	implicitInputs := append(android.Paths(nil), filesToCopy...)
 	implicitInputs = append(implicitInputs, manifest)
@@ -747,6 +753,9 @@
 			pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
 			if f.installDir == "bin" {
 				executablePaths = append(executablePaths, pathInApex)
+				for _, s := range f.symlinks {
+					executablePaths = append(executablePaths, filepath.Join("bin", s))
+				}
 			} else {
 				readOnlyPaths = append(readOnlyPaths, pathInApex)
 			}
@@ -879,7 +888,7 @@
 			Input:  manifest,
 			Output: copiedManifest,
 		})
-		a.filesInfo = append(a.filesInfo, apexFile{copiedManifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc, nil})
+		a.filesInfo = append(a.filesInfo, apexFile{copiedManifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc, nil, nil})
 
 		for _, fi := range a.filesInfo {
 			dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)