Allow modules to disable stripping when dexpreopting

Add a no_stripping property and pass it to dexpreopt to disable
stripping for a module.

Bug: 122610462
Test: dexpreopt_test.go
Change-Id: I5a4b005633bb8b1ea373e9eeb420aa0999de17ab
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 13a14f4..6b5c40d 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -113,6 +113,7 @@
 
 	PresignedPrebuilt bool
 
+	NoStripping     bool
 	StripInputPath  string
 	StripOutputPath string
 }
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 8f45303..f316be4 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -454,6 +454,10 @@
 		strip = false
 	}
 
+	if module.NoStripping {
+		strip = false
+	}
+
 	// Don't strip modules that are not on the system partition in case the oat/vdex version in system ROM
 	// doesn't match the one in other partitions. It needs to be able to fall back to the APK for that case.
 	if !strings.HasPrefix(module.DexLocation, SystemPartition) {
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index fef85a7..f218d01 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -82,6 +82,7 @@
 	NoCreateAppImage:       false,
 	ForceCreateAppImage:    false,
 	PresignedPrebuilt:      false,
+	NoStripping:            false,
 	StripInputPath:         "",
 	StripOutputPath:        "",
 }
@@ -162,47 +163,60 @@
 }
 
 func TestStripDex(t *testing.T) {
-	global, module := testGlobalConfig, testModuleConfig
-
-	module.Name = "test"
-	module.DexLocation = "/system/app/test/test.apk"
-	module.BuildPath = "out/test/test.apk"
-	module.Archs = []string{"arm"}
-	module.StripInputPath = "$1"
-	module.StripOutputPath = "$2"
-
-	rule, err := GenerateStripRule(global, module)
-	if err != nil {
-		t.Error(err)
+	tests := []struct {
+		name  string
+		setup func(global *GlobalConfig, module *ModuleConfig)
+		strip bool
+	}{
+		{
+			name:  "default strip",
+			setup: func(global *GlobalConfig, module *ModuleConfig) {},
+			strip: true,
+		},
+		{
+			name:  "global no stripping",
+			setup: func(global *GlobalConfig, module *ModuleConfig) { global.DefaultNoStripping = true },
+			strip: false,
+		},
+		{
+			name:  "module no stripping",
+			setup: func(global *GlobalConfig, module *ModuleConfig) { module.NoStripping = true },
+			strip: false,
+		},
 	}
 
-	want := `zip2zip -i $1 -o $2 -x "classes*.dex"`
-	if len(rule.Commands()) < 1 || !strings.Contains(rule.Commands()[0], want) {
-		t.Errorf("\nwant commands[0] to have:\n   %v\ngot:\n   %v", want, rule.Commands()[0])
-	}
-}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
 
-func TestNoStripDex(t *testing.T) {
-	global, module := testGlobalConfig, testModuleConfig
+			global, module := testGlobalConfig, testModuleConfig
 
-	global.DefaultNoStripping = true
+			module.Name = "test"
+			module.DexLocation = "/system/app/test/test.apk"
+			module.BuildPath = "out/test/test.apk"
+			module.Archs = []string{"arm"}
+			module.StripInputPath = "$1"
+			module.StripOutputPath = "$2"
 
-	module.Name = "test"
-	module.DexLocation = "/system/app/test/test.apk"
-	module.BuildPath = "out/test/test.apk"
-	module.Archs = []string{"arm"}
-	module.StripInputPath = "$1"
-	module.StripOutputPath = "$2"
+			test.setup(&global, &module)
 
-	rule, err := GenerateStripRule(global, module)
-	if err != nil {
-		t.Error(err)
-	}
+			rule, err := GenerateStripRule(global, module)
+			if err != nil {
+				t.Error(err)
+			}
 
-	wantCommands := []string{
-		"cp -f $1 $2",
-	}
-	if !reflect.DeepEqual(rule.Commands(), wantCommands) {
-		t.Errorf("\nwant commands:\n   %v\ngot:\n   %v", wantCommands, rule.Commands())
+			if test.strip {
+				want := `zip2zip -i $1 -o $2 -x "classes*.dex"`
+				if len(rule.Commands()) < 1 || !strings.Contains(rule.Commands()[0], want) {
+					t.Errorf("\nwant commands[0] to have:\n   %v\ngot:\n   %v", want, rule.Commands()[0])
+				}
+			} else {
+				wantCommands := []string{
+					"cp -f $1 $2",
+				}
+				if !reflect.DeepEqual(rule.Commands(), wantCommands) {
+					t.Errorf("\nwant commands:\n   %v\ngot:\n   %v", wantCommands, rule.Commands())
+				}
+			}
+		})
 	}
 }
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index ce51aba..2c8de55 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -43,6 +43,9 @@
 		// true.
 		Enabled *bool
 
+		// If true, never strip the dex files from the final jar when dexpreopting.  Defaults to false.
+		No_stripping *bool
+
 		// If true, generate an app image (.art file) for this module.
 		App_image *bool
 
@@ -171,6 +174,7 @@
 		NoCreateAppImage:    !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
 		ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
 
+		NoStripping:     Bool(d.dexpreoptProperties.Dex_preopt.No_stripping),
 		StripInputPath:  dexJarFile.String(),
 		StripOutputPath: strippedDexJarFile.String(),
 	}