LED灯系统架构(基于google源码分析)
- 假如系统有好几个灯,需要根据id来选择要亮的灯,我们需要修改hal层代码添加一个接口
hardware/interfaces/light/2.0/default/Light.cpp
light_state_t legacyState {
.ledId = state.ledId,
hardware/interfaces/+/474/1/light/2.0/types.hal
truct LightState {
uint32_t ledId;
hardware/libhardware/include/hardware/lights.h
struct light_state_t {
unsigned int ledId;
这个时候去编译,会编译报错,因为要更新api,根据报错信息修改
添加接口后会报错
c++_headers/gen -L c++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.light@2.0
ERROR: android.hardware.light@2.0::types has hash 6449fbfe75742a10327e8abf89d7f0855ef4c726246f3926078ec8371bb667ec which does not match hash on record. This interface has been frozen. Do not change it!
ERROR: Could not parse android.hardware.light@2.0::types. Abor
将刚刚得到的新 hashcode 值更新到 hardware/interfaces/current.txt 重新编译即可
单独编译模块或者全编译 会出现一个VNDk异常的报错
make android.hardware.light@2.0 -j24
make android.hardware.light@2.0-impl -j24
[ 92% 36/39] //hardware/interfaces/light/2.0:android.hardware.light@2.0 header-abi-diff android.hardware.light@2.0.so.abidiff
FAILED: out/soong/.intermediates/hardware/interfaces/light/2.0/android.hardware.light@2.0/android_arm64_armv8-a_kryo300_vendor_shared/android.hardware.light@2.0.so.abidiff
(prebuilts/clang-tools/linux-x86/bin/header-abi-diff -allow-unreferenced-changes -allow-unreferenced-elf-symbol-changes -lib android.hardware.light@2.0 -arch arm64 -o 'out/soong/.intermediates/hardware/interfaces/light/2.0/android.hardware.light@2.0/android_arm64_armv8-a_kryo300_vendor_shared/android.hardware.light@2.0.so.abidiff' -new 'out/soong/.intermediates/hardware/interfaces/light/2.0/android.hardware.light@2.0/android_arm64_armv8-a_kryo300_vendor_shared/android.hardware.light@2.0.so.lsdump' -old prebuilts/abi-dumps/vndk/29/64/arm64_armv8-a/source-based/android.hardware.light@2.0.so.lsdump)|| (echo 'error: Please update ABI references with: $ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l android.hardware.light@2.0' && (mkdir -p $DIST_DIR/abidiffs && cp 'out/soong/.intermediates/hardware/interfaces/light/2.0/android.hardware.light@2.0/android_arm64_armv8-a_kryo300_vendor_shared/android.hardware.light@2.0.so.abidiff' $DIST_DIR/abidiffs/) && exit 1)
******************************************************
error: VNDK library: android.hardware.light@2.0's ABI has INCOMPATIBLE CHANGES Please check compatibility report at: out/soong/.intermediates/hardware/interfaces/light/2.0/android.hardware.light@2.0/android_arm64_armv8-a_kryo300_vendor_shared/android.hardware.light@2.0.so.abidiff
******************************************************
error: Please update ABI references with: $ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l android.hardware.light@2.0
15:57:58 ninja failed with: exit status 1
解决:
development/vndk/tools/header-checker/utils/create_reference_dumps.py -l android.hardware.light@2.0 -products kona
development/vndk/tools/header-checker/utils/create_reference_dumps.py -product kona
log:
Creating dumps for target_arch: arm and variant armv8-2a
Created abi dump at /prebuilts/abi-dumps/vndk/29/64/arm_armv8-2a/source-based/android.hardware.light@2.0.so.lsdump
Creating dumps for target_arch: arm64 and variant armv8-a
Created abi dump at /prebuilts/abi-dumps/vndk/29/64/arm64_armv8-a/source-based/android.hardware.light@2.0.so.lsdump
再make 还是报错
问题原因 .soon下面的缓存没clean
rm -rf out/soong/.intermediates/hardware/interfaces/light 重新编译后正常
单独模块验证:
make android.hardware.light@2.0-impl -j24
make android.hardware.light@2.0 -j24
adb push system\lib64\vndk-29\android.hardware.light@2.0.so system/lib64/vndk-29/
adb push system\lib\vndk-29\android.hardware.light@2.0.so system/lib/vndk-29/
adb push vendor\lib\hw\android.hardware.light@2.0-impl.so vendor/lib/hw
adb push vendor\lib64\hw\android.hardware.light@2.0-impl.so vendor/lib64/hw
- liblight的具体实现 代码路径 hardware\qcom\display\liblight
编译模块 make lights.kona -j24
从hal接口传下来的ledId 就保存在light_state_t 中
static struct hw_module_methods_t lights_module_methods = {
.open = open_lights,
};
static int open_lights(const struct hw_module_t* module, char const* name,
struct hw_device_t** device)
{
int (*set_light)(struct light_device_t* dev,
struct light_state_t const* state);
if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {
g_has_persistence_node = !access(PERSISTENCE_FILE, F_OK);
set_light = set_light_backlight;
} else if (0 == strcmp(LIGHT_ID_BATTERY, name))
set_light = set_light_battery;
}
/**
* The parameters that can be set for a given light.
*
* Not all lights must support all parameters. If you
* can do something backward-compatible, you should.
*/
struct light_state_t {
unsigned int ledId;
unsigned int batteryState;
}
本文只展示google开源代码,具体实现不便展示
- hal层代码接口以及实现已经加好了,接下来看上层如何调用
1、jni 添加接口
frameworks\base\services\core\jni\com_android_server_lights_LightsService.cpp
static void setLight_native(
JNIEnv* /* env */,
jobject /* clazz */,
jint light,
jint ledId,
jint batteryState,
jint colorARGB,
jint flashMode,
jint onMS,
jint offMS,
jint brightnessMode) {
if (!sLightSupported) {
2、frameworks\base\services\core\java\com\android\server\lights\LightsService.java
static native void setLight_native(int light,int ledId,int batteryState, int color, int mode,
int onMS, int offMS, int brightnessMode);
《添加新接口流程已经完结》
-【扩展】 如何添加一个系统服务管控LED,系统已经有一个服务LightsService.java,我们需要再添加一个对外提供接口
1、frameworks\base\core\java 目录创建一个全局类XXXX.java
获取一个上下文,不需要应用传参
private static Context getContext() {
ActivityThread thread = ActivityThread.currentActivityThread();
if (thread != null) {
return (Context) thread.getApplication();
} else {
return null;
}
}
2、编写静态接口方法
public static void xxxx(int eventId) {
Context context = getContext();
if (context != null) {
if(xxxManger==null) {
xxxManger= new xxxManger(context);
}
xxxManger.xxxxFun(eventId);
} else {
Log.e(TAG, "xxx: context is null");
}
}
3、xxxManger.java 编写aidl调用方法
private synchronized IxxxMangerService getService() {
if (mService == null) {
mService = IxxxMangerService .Stub.asInterface(
ServiceManager.getService("xxxservice"));
if (mService == null) {
Log.w("xxxxManger", "warning: no CWDEIVCE_SERVICE");
}
}
return mService;
}
public void xxxxFun(int eventId) {
try {
final IxxxMangerService cvc = getService();
if (cvc != null) {
cvc.xxxxFun(eventId);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
4、同目录添加aidl
frameworks\base\core\java\IxxxMangerService.aidl
interface IxxxMangerService {
void xxxxFun(int eventId);
}
5、实现aidl的具体方法
public class xxxMangerService extends IxxxMangerService.Stub{
}
6、把此服务开机启动
frameworks\base\services\java\com\android\server\SystemServer.java
xxxMangerService = new xxxMangerService (mSystemContext);
ServiceManager.addService("xxxservice", xxxMangerService );
7、添加权限
------------------------------ private/service.te ------------------------------
index a8ee1955..c8248025 100644
@@ -5,3 +5,5 @@ type gsi_service, service_manager_type;
type incidentcompanion_service, system_api_service, system_server_service, service_manager_type;
type stats_service, service_manager_type;
type statscompanion_service, system_server_service, service_manager_type;
+type led_service, system_api_service, system_server_service, service_manager_type;
+
--------------------------- private/service_contexts ---------------------------
index 96d553bf..ee12cbed 100644
@@ -219,4 +219,5 @@ wificond u:object_r:wificond_service:s0
wifiaware u:object_r:wifiaware_service:s0
wifirtt u:object_r:rttmanager_service:s0
window u:object_r:window_service:s0
+xxxservice u:object_r:led_service:s0
- 【扩展】动态设置电池、数据库的实现原理
动态设置电池
dumpsys battery set level 1 (电池电量)
dumpsys battery set status 2 (电池电量)
BATTERY_STATUS_INVALID = 0;
BATTERY_STATUS_UNKNOWN = 1;
BATTERY_STATUS_CHARGING = 2;
BATTERY_STATUS_DISCHARGING = 3;
BATTERY_STATUS_NOT_CHARGING = 4;
BATTERY_STATUS_FULL = 5;
设置电池温度
dumpsys battery set temp 560
动态设置数据库
adb shell settings put global device_provisioned 1
adb shell settings put secure user_setup_complete 1
adb shell settings put global device_provisioned 0
adb shell settings put secure user_setup_complete 0
adb shell settings get global device_provisioned
adb shell settings get secure user_setup_complete
以battery 的命令为例
frameworks\base\services\core\java\com\android\server\BatteryService.java
定义一个内部类
private final class BinderService extends Binder {
@Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
if (args.length > 0 && "--proto".equals(args[0])) {
dumpProto(fd);
} else {
dumpInternal(fd, pw, args);
}
}
@Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
(new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
}
}
发布
@Override
public void onStart() {
registerHealthCallback();
mBinderService = new BinderService();
publishBinderService("battery", mBinderService);
}