lights: Re-write example service in Rust

Add a re-implementation of the Lights HAL example service in Rust. This
was originally written as the start of a Cuttlefish specific
implementation of this service, but it's simple / small enough that
replacing the current Android C++ one with it shouldn't bring in any
trouble while providing yet another Rust service example to the tree.

Tested: built VtsHalLightTargetTest and ran in Cuttlefish
Bug: 286106270
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a796fb113c405838424e61fd0b4cd6e0ef86c5a7)

Change-Id: I01eaf9ce7c6086e1429f52ff4f7f92cebc5360b6
diff --git a/light/aidl/default/Android.bp b/light/aidl/default/Android.bp
index 7920503..285329e 100644
--- a/light/aidl/default/Android.bp
+++ b/light/aidl/default/Android.bp
@@ -7,19 +7,17 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_binary {
+rust_binary {
     name: "android.hardware.lights-service.example",
     relative_install_path: "hw",
     init_rc: ["lights-default.rc"],
     vintf_fragments: ["lights-default.xml"],
     vendor: true,
-    shared_libs: [
-        "libbase",
-        "libbinder_ndk",
-        "android.hardware.light-V2-ndk",
+    rustlibs: [
+        "liblogger",
+        "liblog_rust",
+        "libbinder_rs",
+        "android.hardware.light-V2-rust",
     ],
-    srcs: [
-        "Lights.cpp",
-        "main.cpp",
-    ],
+    srcs: [ "main.rs" ],
 }
diff --git a/light/aidl/default/Lights.cpp b/light/aidl/default/Lights.cpp
deleted file mode 100644
index 9bf3b20..0000000
--- a/light/aidl/default/Lights.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 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 "Lights.h"
-
-#include <android-base/logging.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace light {
-
-static constexpr int kNumDefaultLights = 3;
-
-ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) {
-    LOG(INFO) << "Lights setting state for id=" << id << " to color " << std::hex << state.color;
-    if (id <= 0 || id > kNumDefaultLights) {
-        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-    } else {
-        return ndk::ScopedAStatus::ok();
-    }
-}
-
-ndk::ScopedAStatus Lights::getLights(std::vector<HwLight>* lights) {
-    for (int i = 1; i <= kNumDefaultLights; i++) {
-        lights->push_back({i, i});
-    }
-    LOG(INFO) << "Lights reporting supported lights";
-    return ndk::ScopedAStatus::ok();
-}
-
-}  // namespace light
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/light/aidl/default/Lights.h b/light/aidl/default/Lights.h
deleted file mode 100644
index cba147f..0000000
--- a/light/aidl/default/Lights.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/light/BnLights.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace light {
-
-// Default implementation that reports a few placeholder lights.
-class Lights : public BnLights {
-    ndk::ScopedAStatus setLightState(int id, const HwLightState& state) override;
-    ndk::ScopedAStatus getLights(std::vector<HwLight>* lights) override;
-};
-
-}  // namespace light
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/light/aidl/default/lights.rs b/light/aidl/default/lights.rs
new file mode 100644
index 0000000..60e98d7
--- /dev/null
+++ b/light/aidl/default/lights.rs
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+//! This module implements the ILights AIDL interface.
+
+use log::info;
+
+use android_hardware_light::aidl::android::hardware::light::{
+    HwLight::HwLight, HwLightState::HwLightState, ILights::ILights, LightType::LightType,
+};
+
+use binder::{ExceptionCode, Interface, Status};
+
+/// Defined so we can implement the ILights AIDL interface.
+pub struct LightsService;
+
+impl Interface for LightsService {}
+
+const NUM_DEFAULT_LIGHTS: i32 = 3;
+
+impl ILights for LightsService {
+    fn setLightState(&self, id: i32, state: &HwLightState) -> binder::Result<()> {
+        info!("Lights setting state for id={} to color {:x}", id, state.color);
+        if id <= 0 || id > NUM_DEFAULT_LIGHTS {
+            return Err(Status::new_exception(ExceptionCode::UNSUPPORTED_OPERATION, None));
+        }
+
+        Ok(())
+    }
+
+    fn getLights(&self) -> binder::Result<Vec<HwLight>> {
+        let mut lights: Vec<HwLight> = Vec::with_capacity(NUM_DEFAULT_LIGHTS.try_into().unwrap());
+
+        for i in 1..=NUM_DEFAULT_LIGHTS {
+            let light = HwLight { id: i, ordinal: i, r#type: LightType::BACKLIGHT };
+
+            lights.push(light);
+        }
+
+        info!("Lights reporting supported lights");
+        Ok(lights)
+    }
+}
diff --git a/light/aidl/default/main.cpp b/light/aidl/default/main.cpp
deleted file mode 100644
index 54e1316..0000000
--- a/light/aidl/default/main.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 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 "Lights.h"
-
-#include <android-base/logging.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
-using ::aidl::android::hardware::light::Lights;
-
-int main() {
-    ABinderProcess_setThreadPoolMaxThreadCount(0);
-    std::shared_ptr<Lights> lights = ndk::SharedRefBase::make<Lights>();
-
-    const std::string instance = std::string() + Lights::descriptor + "/default";
-    binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
-    CHECK_EQ(status, STATUS_OK);
-
-    ABinderProcess_joinThreadPool();
-    return EXIT_FAILURE;  // should not reached
-}
diff --git a/light/aidl/default/main.rs b/light/aidl/default/main.rs
new file mode 100644
index 0000000..ffe33fe
--- /dev/null
+++ b/light/aidl/default/main.rs
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+//! This implements the Lights Example Service.
+
+use android_hardware_light::aidl::android::hardware::light::ILights::{BnLights, ILights};
+use binder::BinderFeatures;
+
+mod lights;
+use lights::LightsService;
+
+const LOG_TAG: &str = "lights_service_example_rust";
+
+use log::Level;
+
+fn main() {
+    let logger_success = logger::init(
+        logger::Config::default().with_tag_on_device(LOG_TAG).with_min_level(Level::Trace),
+    );
+    if !logger_success {
+        panic!("{LOG_TAG}: Failed to start logger.");
+    }
+
+    binder::ProcessState::set_thread_pool_max_thread_count(0);
+
+    let lights_service = LightsService;
+    let lights_service_binder = BnLights::new_binder(lights_service, BinderFeatures::default());
+
+    let service_name = format!("{}/default", LightsService::get_descriptor());
+    binder::add_service(&service_name, lights_service_binder.as_binder())
+        .expect("Failed to register service");
+
+    binder::ProcessState::join_thread_pool()
+}