3 亮度设置 文件:packages/apps/Settings/src/com/android/settings/BrightnessPreference.java private static final int MINIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_DIM + 10; private static final int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON; mSeekBar.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT); 设置进度条的范围,BRIGHTNESS_DIM = 20 BRIGHTNESS_ON=255,它们的定义在: frameworks/base/core/java/android/os/Power.java 3.1.2 设置亮度 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { setMode(isChecked ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); if (!isChecked) { setBrightness(mSeekBar.getProgress() + MINIMUM_BACKLIGHT); } } private void setBrightness(int brightness) { try { IPowerManager power = IPowerManager.Stub.asInterface( ServiceManager.getService("power")); if (power != null) { power.setBacklightBrightness(brightness); } } catch (RemoteException doe) { } } 由以上代码可知,brightness的范围是:20~255;代码通过服务管理器(ServiceManager)获得power服务,然后通过power服务设置亮度。 power.setBacklightBrightness的定义在: rameworks/base/core/java/android/os/IPowerManager.aidl.java frameworks/base/core/java/android/os/PowerManager.java 3.2 Power服务 /** * Brightness value for dim backlight */ public static final int BRIGHTNESS_DIM = 20; /** * Brightness value for fully on */ public static final int BRIGHTNESS_ON = 255; 文件:frameworks/base/core/java/android/os/PowerManager.java /** * sets the brightness of the backlights (screen, keyboard, button). * * @param brightness value from 0 to 255 * * {@hide} */ public void setBacklightBrightness(int brightness) { try { mService.setBacklightBrightness(brightness); } catch (RemoteException e) { } } 电源管理器(powermager)将brightness转给电源服务,该服务位置如下: 文件:frameworks/base/services/java/com/android/server/PowerManagerService.java public void setBacklightBrightness(int brightness) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); // Don't let applications turn the screen all the way off brightness = Math.max(brightness, Power.BRIGHTNESS_DIM); mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness, HardwareService.BRIGHTNESS_MODE_USER); mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, (mKeyboardVisible ? brightness : 0), HardwareService.BRIGHTNESS_MODE_USER); mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness, HardwareService.BRIGHTNESS_MODE_USER); long identity = Binder.clearCallingIdentity(); try { mBatteryStats.noteScreenBrightness(brightness); } catch (RemoteException e) { Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e); } finally { Binder.restoreCallingIdentity(identity); } // update our animation state if (ANIMATE_SCREEN_LIGHTS) { mScreenBrightness.curValue = brightness; mScreenBrightness.animating = false; mScreenBrightness.targetValue = -1; } if (ANIMATE_KEYBOARD_LIGHTS) { mKeyboardBrightness.curValue = brightness; mKeyboardBrightness.animating = false; mKeyboardBrightness.targetValue = -1; } if (ANIMATE_BUTTON_LIGHTS) { mButtonBrightness.curValue = brightness; mButtonBrightness.animating = false; mButtonBrightness.targetValue = -1; } } 由以上代码可知,同时设置了背光、键盘、按钮的亮度。mHardware 是硬件服务,通过该服务调用底层与设备打交道的C/C++代码,setLightBrightness_UNCHECKED原型如下: 文件:frameworks/base/services/java/com/android/server/HardwareService.java void setLightBrightness_UNCHECKED(int light, int brightness, int brightnessMode) { int b = brightness & 0x000000ff; b = 0xff000000 | (b << 16) | (b << 8) | b; setLight_native(mNativePointer, light, b, LIGHT_FLASH_NONE, 0, 0, brightnessMode); } 参数说明:int light 表示类型,选项如下: static final int LIGHT_ID_BACKLIGHT = 0; static final int LIGHT_ID_KEYBOARD = 1; static final int LIGHT_ID_BUTTONS = 2; static final int LIGHT_ID_BATTERY = 3; static final int LIGHT_ID_NOTIFICATIONS = 4; static final int LIGHT_ID_ATTENTION = 5; int brightness 表示亮度值 int brightnessMode 表示亮度的控制模式,选项如下: /** * Light brightness is managed by a user setting. */ static final int BRIGHTNESS_MODE_USER = 0; /** * Light brightness is managed by a light sensor. */ static final int BRIGHTNESS_MODE_SENSOR = 1; 由代码: int b = brightness & 0x000000ff; b = 0xff000000 | (b << 16) | (b << 8) | b; 可知,亮度值在此进行了修改,即亮度值的格式变成:FFRRGGBB,FF是没有的,RR、GG、BB分别是256色的红绿蓝,并且红绿蓝的值都是一样的亮度值。 3.3 硬件调用 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_COUNT }; #define LIGHTS_HARDWARE_MODULE_ID "lights" static jint init_native(JNIEnv *env, jobject clazz) { int err; hw_module_t* module; Devices* devices; devices = (Devices*)malloc(sizeof(Devices)); err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); if (err == 0) { 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); } else { memset(devices, 0, sizeof(Devices)); } return (jint)devices; } 用hw_get_module获取ID为LIGHTS_HARDWARE_MODULE_ID的硬件模块,该模块含有6个不同类型的亮度控制。 hw_get_module 的实现原理,如下: 文件:hardware/libhardware/Hardware.c #define HAL_LIBRARY_PATH "/system/lib/hw" static const char *variant_keys[] = { "ro.hardware", /* This goes first so that it can pick up a different file on the emulator. */ "ro.product.board", "ro.board.platform", "ro.arch" }; static const int HAL_VARIANT_KEYS_COUNT = (sizeof(variant_keys)/sizeof(variant_keys[0])); int hw_get_module(const char *id, const struct hw_module_t **module) { int status; int i; const struct hw_module_t *hmi = NULL; char prop[PATH_MAX]; char path[PATH_MAX]; /* * Here we rely on the fact that calling dlopen multiple times on * the same .so will simply increment a refcount (and not load * a new copy of the library). * We also assume that dlopen() is thread-safe. */ /* Loop through the configuration variants looking for a module */ for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) { if (i < HAL_VARIANT_KEYS_COUNT) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH, id, prop); } else { snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH, id); } if (access(path, R_OK)) { continue; } /* we found a library matching this id/variant */ break; } status = -ENOENT; if (i < HAL_VARIANT_KEYS_COUNT+1) { /* load the module, if this fails, we're doomed, and we should not try * to load a different variant. */ status = load(id, path, module); } return status; } property_get(variant_keys[i], prop, NULL) 会按如下顺序去获取如下变量所对应的值,然后返回给prop: "ro.hardware", /* This goes first so that it can pick up a different file on the emulator. */ "ro.product.board", "ro.board.platform", "ro.arch" 它们对应的变量为: "ro.product.board=$TARGET_BOOTLOADER_BOARD_NAME" "ro.board.platform=$TARGET_BOARD_PLATFORM" 如vendor/htc/dream-open/BoardConfig.mk里定义的TARGET_BOARD_PLATFORM := msm7k,则prop返回” msm7k ”,所以path = /system/lib/hw/lights. msm7k.so,也就是说要获取的硬件模块为lights. msm7k.so。 3.3.2调用硬件 setLight_native对应的jni C/C++代码是: 文件:frameworks/base/services/jni/com_android_server_HardwareService.cpp 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; if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) { return ; } memset(&state, 0, sizeof(light_state_t)); state.color = colorARGB; state.flashMode = flashMode; state.flashOnMS = onMS; state.flashOffMS = offMS; state.brightnessMode = brightnessMode; devices->lights[light]->set_light(devices->lights[light], &state); } 通过light标识找到对应的light设备,然后再设置亮度。 3.3.3 硬件原型 文件:hardware/msm7k/liblights/Android.mk LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM) 也就是生成模块:/system/lib/hw/lights. msm7k.so 文件:hardware/msm7k/liblights/lights.c /** Open a new instance of a lights device using name */ 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)) { set_light = set_light_backlight; } else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) { set_light = set_light_keyboard; } else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) { set_light = set_light_buttons; } else if (0 == strcmp(LIGHT_ID_BATTERY, name)) { set_light = set_light_battery; } else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) { set_light = set_light_notifications; } else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) { set_light = set_light_attention; } else { return -EINVAL; } pthread_once(&g_init, init_globals); struct light_device_t *dev = malloc(sizeof(struct light_device_t)); memset(dev, 0, sizeof(*dev)); dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0; dev->common.module = (struct hw_module_t*)module; dev->common.close = (int (*)(struct hw_device_t*))close_lights; dev->set_light = set_light; *device = (struct hw_device_t*)dev; return 0; } static struct hw_module_methods_t lights_module_methods = { .open = open_lights, }; 以上代码对应的是: 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); 也就是说,对不同的亮度设置给予了不同的设置函数。 举例,背光设置,背光对应的代码如下: char const*const LCD_FILE = "/sys/class/leds/lcd-backlight/brightness"; static int rgb_to_brightness(struct light_state_t const* state) { int color = state->color & 0x00ffffff; return ((77*((color>>16)&0x00ff)) + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; } static int set_light_backlight(struct light_device_t* dev, struct light_state_t const* state) { int err = 0; int brightness = rgb_to_brightness(state); pthread_mutex_lock(&g_lock); g_backlight = brightness; err = write_int(LCD_FILE, brightness); if (g_haveTrackballLight) { handle_trackball_light_locked(dev); } pthread_mutex_unlock(&g_lock); return err; } 也就是往文件/sys/class/leds/lcd-backlight/brightness写入亮度值,然后驱动会根据该文件更改背光的亮度。LCD_FILE的路径根据实际情况更改,同时需要在init.rc 修改其权限,使其可写rgb_to_brightness也根据实际更改,比如要直接亮度值控制,那只要获取r,g,b其中的一个值就行了,如: static int rgb_to_brightness(struct light_state_t const* state) { int color = state->color & 0x000000ff; return color; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int write_int(char const* path, int value) fd = open(path, O_RDWR); |