Add option to use protobuf3

Users of the rust_protobuf module can use the 'use_protobuf3'
option to select version 3 of the protobuf crate instead of the
current default of version 2. This unblocks teams that would like
to use protobuf 3 immediately and provides a mechanism for us to
incrementally migrate users of protobuf 2 to protobuf 3.

Test: Adds tests that are executed during every build.
Bug: 270895633
Change-Id: Ib6a18b77cfa7dc3cc604cea05269004b3712bbb6
diff --git a/rust/protobuf.go b/rust/protobuf.go
index e30f25d..0cf6e8c 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -52,6 +52,10 @@
 
 	// List of libraries which export include paths required for this module
 	Header_libs []string `android:"arch_variant,variant_prepend"`
+
+	// Use protobuf version 3.x. This will be deleted once we migrate all current users
+	// of protobuf off of 2.x.
+	Use_protobuf3 *bool
 }
 
 type protobufDecorator struct {
@@ -65,6 +69,10 @@
 	protoFlags     android.ProtoFlags
 }
 
+func (proto *protobufDecorator) useProtobuf3() bool {
+	return Bool(proto.Properties.Use_protobuf3)
+}
+
 func (proto *protobufDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
 	var protoFlags android.ProtoFlags
 	var grpcProtoFlags android.ProtoFlags
@@ -73,7 +81,13 @@
 	outDir := android.PathForModuleOut(ctx)
 	protoFiles := android.PathsForModuleSrc(ctx, proto.Properties.Protos)
 	grpcFiles := android.PathsForModuleSrc(ctx, proto.Properties.Grpc_protos)
+
+	// For now protobuf2 (the deprecated version) remains the default. This will change in the
+	// future as we update the various users.
 	protoPluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust-deprecated")
+	if proto.useProtobuf3() == true {
+		protoPluginPath = ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+	}
 
 	commonProtoFlags = append(commonProtoFlags, defaultProtobufFlags...)
 	commonProtoFlags = append(commonProtoFlags, proto.Properties.Proto_flags...)
@@ -206,10 +220,20 @@
 
 func (proto *protobufDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
 	deps = proto.BaseSourceProvider.SourceProviderDeps(ctx, deps)
-	deps.Rustlibs = append(deps.Rustlibs, "libprotobuf_deprecated")
+	useProtobuf3 := proto.useProtobuf3()
+	if useProtobuf3 == true {
+		deps.Rustlibs = append(deps.Rustlibs, "libprotobuf")
+	} else {
+		deps.Rustlibs = append(deps.Rustlibs, "libprotobuf_deprecated")
+	}
 	deps.HeaderLibs = append(deps.SharedLibs, proto.Properties.Header_libs...)
 
 	if len(proto.Properties.Grpc_protos) > 0 {
+		if useProtobuf3 == true {
+			ctx.PropertyErrorf("protos", "rust_protobuf with grpc_protos defined must currently use "+
+				"`use_protobuf3: false,` in the Android.bp file. This is temporary until the "+
+				"grpcio crate is updated to use the current version of the protobuf crate.")
+		}
 		deps.Rustlibs = append(deps.Rustlibs, "libgrpcio", "libfutures")
 		deps.HeaderLibs = append(deps.HeaderLibs, "libprotobuf-cpp-full")
 	}