rk3588 Android 12 添加framework层服务,HAL库,从硬件驱动层到上层APP,实现led灯控
系列文章目录
rk3588 Android 12 添加framework层服务,HAL库,从硬件驱动层到上层APP,实现led灯控
文章目录
- 系列文章目录
- 一、 驱动适配:
-
- 1.设备树
- 2.设置文件权限
- 3、开启CONFIG_LEDS_PWM
- 二、HAL层
-
- 1.引入库
- 2.打包hal库
- 三、JNI
- 四、framework层服务添加
-
- 1.framework层服务
- 2.添加系统服务权限设置
- 五、app调用
- 总结
一、 驱动适配:
1.设备树
kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588_evb1_*.dtsi
leds_panel {compatible = "pwm-leds";status = "okay";leds-light {pwms = <&pwm6 0 15000 0>;default-brightness = <2>;max-brightness = <100>;};};&pwm6 {pinctrl-0 = <&pwm6m2_pins>;status = "okay";};
kernel-5.10/drivers/leds/leds-pwm.c
static int set_brightness_perms(struct device *dev, struct led_classdev *lcdev)
{struct kobject *kobj = &lcdev->dev->kobj;struct attribute *attr = NULL;struct kobj_type *ktype;int i;int err = -ENOENT;if (!kobj || !kobj->ktype) return err;ktype = kobj->ktype;if (ktype->default_attrs) {for (i = 0; ktype->default_attrs[i] != NULL; i++) {if (strcmp(ktype->default_attrs[i]->name, "brightness") == 0) {attr = ktype->default_attrs[i];break;}}}if (attr) {err = sysfs_chmod_file(kobj, attr, 0644);if (err) {dev_dbg(dev, "Failed to set brightness permissions: %d\n", err);}}return err;
}led_data->pwm = devm_fwnode_pwm_get(dev, fwnode, NULL);if (IS_ERR(led_data->pwm))return dev_err_probe(dev, PTR_ERR(led_data->pwm),"unable to request PWM for %s\n",led->name);if (!fwnode_property_read_u32(fwnode, "default-brightness", &default_brightness)) led_data->cdev.brightness = default_brightness;else led_data->cdev.brightness = 1;set_brightness_perms(dev, &led_data->cdev);
2.设置文件权限
--- a/device/rockchip/common/rootdir/init.rk30board.rc
+++ b/device/rockchip/common/rootdir/init.rk30board.rc
@@ -125,7 +125,10 @@ on boot# backlightchown system system /sys/class/backlight/rk28_bl/brightnesschown system system /sys/class/backlight/backlight/brightness
-
+
+ #leds-panle
+ chown system system /sys/devices/platform/leds_panel/leds/leds-light/brightness
+ # for hdmi
3、开启CONFIG_LEDS_PWM
diff --git a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index b4f9bcc214a..944c4b5345c 100644
--- a/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -5005,7 +5005,7 @@ hdmi0: hdmi@fde80000 {reset-names = "ref", "hdp";power-domains = <&power RK3588_PD_VO1>;pinctrl-names = "default";
- pinctrl-0 = <&hdmim0_tx0_cec &hdmim0_tx0_hpd &hdmim0_tx0_scl &hdmim0_tx0_sda>;
+ pinctrl-0 = <&hdmim0_tx0_hpd &hdmim0_tx0_scl &hdmim0_tx0_sda>;reg-io-width = <4>;rockchip,grf = <&sys_grf>;rockchip,vo1_grf = <&vo1_grf>;
diff --git a/kernel-5.10/arch/arm64/configs/rockchip_defconfig b/kernel-5.10/arch/arm64/configs/rockchip_defconfig
index 4e943597127..1e8cb97119a 100755
--- a/kernel-5.10/arch/arm64/configs/rockchip_defconfig
+++ b/kernel-5.10/arch/arm64/configs/rockchip_defconfig
@@ -1018,3 +1018,5 @@ CONFIG_BUG_ON_DATA_CORRUPTION=yCONFIG_ENABLE_DEFAULT_TRACERS=y# CONFIG_RUNTIME_TESTING_MENU is not setCONFIG_ROCKCHIP_LT9211=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_PWM=y
二、HAL层
1.引入库
hardware/libhardware/modules/light_panel/Android.bp
// Copyright (C) 2013 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.cc_library_shared {name: "light_panel.default",relative_install_path: "hw",proprietary: true,srcs: ["light_panel.c"],cflags: ["-Wall", "-Werror"],header_libs: ["libhardware_headers"],shared_libs: ["liblog"],
}
hardware/libhardware/modules/light_panel/light_panel.c
/** Copyright (C) 2014, 2017-2018 The Linux Foundation. All rights reserved.* Not a contribution* Copyright (C) 2008 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.*/// #define LOG_NDEBUG 0#include <errno.h>
#include <malloc.h>
#include <stdint.h>
#include <string.h>
#include <log/log.h>
#include <hardware/light_panel.h>
#include <hardware/hardware.h>
#include <cutils/properties.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>#include <sys/ioctl.h>
#include <sys/types.h>char const*const LIGHT_PANEL_BRIGHTNESS_CONTROL= "/sys/devices/platform/leds_panel/leds/leds-light/brightness";static int
write_int(char const* path, int value)
{int fd;static int already_warned = 0;ALOGD("leds write_int!!!\n");fd = open(path, O_WRONLY);ALOGD("open file%s\n",strerror(errno));if (fd >= 0) {char buffer[20];int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);ssize_t amt = write(fd, buffer, (size_t)bytes);close(fd);return amt == -1 ? -errno : 0;} else {if (already_warned == 0) {ALOGE("write_int failed to open %s\n", path);already_warned = 0;}return -errno;}
}/** Close the lights device */
static int
close_led(struct light_panel_device_t *dev)
{if (dev) {free(dev);}return 0;
}int set_light_brightness(struct light_panel_device_t* dev,int brightness)
{int err = 0;if(!dev) {return -1;}if(brightness > 255){err = write_int(LIGHT_PANEL_BRIGHTNESS_CONTROL, 255);}else if(brightness < 0){err = write_int(LIGHT_PANEL_BRIGHTNESS_CONTROL, 0);}else {err = write_int(LIGHT_PANEL_BRIGHTNESS_CONTROL, brightness);}return err;
}static int light_panel_device_open(const struct hw_module_t* module, const char* name,struct hw_device_t** device)
{ALOGD("Hello: light_panel_device_open name = %s",name);struct light_panel_device_t *dev = malloc(sizeof(struct light_panel_device_t));if(!dev)return -ENOMEM;memset(dev, 0, sizeof(*dev));//HAL must init propertydev->common.tag= HARDWARE_DEVICE_TAG;dev->common.version = 0;dev->common.module= (hw_module_t*)module;dev->common.close = (int (*)(struct hw_device_t*))close_led;; dev->set_light_brightness= set_light_brightness;// //*device = (struct hw_device_t*)dev;*device = &(dev->common);return 0;
}static struct hw_module_methods_t light_panel_module_methods = {.open = light_panel_device_open
};/** The led Module*/
struct hw_module_t HAL_MODULE_INFO_SYM = {.tag = HARDWARE_MODULE_TAG,.version_major = 1,.version_minor = 0,.id = LIGHT_PANEL_HARDWARE_MODULE_ID,.name = "light_panel HAL module",.author = "vendor_light_panel, Inc.",.methods = &light_panel_module_methods,
};
2.打包hal库
/build/make/target/product/full_base.mk
# audio.a2dp.default is a system module. Generic system image includes# audio.a2dp.default to support A2DP if board has the capability.PRODUCT_PACKAGES += \
- audio.a2dp.default
+ audio.a2dp.default \
+ light_panel.default
diff --git a/hardware/libhardware/modules/Android.mk b/hardware/libhardware/modules/Android.mk
index 9d934c5f9ca..eeedc46678e 100644
--- a/hardware/libhardware/modules/Android.mk
+++ b/hardware/libhardware/modules/Android.mk
@@ -1,5 +1,6 @@hardware_modules := \camera \gralloc \
- sensors
+ sensors \
+ light_panel
三、JNI
/frameworks/base/services/core/jni/com_android_server_LightPanelService.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+#define LOG_TAG "com_android_server_LightPanelService"
+#include "utils/Log.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <hardware/light_panel.h>
+#include <hardware/hardware.h>
+
+namespace android {
+
+ static light_panel_device_t *sLightPanelDevice = NULL;
+
+ static jint set_light_brightness(JNIEnv* env, jobject clazz, jint brightness) {
+ int brightness_val = brightness;
+ ALOGD("Hello JNI: set brightness_val %d to device.", brightness_val);
+ if(!sLightPanelDevice) {
+ ALOGD("Hello JNI: device is not open.");
+ return -1;
+ }
+ sLightPanelDevice->set_light_brightness(sLightPanelDevice,brightness_val);
+ return 0;
+ }
+
+ static inline int light_panel_device_open(const hw_module_t* module, struct light_panel_device_t** device) {
+ return module->methods->open(module, LIGHT_PANEL_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
+ //return module->common.methods->open(&(module->common), LIGHT_PANEL_HARDWARE_MODULE_ID,(struct hw_device_t**)&device));
+ }
+
+ static jint light_panel_init(JNIEnv* env,jobject clazz) {
+ light_panel_module_t* module;
+ ALOGE("Initializing LightPanel HAL...");
+
+ int ret = hw_get_module(LIGHT_PANEL_HARDWARE_MODULE_ID, (const hw_module_t**)&module);
+ if (ret != 0) {
+ ALOGE("Failed to get HAL module (Error %d). Check device HAL implementation.", ret);
+ return -1;
+ }
+
+ ret = light_panel_device_open(&module->common, &sLightPanelDevice);
+ if (ret != 0) {
+ ALOGE("Failed to open device (Error %d). Verify HAL compatibility.", ret);
+ return -1;
+ }
+
+ ALOGE("LightPanel device initialized successfully.");
+ return 0;
+ }
+
+ static const JNINativeMethod method_table[] = {
+ {"init_native", "()I", (void*)light_panel_init},
+ { "set_light_brightness","(I)I",(void*)set_light_brightness},
+ };
+
+ int register_android_server_LightPanelService(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/server/LightPanelService", method_table, NELEM(method_table));
+ }
+};
diff --git a/frameworks/base/services/core/jni/Android.bp b/frameworks/base/services/core/jni/Android.bp
index 57db80bbc7f..9525d8ef596 100644
--- a/frameworks/base/services/core/jni/Android.bp
+++ b/frameworks/base/services/core/jni/Android.bp
@@ -73,6 +73,7 @@ cc_library_static {"com_android_server_sensor_SensorService.cpp","com_android_server_rkdisplay_RkDisplayModes.cpp","com_android_server_audio_RkAudioSetting.cpp",
+ "com_android_server_LightPanelService.cpp","rkbox/rklog.cpp","com_android_server_RKBoxService.cpp","onload.cpp",
diff --git a/frameworks/base/services/core/jni/onload.cpp b/frameworks/base/services/core/jni/onload.cpp
index de3526cf361..a8f47a9cc94 100644
--- a/frameworks/base/services/core/jni/onload.cpp
+++ b/frameworks/base/services/core/jni/onload.cpp
@@ -66,6 +66,7 @@ int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env);int register_com_android_server_rkdisplay_RkDisplayModes(JNIEnv* env);int register_com_android_server_audio_RkAudioSetting(JNIEnv* env);int register_com_android_server_RKBoxManagementService(JNIEnv* env);
+int register_android_server_LightPanelService(JNIEnv* env);};using namespace android;
@@ -125,5 +126,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)register_com_android_server_rkdisplay_RkDisplayModes(env);register_com_android_server_audio_RkAudioSetting(env);register_com_android_server_RKBoxManagementService(env);
+ register_android_server_LightPanelService(env);return JNI_VERSION_1_4;}
四、framework层服务添加
1.framework层服务
diff --git a/frameworks/base/Android.bp b/frameworks/base/Android.bp
index a99cef87938..d69d338edcd 100644
--- a/frameworks/base/Android.bp
+++ b/frameworks/base/Android.bp
@@ -496,7 +496,8 @@ metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.x"--api-lint-ignore-prefix android.icu. " +"--api-lint-ignore-prefix java. " +"--api-lint-ignore-prefix junit. " +
- "--api-lint-ignore-prefix org. "
+ "--api-lint-ignore-prefix org. " +
+ "--api-lint-ignore-prefix android. "packages_to_document = ["android",
diff --git a/frameworks/base/core/api/current.txt b/frameworks/base/core/api/current.txt
index 84e8e5e69ce..8556dd63d8e 100644
--- a/frameworks/base/core/api/current.txt
+++ b/frameworks/base/core/api/current.txt
@@ -5378,6 +5378,26 @@ package android.app {field public static final int GAME_MODE_UNSUPPORTED = 0; // 0x0}+ public interface ILightPanelService extends android.os.IInterface {
+ method public void setLightPanelBrightness(int) throws android.os.RemoteException;
+ field public static final String DESCRIPTOR = "android.app.ILightPanelService";
+ }
+
+ public static class ILightPanelService.Default implements android.app.ILightPanelService {
+ ctor public ILightPanelService.Default();
+ method public android.os.IBinder asBinder();
+ method public void setLightPanelBrightness(int) throws android.os.RemoteException;
+ }
+
+ public abstract static class ILightPanelService.Stub extends android.os.Binder implements android.app.ILightPanelService {
+ ctor public ILightPanelService.Stub();
+ method public android.os.IBinder asBinder();
+ method public static android.app.ILightPanelService asInterface(android.os.IBinder);
+ method public static android.app.ILightPanelService getDefaultImpl();
+ method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+ method public static boolean setDefaultImpl(android.app.ILightPanelService);
+ }
+public class Instrumentation {ctor public Instrumentation();method public android.os.TestLooperManager acquireLooperManager(android.os.Looper);
@@ -5533,6 +5553,12 @@ package android.app {field @Deprecated public android.content.pm.ResolveInfo resolveInfo;}+ public class LightPanelManager {
+ ctor public LightPanelManager(android.content.Context, android.app.ILightPanelService);
+ method public static android.app.LightPanelManager getInstance(android.content.Context);
+ method public void setLightPanelBrightness(int);
+ }
+@Deprecated public class ListActivity extends android.app.Activity {ctor @Deprecated public ListActivity();method @Deprecated public android.widget.ListAdapter getListAdapter();
@@ -10658,6 +10684,7 @@ package android.content {field public static final String KEYGUARD_SERVICE = "keyguard";field public static final String LAUNCHER_APPS_SERVICE = "launcherapps";field @UiContext public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
+ field public static final String LIGHTPANEL_SERVICE = "lightpanel";field public static final String LOCATION_SERVICE = "location";field public static final String MEDIA_COMMUNICATION_SERVICE = "media_communication";field public static final String MEDIA_METRICS_SERVICE = "media_metrics";
diff --git a/frameworks/base/core/java/android/app/ILightPanelService.aidl b/frameworks/base/core/java/android/app/ILightPanelService.aidl
new file mode 100755
index 00000000000..54b494a73aa
--- /dev/null
+++ b/frameworks/base/core/java/android/app/ILightPanelService.aidl
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2012, 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. HelloService
+ */
+
+package android.app;
+
+interface ILightPanelService {
+ void setLightPanelBrightness(int brightness);
+}
diff --git a/frameworks/base/core/java/android/app/LightPanelManager.java b/frameworks/base/core/java/android/app/LightPanelManager.java
new file mode 100755
index 00000000000..bb0e6ff8300
--- /dev/null
+++ b/frameworks/base/core/java/android/app/LightPanelManager.java
@@ -0,0 +1,44 @@
+package android.app;
+
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.os.ServiceManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.app.ILightPanelService;
+import android.util.Log;
+
+
+@SystemService(Context.LIGHTPANEL_SERVICE)
+public class LightPanelManager {
+ private static final String TAG = "LightPanelManager";
+ private final ILightPanelService mService;
+
+ // 公开构造函数,供系统内部使用
+ public LightPanelManager(Context context, ILightPanelService service) {
+ mService = service;
+ }
+
+ // 提供静态获取方法,无需隐藏
+ public static LightPanelManager getInstance(Context context) {
+ ILightPanelService service = ILightPanelService.Stub.asInterface(
+ ServiceManager.getService(Context.LIGHTPANEL_SERVICE)
+ );
+ return new LightPanelManager(context, service);
+ }
+
+ // 公开亮度设置方法
+ public void setLightPanelBrightness(int brightness) {
+ try {
+ mService.setLightPanelBrightness(brightness);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed to set brightness", e);
+ }
+ }
+}
+
diff --git a/frameworks/base/core/java/android/app/SystemServiceRegistry.java b/frameworks/base/core/java/android/app/SystemServiceRegistry.java
index 32ea41b2c75..deb8b0fa0c1 100644
--- a/frameworks/base/core/java/android/app/SystemServiceRegistry.java
+++ b/frameworks/base/core/java/android/app/SystemServiceRegistry.java
@@ -47,6 +47,8 @@ import android.app.usage.IUsageStatsManager;import android.app.usage.NetworkStatsManager;import android.app.usage.StorageStatsManager;import android.app.usage.UsageStatsManager;
+import android.app.ILightPanelService;
+import android.app.LightPanelManager;import android.apphibernation.AppHibernationManager;import android.appwidget.AppWidgetManager;import android.bluetooth.BluetoothManager;
@@ -1469,7 +1471,15 @@ public final class SystemServiceRegistry {public DisplayHashManager createService(ContextImpl ctx) {return new DisplayHashManager();}});
-
+ registerService(Context.LIGHTPANEL_SERVICE, LightPanelManager.class,
+ new CachedServiceFetcher<LightPanelManager>() {
+ @Override
+ public LightPanelManager createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(Context.LIGHTPANEL_SERVICE);
+ ILightPanelService service = ILightPanelService.Stub.asInterface(b);
+ return new LightPanelManager(ctx, service);
+ }});
+ sInitializing = true;try {// Note: the following functions need to be @SystemApis, once they become mainline
diff --git a/frameworks/base/core/java/android/content/Context.java b/frameworks/base/core/java/android/content/Context.java
index 913c3b8a33c..02ae318e9e2 100644
--- a/frameworks/base/core/java/android/content/Context.java
+++ b/frameworks/base/core/java/android/content/Context.java
@@ -3728,6 +3728,7 @@ public abstract class Context {//@hide: SPEECH_RECOGNITION_SERVICE,UWB_SERVICE,MEDIA_METRICS_SERVICE,
+ LIGHTPANEL_SERVICE,})@Retention(RetentionPolicy.SOURCE)public @int