Add hidden_api for java_import

Test: go java tests
Test: m
Bug: 160455085
Change-Id: Ib6e826e32ca73ceea0799b26145ad06b1e62a1bf
diff --git a/java/Android.bp b/java/Android.bp
index e345014..92e8ca4 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -59,6 +59,7 @@
         "device_host_converter_test.go",
         "dexpreopt_test.go",
         "dexpreopt_bootjars_test.go",
+        "hiddenapi_singleton_test.go",
         "java_test.go",
         "jdeps_test.go",
         "kotlin_test.go",
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index ea3fbda..7f1078b 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -163,6 +163,7 @@
 						return
 					}
 				}
+
 				bootDexJars = append(bootDexJars, jar)
 			}
 		}
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
new file mode 100644
index 0000000..bcca93a
--- /dev/null
+++ b/java/hiddenapi_singleton_test.go
@@ -0,0 +1,136 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// 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.
+
+package java
+
+import (
+	"android/soong/android"
+	"strings"
+	"testing"
+)
+
+func testConfigWithBootJars(bp string, bootJars []string) android.Config {
+	config := testConfig(nil, bp, nil)
+	config.TestProductVariables.BootJars = bootJars
+	return config
+}
+
+func testContextWithHiddenAPI() *android.TestContext {
+	ctx := testContext()
+	ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
+	return ctx
+}
+
+func testHiddenAPI(t *testing.T, bp string, bootJars []string) (*android.TestContext, android.Config) {
+	t.Helper()
+
+	config := testConfigWithBootJars(bp, bootJars)
+	ctx := testContextWithHiddenAPI()
+
+	run(t, ctx, config)
+
+	return ctx, config
+}
+
+func TestHiddenAPISingleton(t *testing.T) {
+	ctx, _ := testHiddenAPI(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			compile_dex: true,
+	}
+	`, []string{":foo"})
+
+	hiddenAPI := ctx.SingletonForTests("hiddenapi")
+	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+	want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
+	if !strings.Contains(hiddenapiRule.RuleParams.Command, want) {
+		t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command)
+	}
+}
+
+func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
+	ctx, _ := testHiddenAPI(t, `
+		java_import {
+			name: "foo",
+			jars: ["a.jar"],
+			compile_dex: true,
+	}
+	`, []string{":foo"})
+
+	hiddenAPI := ctx.SingletonForTests("hiddenapi")
+	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+	want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/dex/foo.jar"
+	if !strings.Contains(hiddenapiRule.RuleParams.Command, want) {
+		t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command)
+	}
+}
+
+func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
+	ctx, _ := testHiddenAPI(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			compile_dex: true,
+	}
+
+		java_import {
+			name: "foo",
+			jars: ["a.jar"],
+			compile_dex: true,
+			prefer: false,
+	}
+	`, []string{":foo"})
+
+	hiddenAPI := ctx.SingletonForTests("hiddenapi")
+	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+	fromSourceJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
+	if !strings.Contains(hiddenapiRule.RuleParams.Command, fromSourceJarArg) {
+		t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command)
+	}
+
+	prebuiltJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/dex/foo.jar"
+	if strings.Contains(hiddenapiRule.RuleParams.Command, prebuiltJarArg) {
+		t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", prebuiltJarArg, hiddenapiRule.RuleParams.Command)
+	}
+}
+
+func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
+	ctx, _ := testHiddenAPI(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			compile_dex: true,
+	}
+
+		java_import {
+			name: "foo",
+			jars: ["a.jar"],
+			compile_dex: true,
+			prefer: true,
+	}
+	`, []string{":foo"})
+
+	hiddenAPI := ctx.SingletonForTests("hiddenapi")
+	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+	prebuiltJarArg := "--boot-dex=" + buildDir + "/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
+	if !strings.Contains(hiddenapiRule.RuleParams.Command, prebuiltJarArg) {
+		t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", prebuiltJarArg, hiddenapiRule.RuleParams.Command)
+	}
+
+	fromSourceJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
+	if strings.Contains(hiddenapiRule.RuleParams.Command, fromSourceJarArg) {
+		t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command)
+	}
+}
diff --git a/java/java.go b/java/java.go
index eb88417..2362676 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1611,6 +1611,9 @@
 
 		configurationName := j.ConfigurationName()
 		primary := configurationName == ctx.ModuleName()
+		// If the prebuilt is being used rather than the from source, skip this
+		// module to prevent duplicated classes
+		primary = primary && !j.IsReplacedByPrebuilt()
 
 		// Hidden API CSV generation and dex encoding
 		dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, j.implementationJarFile,
@@ -2681,6 +2684,13 @@
 			return
 		}
 
+		configurationName := j.BaseModuleName()
+		primary := j.Prebuilt().UsePrebuilt()
+
+		// Hidden API CSV generation and dex encoding
+		dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, outputFile,
+			proptools.Bool(j.dexProperties.Uncompress_dex))
+
 		j.dexJarFile = dexOutputFile
 	}
 }
diff --git a/java/testing.go b/java/testing.go
index 1db6ef2..dc8f2a6 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -146,6 +146,7 @@
 				srcs: ["a.java"],
 				sdk_version: "none",
 				system_modules: "stable-core-platform-api-stubs-system-modules",
+				compile_dex: true,
 			}
 		`, extra)
 	}