cargo2android: Improve package version logic

If there are multiple packages present in the workspace, attempt
to determine what the current package is by checking the emitted
crate_name value against the package name. If this still fails, a new
`--no-pkg-vers` flag is added to skip this behavior.

Bug: 196803495
Test: New logic finds package if package.name is used for crate_name
Test: New flag prevents emitting the pkg version.
Change-Id: I152e94a0520f09f37622a6cec340ae35842d56ea
diff --git a/scripts/cargo2android.py b/scripts/cargo2android.py
index 11b7010..1c01fc8 100755
--- a/scripts/cargo2android.py
+++ b/scripts/cargo2android.py
@@ -432,19 +432,6 @@
             self.outf_name = self.cargo_dir + '/Android.bp'
             self.main_src = self.main_src[len(self.cargo_dir) + 1:]
 
-        # get the package version from running cargo metadata
-        cargo_metadata = subprocess.run(["cargo", "metadata", "--no-deps"],
-                cwd=os.path.abspath(self.cargo_dir), capture_output=True)
-        if cargo_metadata.returncode:
-            self.errors += ("ERROR: unable to get cargo metadata for package version; return code " +
-                cargo_metadata.returncode + "\n")
-        else:
-            metadata_json = json.loads(cargo_metadata.stdout)
-            if len(metadata_json["packages"]) > 1:
-                self.errors += "ERROR: multiple packages defined, will not output package version"
-            else:
-                self.cargo_pkg_version = metadata_json["packages"][0]["version"]
-
       else:
         self.errors += 'ERROR: unknown ' + arg + '\n'
       i += 1
@@ -467,6 +454,11 @@
         self.errors += 'ERROR: cannot generate both lib and rlib crate types\n'
     if not self.root_pkg:
       self.root_pkg = self.crate_name
+
+    # get the package version from running cargo metadata
+    if not self.runner.args.no_pkg_vers:
+        self.get_pkg_version()
+
     self.device_supported = self.runner.args.device
     self.host_supported = not self.runner.args.no_host
     self.cfgs = sorted(set(self.cfgs))
@@ -481,6 +473,36 @@
     self.module_name = altered_name(self.stem)
     return self
 
+  def get_pkg_version(self):
+    """Attempt to retrieve the package version from the Cargo.toml
+
+    If there is only one package, use its version. Otherwise, try to
+    match the emitted `--crate_name` arg against the package name.
+
+    This may fail in cases where multiple packages are defined (workspaces)
+    and where the package name does not match the emitted crate_name
+    (e.g. [lib.name] is set).
+    """
+    cargo_metadata = subprocess.run(['cargo', 'metadata', '--no-deps'],
+            cwd=os.path.abspath(self.cargo_dir), capture_output=True)
+    if cargo_metadata.returncode:
+        self.errors += ('ERROR: unable to get cargo metadata for package version; ' +
+                'return code ' + cargo_metadata.returncode + '\n')
+    else:
+        metadata_json = json.loads(cargo_metadata.stdout)
+        if len(metadata_json['packages']) > 1:
+            for package in metadata_json['packages']:
+                # package names may contain '-', but is changed to '_' in the crate_name
+                if package['name'].replace('-','_') == self.crate_name:
+                    self.cargo_pkg_version = package['version']
+                    break
+        else:
+            self.cargo_pkg_version = metadata_json['packages'][0]['version']
+
+        if not self.cargo_pkg_version:
+            self.errors += ('ERROR: Unable to retrieve package version; ' +
+                'to disable, run with arg "--no-pkg-vers"\n')
+
   def dump_line(self):
     self.write('\n// Line ' + str(self.line_num) + ' ' + self.line)
 
@@ -1662,6 +1684,11 @@
       default=[],
       help='Make the given libraries (without lib prefixes) whole_static_libs.')
   parser.add_argument(
+      '--no-pkg-vers',
+      action='store_true',
+      default=False,
+      help='Do not attempt to determine the package version automatically.')
+  parser.add_argument(
       '--test-data',
       nargs='*',
       default=[],