Merge "Add a simple metadata class option for system feature codegen" into main
diff --git a/aconfig/exported_java_aconfig_library.go b/aconfig/exported_java_aconfig_library.go
index a64cac8..f7e6dcf 100644
--- a/aconfig/exported_java_aconfig_library.go
+++ b/aconfig/exported_java_aconfig_library.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"strconv"
 )
 
 func ExportedJavaDeclarationsLibraryFactory() android.Singleton {
@@ -37,6 +38,16 @@
 		cacheFiles = append(cacheFiles, decl.IntermediateCacheOutputPath)
 	})
 
+	var newExported bool
+	if useNewExported, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_NEW_EXPORTED"); ok {
+		newExported = useNewExported == "true"
+	}
+
+	var newStorage bool
+	if useNewStorage, ok := ctx.Config().GetBuildFlag("RELEASE_READ_FROM_NEW_STORAGE"); ok {
+		newStorage = useNewStorage == "true"
+	}
+
 	// Generate build action for aconfig
 	this.intermediatePath = android.PathForIntermediates(ctx, "exported_java_aconfig_library.jar")
 	ctx.Build(pctx, android.BuildParams{
@@ -45,7 +56,9 @@
 		Output:      this.intermediatePath,
 		Description: "exported_java_aconfig_library",
 		Args: map[string]string{
-			"cache_files": android.JoinPathsWithPrefix(cacheFiles, " "),
+			"cache_files":      android.JoinPathsWithPrefix(cacheFiles, " "),
+			"use_new_storage":  strconv.FormatBool(newStorage),
+			"use_new_exported": strconv.FormatBool(newExported),
 		},
 	})
 	ctx.Phony("exported_java_aconfig_library", this.intermediatePath)
diff --git a/aconfig/init.go b/aconfig/init.go
index 21903e2..ab6ee46 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -91,7 +91,12 @@
 			Command: `rm -rf ${out}.tmp` +
 				`&& for cache in ${cache_files}; do ` +
 				`  if [ -n "$$(${aconfig} dump-cache --dedup --cache $$cache --filter=is_exported:true --format='{fully_qualified_name}')" ]; then ` +
-				`    ${aconfig} create-java-lib --cache $$cache --mode=exported --out ${out}.tmp; ` +
+				`    ${aconfig} create-java-lib` +
+				`        --cache $$cache` +
+				`        --mode=exported` +
+				`        --allow-instrumentation ${use_new_storage}` +
+				`        --new-exported ${use_new_exported}` +
+				`        --out ${out}.tmp; ` +
 				`  fi ` +
 				`done` +
 				`&& $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
@@ -100,7 +105,7 @@
 				"$aconfig",
 				"$soong_zip",
 			},
-		}, "cache_files")
+		}, "cache_files", "use_new_storage", "use_new_exported")
 )
 
 func init() {
diff --git a/android/Android.bp b/android/Android.bp
index 4e2006d..bb16856 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -98,6 +98,7 @@
         "raw_files.go",
         "recovery_build_prop.go",
         "register.go",
+        "removed_package.go",
         "rule_builder.go",
         "sandbox.go",
         "sbom.go",
diff --git a/android/defs.go b/android/defs.go
index c4e3b99..9f3fb1e 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -102,18 +102,6 @@
 			Description: "concatenate files to $out",
 		})
 
-	// Calculates the hash of a directory and writes to a file.
-	// Note that the directory to calculate the hash is intentionally not listed as an input,
-	// to prevent adding directory as a ninja dependency. Thus, an implicit dependency to a file
-	// is required.
-	WriteDirectoryHash = pctx.AndroidStaticRule("WriteDirectoryHash",
-		blueprint.RuleParams{
-			Command:     "rm -f $out && ${calculateDirectoryHash} $dir $out",
-			CommandDeps: []string{"${calculateDirectoryHash}"},
-			Description: "Calculates the hash of a directory and writes to $out",
-		}, "dir",
-	)
-
 	// Used only when USE_GOMA=true is set, to restrict non-goma jobs to the local parallelism value
 	localPool = blueprint.NewBuiltinPool("local_pool")
 
@@ -130,6 +118,4 @@
 	pctx.VariableFunc("RBEWrapper", func(ctx PackageVarContext) string {
 		return ctx.Config().RBEWrapper()
 	})
-
-	pctx.HostBinToolVariable("calculateDirectoryHash", "calculate_directory_hash")
 }
diff --git a/android/module.go b/android/module.go
index 72dba04..b8f2cae 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1049,7 +1049,7 @@
 	hostTargets = append(hostTargets, ctx.Config().BuildOSCommonTarget)
 
 	if ctx.Device() {
-		for _, depName := range ctx.Module().RequiredModuleNames(ctx) {
+		for _, depName := range append(ctx.Module().RequiredModuleNames(ctx), ctx.Module().VintfFragmentModuleNames(ctx)...) {
 			for _, target := range deviceTargets {
 				addDep(target, depName)
 			}
@@ -1062,7 +1062,7 @@
 	}
 
 	if ctx.Host() {
-		for _, depName := range ctx.Module().RequiredModuleNames(ctx) {
+		for _, depName := range append(ctx.Module().RequiredModuleNames(ctx), ctx.Module().VintfFragmentModuleNames(ctx)...) {
 			for _, target := range hostTargets {
 				// When a host module requires another host module, don't make a
 				// dependency if they have different OSes (i.e. hostcross).
diff --git a/android/recovery_build_prop.go b/android/recovery_build_prop.go
index 91d1904..ac7d2ec 100644
--- a/android/recovery_build_prop.go
+++ b/android/recovery_build_prop.go
@@ -83,8 +83,10 @@
 		r.properties.Product_build_prop,
 		r.properties.System_ext_build_prop,
 	} {
-		if buildPropPath := PathForModuleSrc(ctx, proptools.String(buildProp)); buildPropPath != nil {
-			buildProps = append(buildProps, buildPropPath)
+		if buildProp != nil {
+			if buildPropPath := PathForModuleSrc(ctx, proptools.String(buildProp)); buildPropPath != nil {
+				buildProps = append(buildProps, buildPropPath)
+			}
 		}
 	}
 	return buildProps
diff --git a/android/removed_package.go b/android/removed_package.go
new file mode 100644
index 0000000..aa54c2a
--- /dev/null
+++ b/android/removed_package.go
@@ -0,0 +1,60 @@
+package android
+
+import (
+	"fmt"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+)
+
+func init() {
+	InitRegistrationContext.RegisterModuleType("removed_package", removedPackageModuleFactory)
+}
+
+type removedPackageModuleProps struct {
+	// The error message to display when this module is built. This is optional, there is a
+	// reasonable default message.
+	Message *string
+}
+
+type removedPackageModule struct {
+	ModuleBase
+	properties removedPackageModuleProps
+}
+
+// removed_package will cause a build failure when it's included in PRODUCT_PACKAGES. It's needed
+// because currently you can add non-existent packages to PRODUCT_PACKAGES, and the build will
+// not notice/complain, unless you opt-into enforcement via $(call enforce-product-packages-exist).
+// Opting into the enforcement is difficult in some cases, because a package exists on some source
+// trees but not on others. removed_package is an intermediate solution that allows you to remove
+// a package and still get an error if it remains in PRODUCT_PACKAGES somewhere.
+func removedPackageModuleFactory() Module {
+	m := &removedPackageModule{}
+	InitAndroidModule(m)
+	m.AddProperties(&m.properties)
+	return m
+}
+
+var removedPackageRule = pctx.AndroidStaticRule("removed_package", blueprint.RuleParams{
+	Command: "echo $message && false",
+}, "message")
+
+func (m *removedPackageModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	// Unchecked module so that checkbuild doesn't fail
+	ctx.UncheckedModule()
+
+	out := PathForModuleOut(ctx, "out.txt")
+	message := fmt.Sprintf("%s has been removed, and can no longer be used.", ctx.ModuleName())
+	if m.properties.Message != nil {
+		message = *m.properties.Message
+	}
+	ctx.Build(pctx, BuildParams{
+		Rule:   removedPackageRule,
+		Output: out,
+		Args: map[string]string{
+			"message": proptools.ShellEscape(message),
+		},
+	})
+
+	ctx.InstallFile(PathForModuleInstall(ctx, "removed_module"), ctx.ModuleName(), out)
+}
diff --git a/android/variable.go b/android/variable.go
index 3cf66ea..a60cad5 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -532,7 +532,8 @@
 	OdmPropFiles       []string `json:",omitempty"`
 	VendorPropFiles    []string `json:",omitempty"`
 
-	EnableUffdGc *string `json:",omitempty"`
+	EnableUffdGc       *string `json:",omitempty"`
+	BoardKernelVersion *string `json:",omitempty"`
 
 	BoardAvbEnable                         *bool    `json:",omitempty"`
 	BoardAvbSystemAddHashtreeFooterArgs    []string `json:",omitempty"`
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index e3804e5..ee23b51 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -718,6 +718,16 @@
 	} else if global.EnableUffdGc == "default" {
 		// Generated by `build/make/core/Makefile`.
 		kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt")
+		if !ctx.Config().KatiEnabled() {
+			// In soong-only mode, we need to generate the kernel_version_for_uffd_gc.txt with kernel version
+			kernelVersion := android.String(ctx.Config().ProductVariables().BoardKernelVersion)
+			if kernelVersion == "" {
+				// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5382;drc=66783fca85911af9da48d9b4f35a61b3873023e9
+				panic("BOARD_KERNEL_VERSION is not set. Build team will convert more stuff from Make to Soong to support this scenario.")
+			}
+			android.WriteFileRule(ctx, kernelVersionFile, kernelVersion)
+		}
+
 		// Determine the UFFD GC flag by the kernel version file.
 		rule := android.NewRuleBuilder(pctx, ctx)
 		rule.Command().
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 7b0f51f..1f188d5 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -15,9 +15,10 @@
 package dexpreopt
 
 import (
-	"android/soong/android"
 	"fmt"
 	"testing"
+
+	"android/soong/android"
 )
 
 func testSystemModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
@@ -403,6 +404,7 @@
 	preparers := android.GroupFixturePreparers(
 		PrepareForTestWithFakeDex2oatd,
 		PrepareForTestWithDexpreoptConfig,
+		android.FixtureModifyConfig(android.SetKatiEnabledForTests),
 		FixtureSetEnableUffdGc("default"),
 	)
 
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index ab1b96e..ea46556 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -79,5 +79,39 @@
 }
 
 func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	a.buildTargetFilesZip(ctx)
+}
 
+func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext) {
+	targetFilesDir := android.PathForModuleOut(ctx, "target_files_dir")
+	targetFilesZip := android.PathForModuleOut(ctx, "target_files.zip")
+
+	builder := android.NewRuleBuilder(pctx, ctx)
+	builder.Command().Textf("rm -rf %s", targetFilesDir.String())
+	builder.Command().Textf("mkdir -p %s", targetFilesDir.String())
+	if a.partitionProps.Vendor_partition_name != nil {
+		fsInfo := a.getFilesystemInfo(ctx, *a.partitionProps.Vendor_partition_name)
+		builder.Command().Textf("mkdir -p %s/VENDOR", targetFilesDir.String())
+		builder.Command().
+			BuiltTool("acp").
+			Textf("-rd %s/. %s/VENDOR", fsInfo.RootDir, targetFilesDir).
+			Implicit(fsInfo.Output) // so that the staging dir is built
+	}
+	builder.Command().
+		BuiltTool("soong_zip").
+		Text("-d").
+		FlagWithOutput("-o ", targetFilesZip).
+		FlagWithArg("-C ", targetFilesDir.String()).
+		FlagWithArg("-D ", targetFilesDir.String()).
+		Text("-sha256")
+	builder.Build("target_files_"+ctx.ModuleName(), "Build target_files.zip")
+}
+
+func (a *androidDevice) getFilesystemInfo(ctx android.ModuleContext, depName string) FilesystemInfo {
+	fsMod := ctx.GetDirectDepWithTag(depName, filesystemDepTag)
+	fsInfo, ok := android.OtherModuleProvider(ctx, fsMod, FilesystemProvider)
+	if !ok {
+		ctx.ModuleErrorf("Expected dependency %s to be a filesystem", depName)
+	}
+	return fsInfo
 }
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 3f08648..5845d59 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -345,15 +345,14 @@
 }
 
 type FilesystemInfo struct {
+	// The built filesystem image
+	Output android.Path
 	// A text file containing the list of paths installed on the partition.
 	FileListFile android.Path
-
-	// Root directory of the installed partition
-	Rootdir android.Path
-
-	// A text file containing the hash value of the metadata and the content hashes
-	// of Rootdir
-	DirectoryHashFile android.Path
+	// The root staging directory used to build the output filesystem. If consuming this, make sure
+	// to add a dependency on the Output file, as you cannot add dependencies on directories
+	// in ninja.
+	RootDir android.Path
 }
 
 var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]()
@@ -452,25 +451,14 @@
 		rootDir = rootDir.Join(ctx, "root")
 	}
 
-	rootDirHash := android.PathForModuleOut(ctx, "rootdir-hash.txt")
-	ctx.Build(pctx, android.BuildParams{
-		Rule:     android.WriteDirectoryHash,
-		Output:   rootDirHash,
-		Implicit: f.output,
-		Args: map[string]string{
-			"dir": rootDir.String(),
-		},
-	})
-
 	fileListFile := android.PathForModuleOut(ctx, "fileList")
 	android.WriteFileRule(ctx, fileListFile, f.installedFilesList())
 
 	android.SetProvider(ctx, FilesystemProvider, FilesystemInfo{
-		FileListFile:      fileListFile,
-		Rootdir:           rootDir,
-		DirectoryHashFile: rootDirHash,
+		Output:       f.output,
+		FileListFile: fileListFile,
+		RootDir:      rootDir,
 	})
-
 	f.fileListFile = fileListFile
 
 	if proptools.Bool(f.properties.Unchecked_module) {
@@ -829,17 +817,17 @@
 	}
 }
 
-func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, hashFiles android.Paths) {
+func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, partitions android.Paths) {
 	ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) {
 		if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok {
-			rootDirs = append(rootDirs, fsProvider.Rootdir)
-			hashFiles = append(hashFiles, fsProvider.DirectoryHashFile)
+			rootDirs = append(rootDirs, fsProvider.RootDir)
+			partitions = append(partitions, fsProvider.Output)
 		} else {
 			ctx.PropertyErrorf("include_files_of", "only filesystem modules can be listed in "+
 				"include_files_of but %s is not a filesystem module", m.Name())
 		}
 	})
-	return rootDirs, hashFiles
+	return rootDirs, partitions
 }
 
 func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) (android.Path, android.OutputPath) {
@@ -874,7 +862,7 @@
 	f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir)
 	f.copyFilesToProductOut(ctx, builder, rebasedDir)
 
-	rootDirs, hashFiles := includeFilesRootDir(ctx)
+	rootDirs, partitions := includeFilesRootDir(ctx)
 
 	output := android.PathForModuleOut(ctx, f.installFileName())
 	cmd := builder.Command().
@@ -884,7 +872,7 @@
 	for i := range len(rootDirs) {
 		cmd.Text(rootDirs[i].String())
 	}
-	cmd.Implicits(hashFiles)
+	cmd.Implicits(partitions)
 
 	if nodeList := f.properties.Dev_nodes_description_file; nodeList != nil {
 		cmd.FlagWithInput("-n ", android.PathForModuleSrc(ctx, proptools.String(nodeList)))
diff --git a/fsgen/boot_imgs.go b/fsgen/boot_imgs.go
index 4e80720..c73c345 100644
--- a/fsgen/boot_imgs.go
+++ b/fsgen/boot_imgs.go
@@ -119,7 +119,6 @@
 			Avb_mode:           avbInfo.avbMode,
 			Avb_private_key:    avbInfo.avbkeyFilegroup,
 			Avb_rollback_index: avbInfo.avbRollbackIndex,
-			Avb_algorithm:      avbInfo.avbAlgorithm,
 			Dtb_prebuilt:       dtbPrebuilt,
 			Cmdline:            cmdline,
 			Bootconfig:         vendorBootConfigImg,
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 6474397..a2840b5 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -339,22 +339,7 @@
 		}
 	case "recovery":
 		dirs := append(commonPartitionDirs, []string{
-			"odm_file_contexts",
-			"odm_property_contexts",
-			"plat_file_contexts",
-			"plat_property_contexts",
-			"plat_service_contexts",
-			"product_file_contexts",
-			"product_property_contexts",
-			"product_service_contexts",
 			"sdcard",
-			"sepolicy",
-			"system_ext_file_contexts",
-			"system_ext_property_contexts",
-			"system_ext_service_contexts",
-			"vendor_file_contexts",
-			"vendor_property_contexts",
-			"vendor_service_contexts",
 		}...)
 
 		dirsWithRoot := make([]string, len(dirs))
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index de0a1cb..9327669 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -150,7 +150,23 @@
 				},
 				"ramdisk":        {},
 				"vendor_ramdisk": {},
-				"recovery":       {},
+				"recovery": {
+					"sepolicy.recovery":                     defaultDepCandidateProps(ctx.Config()),
+					"plat_file_contexts.recovery":           defaultDepCandidateProps(ctx.Config()),
+					"plat_service_contexts.recovery":        defaultDepCandidateProps(ctx.Config()),
+					"plat_property_contexts.recovery":       defaultDepCandidateProps(ctx.Config()),
+					"system_ext_file_contexts.recovery":     defaultDepCandidateProps(ctx.Config()),
+					"system_ext_service_contexts.recovery":  defaultDepCandidateProps(ctx.Config()),
+					"system_ext_property_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+					"vendor_file_contexts.recovery":         defaultDepCandidateProps(ctx.Config()),
+					"vendor_service_contexts.recovery":      defaultDepCandidateProps(ctx.Config()),
+					"vendor_property_contexts.recovery":     defaultDepCandidateProps(ctx.Config()),
+					"odm_file_contexts.recovery":            defaultDepCandidateProps(ctx.Config()),
+					"odm_property_contexts.recovery":        defaultDepCandidateProps(ctx.Config()),
+					"product_file_contexts.recovery":        defaultDepCandidateProps(ctx.Config()),
+					"product_service_contexts.recovery":     defaultDepCandidateProps(ctx.Config()),
+					"product_property_contexts.recovery":    defaultDepCandidateProps(ctx.Config()),
+				},
 			},
 			fsDepsMutex:                     sync.Mutex{},
 			moduleToInstallationProps:       map[string]installationProperties{},
diff --git a/java/robolectric.go b/java/robolectric.go
index 5f46267..3b2c656 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -41,6 +41,7 @@
 }
 
 const robolectricCurrentLib = "Robolectric_all-target"
+const clearcutJunitLib = "ClearcutJunitListenerAar"
 const robolectricPrebuiltLibPattern = "platform-robolectric-%s-prebuilt"
 
 var (
@@ -106,6 +107,8 @@
 		ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module")
 	}
 
+	ctx.AddVariationDependencies(nil, staticLibTag, clearcutJunitLib)
+
 	if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
 		ctx.AddVariationDependencies(nil, staticLibTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
 	} else if !proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
diff --git a/java/robolectric_test.go b/java/robolectric_test.go
index 4775bac..a2474e8 100644
--- a/java/robolectric_test.go
+++ b/java/robolectric_test.go
@@ -44,6 +44,12 @@
 	java_library {
 		name: "junitxml",
 		srcs: ["JUnitXml.java"]
+
+	}
+
+	java_library {
+		name: "ClearcutJunitListenerAar",
+		srcs: ["Runtime.java"]
 	}
 
 	java_library_host {
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
index ec7a971..1225da0 100644
--- a/kernel/prebuilt_kernel_modules.go
+++ b/kernel/prebuilt_kernel_modules.go
@@ -247,6 +247,8 @@
 		return modulesDir.Join(ctx, "vendor", "lib", "modules")
 	} else if ctx.InstallInOdmDlkm() {
 		return modulesDir.Join(ctx, "odm", "lib", "modules")
+	} else if ctx.InstallInVendorRamdisk() {
+		return modulesDir.Join(ctx, "lib", "modules")
 	} else {
 		// not an android dlkm module.
 		return modulesDir
@@ -309,8 +311,8 @@
 	builder.Build("depmod", fmt.Sprintf("depmod %s", ctx.ModuleName()))
 
 	finalModulesDep := modulesDep
-	// Add a leading slash to paths in modules.dep of android dlkm
-	if ctx.InstallInSystemDlkm() || ctx.InstallInVendorDlkm() || ctx.InstallInOdmDlkm() {
+	// Add a leading slash to paths in modules.dep of android dlkm and vendor ramdisk
+	if ctx.InstallInSystemDlkm() || ctx.InstallInVendorDlkm() || ctx.InstallInOdmDlkm() || ctx.InstallInVendorRamdisk() {
 		finalModulesDep = modulesDep.ReplaceExtension(ctx, "intermediates")
 		ctx.Build(pctx, android.BuildParams{
 			Rule:   addLeadingSlashToPaths,
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 49e6b73..d39c84a 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -327,11 +327,3 @@
         "rustc_linker.py",
     ],
 }
-
-python_binary_host {
-    name: "calculate_directory_hash",
-    main: "calculate_directory_hash.py",
-    srcs: [
-        "calculate_directory_hash.py",
-    ],
-}
diff --git a/scripts/calculate_directory_hash.py b/scripts/calculate_directory_hash.py
deleted file mode 100755
index d4802d8..0000000
--- a/scripts/calculate_directory_hash.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2024 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-"""A tool for calculating the hash of a directory based on file contents and metadata."""
-
-import argparse
-import hashlib
-import os
-import stat
-
-def calculate_hash(directory: str) -> str:
-    """
-    Calculates the hash of a directory, including file contents and metadata.
-
-    Following informations are taken into consideration:
-    * Name: The file or directory name.
-    * File Type: Whether it's a regular file, directory, symbolic link, etc.
-    * Size: The size of the file in bytes.
-    * Permissions: The file's access permissions (read, write, execute).
-    * Content Hash (for files): The SHA-1 hash of the file's content.
-    """
-
-    output = []
-    for root, _, files in os.walk(directory):
-        for file in files:
-            filepath = os.path.join(root, file)
-            file_stat = os.lstat(filepath)
-            stat_info = f"{filepath} {stat.filemode(file_stat.st_mode)} {file_stat.st_size}"
-
-            if os.path.islink(filepath):
-                stat_info += os.readlink(filepath)
-            elif os.path.isfile(filepath):
-                with open(filepath, "rb") as f:
-                    file_hash = hashlib.sha1(f.read()).hexdigest()
-                stat_info += f" {file_hash}"
-
-            output.append(stat_info)
-
-    return hashlib.sha1("\n".join(sorted(output)).encode()).hexdigest()
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser(description="Calculate the hash of a directory.")
-    parser.add_argument("directory", help="Path to the directory")
-    parser.add_argument("output_file", help="Path to the output file")
-    args = parser.parse_args()
-
-    hash_value = calculate_hash(args.directory)
-    with open(args.output_file, "w") as f:
-        f.write(hash_value)