框架图
一、先看framework层提供的API
LightsService中的一些注释
路径frameworks/base/services/java/com/android/server/LightsService.java
//灯的定义 public static final int LIGHT_ID_BACKLIGHT = 0;//LCD背光灯 public static final int LIGHT_ID_KEYBOARD = 1;//键盘灯 public static final int LIGHT_ID_BUTTONS = 2;//按键灯 public static final int LIGHT_ID_BATTERY = 3;//电池灯 public static final int LIGHT_ID_NOTIFICATIONS = 4;//消息通知等灯 public static final int LIGHT_ID_ATTENTION = 5;//警示灯 public static final int LIGHT_ID_BLUETOOTH = 6;//蓝牙灯 public static final int LIGHT_ID_WIFI = 7;//Wifi灯 //闪烁方式 public static final int LIGHT_FLASH_NONE = 0;//不闪烁 public static final int LIGHT_FLASH_TIMED = 1;//根据设定的时间闪烁 public static final int LIGHT_FLASH_HARDWARE = 2;//根据硬件控制的闪烁 /** * Light brightness is managed by a user setting. * 背光亮度由用户设置 */ public static final int BRIGHTNESS_MODE_USER = 0; /** * Light brightness is managed by a light sensor. *背光亮度由光线传感器自动设置 */ public static final int BRIGHTNESS_MODE_SENSOR = 1; //存放Light对象的数组 private final Light mLights[] = new Light[LIGHT_ID_COUNT]; //构造方法 LightsService(Context context) { mNativePointer = init_native(); mContext = context; ServiceManager.addService("hardware",mLegacyFlashlightHack); for (int i = 0; i < LIGHT_ID_COUNT; i++) { mLights[i] = new Light(i); } } /* *根据id获取对应的Light对象 */ public Light getLight(int id) { return mLights[id]; } //本地方法 private static native int init_native(); //初始化 private static native void finalize_native(int ptr); //释放资源 //设置灯参数 private static native void setLight_native(int ptr, int light, int color, int mode, int onMS, int offMS, int brightnessMode);
LightsService中的内部类Light的一些注释
Light的方法定义有如下几个:
public void setBrightness(int brightness); public void setBrightness(int brightness, int brightnessMode); public void setColor(int color); public void setFlashing(int color, int mode, int onMS, int offMS); public void pulse(); public void pulse(int color, int onMS); public void turnOff();
Light类的方法详解
setBrightness
/* *这个方法是设置灯的亮度值,它最终会将这个亮度brightness(取值范围0~255)转换成色彩值 *color(ARGB)。我们知道颜色都是三基色RGB组成的,我们要控制的灯基本上都是单色的, *要么是红色,要么是绿色。所以在转换过程中,是将亮度值对应的数值分别设置到RGB三色 *中,也就是每一个单色上都设置为跟亮度相同的数值,这样无论控制的是什么颜色的灯,都会将 *亮度值设置为brightness。其中0xff000000表示的是ARGB模式,A表示的是透明度。在实际操作过程中,只要亮度值大于0,设置任意数值都会起到相同的作用,都能够达到点亮灯的效果。 */ public void setBrightness(int brightness, int brightnessMode) { synchronized (this) { int color = brightness & 0x000000ff; color = 0xff000000 | (color << 16) | (color << 8) | color; setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode); } }
setLightLocked
这个方法名中之所以要加上Locked,是因为在调用这个方法的时候都要放在关键字synchronized的作用域中
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) { if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) { if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#" + Integer.toHexString(color)); mColor = color; mMode = mode; mOnMS = onMS; mOffMS = offMS; setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode); } }
例如其它方法都同步调用setLightLocked方法:
public void turnOff() { synchronized (this) { setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0); } } private void stopFlashing() { synchronized (this) { setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER); } }
二、JNI层
com_android_server_LightsService.cpp
路径:frameworks/base/services/jni/com_android_server_LightsService.cpp
LightsService调用了LightsService.cpp的本地方法,下面看一下该类。
com_android_server_LightsService.cpp的一些注释
//关键引入hardware模块和lights模块接口 #include <hardware/hardware.h> #include <hardware/lights.h> //入口函数,注册方法 int register_android_server_LightsService(JNIEnv *env) { return jniRegisterNativeMethods(env, "com/android/server/LightsService", method_table, NELEM(method_table)); } //注册方法表 static JNINativeMethod method_table[] = { { "init_native", "()I", (void*)init_native }, { "finalize_native", "(I)V", (void*)finalize_native }, { "setLight_native", "(IIIIIII)V", (void*)setLight_native }, }; //LIGHT_ID定义,与LightsService.java中定义的必须一致 // These values must correspond with the LIGHT_ID constants in LightsService.java enum { LIGHT_INDEX_BACKLIGHT = 0, LIGHT_INDEX_KEYBOARD = 1, LIGHT_INDEX_BUTTONS = 2, LIGHT_INDEX_BATTERY = 3, LIGHT_INDEX_NOTIFICATIONS = 4, LIGHT_INDEX_ATTENTION = 5, LIGHT_INDEX_BLUETOOTH = 6, LIGHT_INDEX_WIFI = 7, LIGHT_COUNT }; //定义结构体 struct Devices { light_device_t* lights[LIGHT_COUNT]; }; //初始化方法 static jint init_native(JNIEnv *env, jobject clazz) { int err; hw_module_t* module; Devices* devices; //为Light设备分配内存 devices = (Devices*)malloc(sizeof(Devices)); //根据模块ID获取Lights模块,LIGHTS_HARDWARE_MODULE_ID定义在lights.h中 //#define LIGHTS_HARDWARE_MODULE_ID "lights" err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); if (err == 0) { //err=0表示获取Lights模块成功 //Light设备内存的初始化,根据不同的LIGHT_ID获取对应的设备,LIGHT_ID_XX 定义在lights.h中 devices->lights[LIGHT_INDEX_BACKLIGHT] = get_device(module, LIGHT_ID_BACKLIGHT); devices->lights[LIGHT_INDEX_KEYBOARD] = get_device(module, LIGHT_ID_KEYBOARD); devices->lights[LIGHT_INDEX_BUTTONS] = get_device(module, LIGHT_ID_BUTTONS); devices->lights[LIGHT_INDEX_BATTERY] = get_device(module, LIGHT_ID_BATTERY); devices->lights[LIGHT_INDEX_NOTIFICATIONS] = get_device(module, LIGHT_ID_NOTIFICATIONS); devices->lights[LIGHT_INDEX_ATTENTION] = get_device(module, LIGHT_ID_ATTENTION); devices->lights[LIGHT_INDEX_BLUETOOTH] = get_device(module, LIGHT_ID_BLUETOOTH); devices->lights[LIGHT_INDEX_WIFI] = get_device(module, LIGHT_ID_WIFI); } else { memset(devices, 0, sizeof(Devices)); } return (jint)devices; } //根据ID获取设备 static light_device_t* get_device(hw_module_t* module, char const* name) { int err; hw_device_t* device; //打开设备,err=0表示打开成功 err = module->methods->open(module, name, &device); if (err == 0) { return (light_device_t*)device; } else { return NULL; } } /*设置Light设备的参数 * env: jni环境变量 * clazz:调用该本地方法的java对象 * ptr: light设备的地址指针 * light: light的id值 * colorARGB:颜色值 * flashMode:闪烁模式(不闪烁/根据设置时间闪烁/硬件控制闪烁) * onMS: 闪烁时light打开时长 * offMS: 闪烁时light关闭时长 * brightnessMode:背光亮度模式(传感器/用户设置) */ static void setLight_native(JNIEnv *env, jobject clazz, int ptr, int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode) { Devices* devices = (Devices*)ptr; //根据指针获取到实例对象 light_state_t state; //判断light id值是否合法必须>=0并且小于LIGHT_COUNT,设备的light对象不能为空 if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) { return ; } //生成参数写入到state对象 memset(&state, 0, sizeof(light_state_t)); state.color = colorARGB; state.flashMode = flashMode; state.flashOnMS = onMS; state.flashOffMS = offMS; state.brightnessMode = brightnessMode; { ALOGD_IF_SLOW(50, "Excessive delay setting light"); //将state对象设置到light对象中 devices->lights[light]->set_light(devices->lights[light], &state); } } //销毁LightService static void finalize_native(JNIEnv *env, jobject clazz, int ptr) { Devices* devices = (Devices*)ptr; if (devices == NULL) { //对象指向空地址 return; } free(devices);//释放内存空间 }