Add Rust bindings to get the list of HALs.

Test: vintf_test
Change-Id: Ic64b53763a4811c79173cdc585a40ccba956ceb9
diff --git a/keystore2/src/vintf/Android.bp b/keystore2/src/vintf/Android.bp
new file mode 100644
index 0000000..31a1de9
--- /dev/null
+++ b/keystore2/src/vintf/Android.bp
@@ -0,0 +1,69 @@
+// Copyright 2021, 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.
+
+rust_library {
+    name: "libkeystore2_vintf_rust",
+    crate_name: "keystore2_vintf",
+    srcs: ["lib.rs"],
+    rustlibs: [
+        "libkeystore2_vintf_bindgen",
+    ],
+    shared_libs: [
+        "libkeystore2_vintf_cpp",
+        "libvintf",
+    ],
+}
+
+cc_library {
+    name: "libkeystore2_vintf_cpp",
+    srcs: [
+        "vintf.cpp",
+    ],
+    shared_libs: [
+        "libvintf",
+    ],
+}
+
+rust_bindgen {
+    name: "libkeystore2_vintf_bindgen",
+    wrapper_src: "vintf.hpp",
+    crate_name: "keystore2_vintf_bindgen",
+    source_stem: "bindings",
+    host_supported: true,
+    shared_libs: ["libvintf"],
+    bindgen_flags: [
+        "--size_t-is-usize",
+        "--whitelist-function", "getHalNames",
+        "--whitelist-function", "getHalNamesAndVersions",
+        "--whitelist-function", "freeNames",
+    ],
+}
+
+rust_test {
+    name: "keystore2_vintf_test",
+    crate_name: "keystore2_vintf_test",
+    srcs: ["lib.rs"],
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+    rustlibs: [
+        "libkeystore2_vintf_bindgen",
+    ],
+    static_libs: [
+        "libkeystore2_vintf_cpp",
+    ],
+    shared_libs: [
+        "libc++",
+        "libvintf",
+    ],
+}
diff --git a/keystore2/src/vintf/lib.rs b/keystore2/src/vintf/lib.rs
new file mode 100644
index 0000000..3a10ece
--- /dev/null
+++ b/keystore2/src/vintf/lib.rs
@@ -0,0 +1,85 @@
+// Copyright 2021, 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.
+
+//! Bindings for getting the list of HALs.
+
+use keystore2_vintf_bindgen::{freeNames, getHalNames, getHalNamesAndVersions};
+use std::ffi::CStr;
+use std::os::raw::c_char;
+use std::str::Utf8Error;
+
+/// A struct that contains a list of HALs (optionally with version numbers).
+/// To use it, call as_vec to get a Vec view of the data it contains.
+pub struct HalNames {
+    data: *mut *mut c_char,
+    len: usize,
+}
+
+impl Drop for HalNames {
+    fn drop(&mut self) {
+        // Safety: The memory is allocated by our C shim so it must free it as well.
+        unsafe { freeNames(self.data, self.len) }
+    }
+}
+
+impl<'a> HalNames {
+    /// Get a Vec view of the list of HALs.
+    pub fn as_vec(&'a self) -> Result<Vec<&'a str>, Utf8Error> {
+        // Safety: self.data contains self.len C strings.
+        // The lifetimes ensure that the HalNames (and hence the strings) live
+        // at least as long as the returned vector.
+        unsafe { (0..self.len).map(|i| CStr::from_ptr(*self.data.add(i)).to_str()) }.collect()
+    }
+}
+
+/// Gets all HAL names.
+/// Note that this is not a zero-cost shim: it will make copies of the strings.
+pub fn get_hal_names() -> HalNames {
+    let mut len: usize = 0;
+    // Safety: We'll wrap this in HalNames to free the memory it allocates.
+    // It stores the size of the array it returns in len.
+    let raw_strs = unsafe { getHalNames(&mut len) };
+    HalNames { data: raw_strs, len }
+}
+
+/// Gets all HAL names and versions.
+/// Note that this is not a zero-cost shim: it will make copies of the strings.
+pub fn get_hal_names_and_versions() -> HalNames {
+    let mut len: usize = 0;
+    // Safety: We'll wrap this in HalNames to free the memory it allocates.
+    // It stores the size of the array it returns in len.
+    let raw_strs = unsafe { getHalNamesAndVersions(&mut len) };
+    HalNames { data: raw_strs, len }
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+
+    #[test]
+    fn test() -> Result<(), Utf8Error> {
+        let result = get_hal_names();
+        let names = result.as_vec()?;
+        assert_ne!(names.len(), 0);
+
+        let result = get_hal_names_and_versions();
+        let names_and_versions = result.as_vec()?;
+        assert_ne!(names_and_versions.len(), 0);
+
+        assert!(names_and_versions.len() >= names.len());
+
+        Ok(())
+    }
+}
diff --git a/keystore2/src/vintf/vintf.cpp b/keystore2/src/vintf/vintf.cpp
new file mode 100644
index 0000000..1e69e7e
--- /dev/null
+++ b/keystore2/src/vintf/vintf.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "vintf.hpp"
+
+#include <vintf/HalManifest.h>
+#include <vintf/VintfObject.h>
+
+// Converts a set<string> into a C-style array of C strings.
+static char** convert(const std::set<std::string>& names) {
+    char** ret = new char*[names.size()];
+    char** ptr = ret;
+    for (const auto& name : names) {
+        *(ptr++) = strdup(name.c_str());
+    }
+    return ret;
+}
+
+char** getHalNames(size_t* len) {
+    auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+    const auto names = manifest->getHalNames();
+    *len = names.size();
+    return convert(names);
+}
+
+char** getHalNamesAndVersions(size_t* len) {
+    auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+    const auto names = manifest->getHalNamesAndVersions();
+    *len = names.size();
+    return convert(names);
+}
+
+void freeNames(char** names, size_t len) {
+    for (int i = 0; i < len; i++) {
+        free(names[i]);
+    }
+    delete[] names;
+}
diff --git a/keystore2/src/vintf/vintf.hpp b/keystore2/src/vintf/vintf.hpp
new file mode 100644
index 0000000..4d2c905
--- /dev/null
+++ b/keystore2/src/vintf/vintf.hpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#ifndef __VINTF_H__
+#define __VINTF_H__
+
+#include <stddef.h>
+
+extern "C" {
+
+char** getHalNames(size_t* len);
+char** getHalNamesAndVersions(size_t* len);
+void freeNames(char** names, size_t len);
+
+}
+
+#endif  //  __VINTF_H__