zenfone6: Import binderized lights HAL
* Remove blue led support
Change-Id: Ibac971507e6e95ad9d558a3eb45c4edf5c37552d
diff --git a/device.mk b/device.mk
index 0d46c67..317f9a1 100755
--- a/device.mk
+++ b/device.mk
@@ -112,6 +112,10 @@
VisualizationWallpapers \
librs_jni
+# Lights
+PRODUCT_PACKAGES += \
+ android.hardware.light@2.0-service.asus_msmnile
+
# Media
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/configs/media_profiles_vendor.xml:system/etc/media_profiles_vendor.xml
diff --git a/lights/.clang-format b/lights/.clang-format
new file mode 100644
index 0000000..ae4a451
--- /dev/null
+++ b/lights/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/lights/Android.bp b/lights/Android.bp
new file mode 100644
index 0000000..30e9a1e
--- /dev/null
+++ b/lights/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2018 The LineageOS 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.
+
+cc_binary {
+ relative_install_path: "hw",
+ defaults: ["hidl_defaults"],
+ name: "android.hardware.light@2.0-service.asus_msmnile",
+ init_rc: ["android.hardware.light@2.0-service.asus_msmnile.rc"],
+ srcs: ["service.cpp", "Light.cpp"],
+ shared_libs: [
+ "android.hardware.light@2.0",
+ "libbase",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/lights/Light.cpp b/lights/Light.cpp
new file mode 100644
index 0000000..e4178e7
--- /dev/null
+++ b/lights/Light.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2014, 2017-2018 The Linux Foundation. All rights reserved.
+ * Not a contribution
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2018-2019 The LineageOS 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.
+ */
+
+#define LOG_TAG "LightsService"
+
+#include "Light.h"
+#include <android-base/logging.h>
+#include <fstream>
+
+namespace {
+/*
+ * Write value to path and close file.
+ */
+template <typename T>
+static void set(const std::string& path, const T& value) {
+ std::ofstream file(path);
+
+ if (!file.is_open()) {
+ LOG(DEBUG) << "failed to open path " << path;
+ return;
+ }
+
+ file << value;
+
+ if (file.fail()) {
+ LOG(DEBUG) << "failed to write " << value
+ << "to " << path;
+ }
+}
+
+/*
+ * Read from path and close file.
+ * Return def in case of any failure.
+ */
+template <typename T>
+static T get(const std::string& path, const T& def) {
+ std::ifstream file(path);
+ T result;
+
+ if (!file.is_open()) {
+ LOG(DEBUG) << "failed to open path " << path;
+ return def;
+ }
+
+ file >> result;
+
+ if (file.fail()) {
+ LOG(DEBUG) << "failed to read from " << path;
+ return def;
+ }
+
+ return result;
+}
+} // anonymous namespace
+
+namespace android {
+namespace hardware {
+namespace light {
+namespace V2_0 {
+namespace implementation {
+
+static constexpr int kDefaultMaxBrightness = 255;
+static constexpr char kBreath[] = "breath";
+static constexpr char kBrightness[] = "brightness";
+static constexpr char kDelayOff[] = "delay_off";
+static constexpr char kDelayOn[] = "delay_on";
+
+static uint32_t rgbToBrightness(const LightState& state) {
+ uint32_t color = state.color & 0x00ffffff;
+ return ((77 * ((color >> 16) & 0xff))
+ + (150 * ((color >> 8) & 0xff))
+ + (29 * (color & 0xff))) >> 8;
+}
+
+Light::Light() {
+ mLights.emplace(Type::ATTENTION, std::bind(&Light::handleNotification, this, std::placeholders::_1, 0));
+ mLights.emplace(Type::BACKLIGHT, std::bind(&Light::handleBacklight, this, std::placeholders::_1));
+ mLights.emplace(Type::BATTERY, std::bind(&Light::handleNotification, this, std::placeholders::_1, 1));
+ mLights.emplace(Type::NOTIFICATIONS, std::bind(&Light::handleNotification, this, std::placeholders::_1, 2));
+}
+
+void Light::handleBacklight(const LightState& state) {
+ uint32_t maxBrightness = get("/sys/class/backlight/panel0-backlight/max_brightness", kDefaultMaxBrightness);
+ uint32_t sentBrightness = rgbToBrightness(state);
+ uint32_t brightness = sentBrightness * maxBrightness / kDefaultMaxBrightness;
+ LOG(DEBUG) << "Writing backlight brightness " << brightness
+ << " (orig " << sentBrightness << ")";
+ set("/sys/class/backlight/panel0-backlight/brightness", brightness);
+}
+
+void Light::handleNotification(const LightState& state, size_t index) {
+ mLightStates.at(index) = state;
+
+ LightState stateToUse = mLightStates.front();
+ for (const auto& lightState : mLightStates) {
+ if (lightState.color & 0xffffff) {
+ stateToUse = lightState;
+ break;
+ }
+ }
+
+ // Extract brightness from AARRGG
+ uint32_t alpha = (stateToUse.color >> 24) & 0xff;
+
+ std::map<std::string, int> colorValues;
+ colorValues["red"] = (stateToUse.color >> 16) & 0xff;
+ colorValues["green"] = (stateToUse.color >> 8) & 0xff;
+
+ // Scale RG colors if a brightness has been applied by the user
+ if (alpha != 0xff) {
+ for (auto& entry : colorValues) {
+ // For more exact scaling divide by half
+ entry.second = ((entry.second * alpha) / 0xff) / 2;
+ }
+ }
+
+ auto makeLedPath = [](const std::string& led, const char op[]) -> std::string {
+ return "/sys/class/leds/" + led + "/" + op;
+ };
+
+ // Disable all blinking before starting
+ for (const auto& entry : colorValues) {
+ set(makeLedPath(entry.first, kBreath), 0);
+ }
+
+ if (state.flashMode == Flash::TIMED) {
+ for (const auto& entry : colorValues) {
+ set(makeLedPath(entry.first, kDelayOff), state.flashOffMs);
+ set(makeLedPath(entry.first, kDelayOn), state.flashOnMs);
+ }
+
+ // Start blinking
+ for (const auto& entry : colorValues) {
+ set(makeLedPath(entry.first, kBreath), entry.second);
+ }
+ } else {
+ for (const auto& entry : colorValues) {
+ set(makeLedPath(entry.first, kBrightness), entry.second);
+ }
+ }
+}
+
+Return<Status> Light::setLight(Type type, const LightState& state) {
+ auto it = mLights.find(type);
+
+ if (it == mLights.end()) {
+ return Status::LIGHT_NOT_SUPPORTED;
+ }
+
+ // Lock global mutex until light state is updated.
+ std::lock_guard<std::mutex> lock(mLock);
+
+ it->second(state);
+
+ return Status::SUCCESS;
+}
+
+Return<void> Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb) {
+ std::vector<Type> types;
+
+ for (auto const& light : mLights) {
+ types.push_back(light.first);
+ }
+
+ _hidl_cb(types);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace light
+} // namespace hardware
+} // namespace android
diff --git a/lights/Light.h b/lights/Light.h
new file mode 100644
index 0000000..a19d6e6
--- /dev/null
+++ b/lights/Light.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The LineageOS 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 ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
+#define ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
+
+#include <android/hardware/light/2.0/ILight.h>
+#include <hardware/lights.h>
+#include <hidl/Status.h>
+#include <unordered_map>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace light {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::light::V2_0::ILight;
+using ::android::hardware::light::V2_0::LightState;
+using ::android::hardware::light::V2_0::Status;
+using ::android::hardware::light::V2_0::Type;
+
+class Light : public ILight {
+ public:
+ Light();
+
+ Return<Status> setLight(Type type, const LightState& state) override;
+ Return<void> getSupportedTypes(getSupportedTypes_cb _hidl_cb) override;
+
+ private:
+ void handleBacklight(const LightState& state);
+ void handleNotification(const LightState& state, size_t index);
+
+ std::mutex mLock;
+ std::unordered_map<Type, std::function<void(const LightState&)>> mLights;
+ std::array<LightState, 3> mLightStates;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace light
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
diff --git a/lights/android.hardware.light@2.0-service.asus_msmnile.rc b/lights/android.hardware.light@2.0-service.asus_msmnile.rc
new file mode 100644
index 0000000..22e6708
--- /dev/null
+++ b/lights/android.hardware.light@2.0-service.asus_msmnile.rc
@@ -0,0 +1,7 @@
+service vendor.light-hal-2-0 /system/bin/hw/android.hardware.light@2.0-service.asus_msmnile
+ interface android.hardware.light@2.0::ILight default
+ class hal
+ user system
+ group system
+ # shutting off lights while powering-off
+ shutdown critical
diff --git a/lights/service.cpp b/lights/service.cpp
new file mode 100644
index 0000000..423263d
--- /dev/null
+++ b/lights/service.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The LineageOS 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.
+ */
+
+#define LOG_TAG "android.hardware.light@2.0-service.asus_msmnile"
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "Light.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+using android::hardware::light::V2_0::ILight;
+using android::hardware::light::V2_0::implementation::Light;
+
+using android::OK;
+using android::sp;
+using android::status_t;
+
+int main() {
+ status_t status;
+ sp<ILight> service = nullptr;
+
+ LOG(INFO) << "Light HAL service 2.0 is starting.";
+
+ service = new Light();
+ if (service == nullptr) {
+ LOG(ERROR) << "Can not create an instance of Light HAL Iface, exiting.";
+ goto shutdown;
+ }
+
+ configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+ status = service->registerAsService();
+ if (status != OK) {
+ LOG(ERROR) << "Could not register service for Light HAL Iface (" << status << ")";
+ goto shutdown;
+ }
+
+ LOG(INFO) << "Light HAL service is ready.";
+ joinRpcThreadpool();
+ // Should not pass this line
+
+shutdown:
+ // In normal operation, we don't expect the thread pool to exit
+ LOG(ERROR) << "Light HAL service is shutting down.";
+ return 1;
+}
diff --git a/sepolicy/private/file.te b/sepolicy/private/file.te
index 28fcbe5..df8c2d3 100644
--- a/sepolicy/private/file.te
+++ b/sepolicy/private/file.te
@@ -4,6 +4,10 @@
type voucher_file, file_type;
type xrom_file, file_type;
+# Lights
+type sysfs_rg_led, sysfs_type, fs_type;
+type sysfs_graphics, sysfs_type, fs_type;
+
# Offscreen Gestures
type sysfs_gesture, sysfs_type, fs_type;
type sysfs_touchscreen, sysfs_type, fs_type;
diff --git a/sepolicy/private/file_contexts b/sepolicy/private/file_contexts
index 983ceba..b52c919 100644
--- a/sepolicy/private/file_contexts
+++ b/sepolicy/private/file_contexts
@@ -15,5 +15,8 @@
/proc/driver/swipeup u:object_r:sysfs_gesture:s0
/sys/devices/platform/soc/soc:asustek_googlekey/googlekey_enable u:object_r:sysfs_gesture:s0
+# HALs
+/system/bin/hw/android\.hardware\.light@2\.0-service\.asus_msmnile u:object_r:hal_light_msmnile_exec:s0
+
# Modules
/system/lib/modules/wlan\.ko u:object_r:system_file:s0
diff --git a/sepolicy/private/hal_light_msmnile.te b/sepolicy/private/hal_light_msmnile.te
new file mode 100644
index 0000000..140f1e2
--- /dev/null
+++ b/sepolicy/private/hal_light_msmnile.te
@@ -0,0 +1,20 @@
+type hal_light_msmnile, coredomain, domain;
+
+# Allow a base set of permissions required for a domain to offer a
+# HAL implementation of the specified type over HwBinder.
+typeattribute hal_light_msmnile halclientdomain;
+typeattribute hal_light_msmnile hal_light_client;
+
+# HwBinder IPC from client to server, and callbacks
+binder_call(hal_light_client, hal_light_server)
+binder_call(hal_light_server, hal_light_client)
+
+add_hwservice(hal_light_server, hal_light_hwservice)
+allow hal_light_client hal_light_hwservice:hwservice_manager find;
+
+type hal_light_msmnile_exec, exec_type, file_type;
+init_daemon_domain(hal_light_msmnile)
+
+allow hal_light_msmnile { sysfs_graphics sysfs_rg_led }:lnk_file read;
+allow hal_light_msmnile { sysfs_graphics sysfs_rg_led }:file rw_file_perms;
+allow hal_light_msmnile { sysfs_graphics sysfs_leds sysfs_rg_led }:dir r_dir_perms;