屏幕亮度调节—基于Android_6.0(代码源于Google)

屏幕亮度调节

对于屏幕亮度调节 framework层已经有很多文章,再次主要分析一下hal层。

####1、Framework层主要文件BrightnessController.java
#####1.1、文件位置
frameworks/base/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java

#####1.2、主思路代码追踪

 public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value,
            boolean stopTracking) {
        updateIcon(mAutomatic);
        if (mExternalChange) return;

        if (!mAutomatic) {
            final int val = value + mMinimumBacklight;
            if (stopTracking) {
                MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
            }
            setBrightness(val);
            if (!tracking) {
                AsyncTask.execute(new Runnable() {
                        public void run() {
                            Settings.System.putIntForUser(mContext.getContentResolver(),
                                    Settings.System.SCREEN_BRIGHTNESS, val,
                                    UserHandle.USER_CURRENT);
                        }
                    });
            }
        } else {
            final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1;
            if (stopTracking) {
                MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS_AUTO, value);
            }
            setBrightnessAdj(adj);
            if (!tracking) {
                AsyncTask.execute(new Runnable() {
                    public void run() {
                        Settings.System.putFloatForUser(mContext.getContentResolver(),
                                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj,
                                UserHandle.USER_CURRENT);
                    }
                });
            }
        }

        for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
            cb.onBrightnessLevelChanged();
        }
}

当它获取到 设置的 brightness 的值之后,主要调用函数 setbrightness() 函数。通过该服务调用底层与设备打交道的C/C++代码,setLightBrightnes原型如下:

####2、跳转到 LightsService.java

#####2.1、文件位置
frameworks/base/services/core/java/com/android/server/lights/LightsService.java

#####2.2、主要代码分析

 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);
                }

亮度值在此进行了修改,即亮度值的格式变成:FFRRGGBB,FF是没有的,RR、GG、BB分别是256色的红绿蓝,并且红绿蓝的值都是一样的亮度值。

####3、硬件调用 接口com_android_server_lights_LightsService.cpp

#####3.1、文件位置
frameworks/base/services/core/jni/com_android_server_lights_LightsService.cpp

#####3.2、主要代码分析

static jlong 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);
        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 (jlong)devices;
}

用hw_get_module获取ID为LIGHTS_HARDWARE_MODULE_ID的硬件模块,该模块含有6个不同类型的亮度控制。

####4、hardware.c 实现 hw_get_module()函数
#####4.1、文件位置
hardware/libhardware/hardware.c

#####4.2、主要代码分析
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”
};

  /* Loop through the configuration variants looking for a module */
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
        if (property_get(variant_keys[i], prop, NULL) == 0) {
            continue;
        }
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

    /* Nothing found, try the default */
    if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
        goto found;
    }

    return -ENOENT;

found:
    /* load the module, if this fails, we're doomed, and we should not try
     * to load a different variant. */
    return load(class_id, path, module);
}````````

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。

(此处可自己定义,不一定需要在BoardConfig.mk中  比如在 :device/项目名/项目名 / device.mk  中 

```


PRODUCT_PACKAGES += \
	logFileManager

#add lights HAL for adjust backlight
PRODUCT_PACKAGES += lights.abc(项目名或板子名字)
PRODUCT_PROPERTY_OVERRIDES += ro.hardware.lights=abc(项目名或板子名字)

# SIM Toolkit
PRODUCT_PACKAGES += \
    Stk

```


    比如vendor/htc/dream-open/BoardConfig.mk里定义的TARGET_BOARD_PLATFORM := msm7k  ,则prop返回” msm7k ”,所以path = /system/lib/hw/lights. msm7k.so,也就是说要获取的硬件模块为lights. msm7k.so。 


####5、硬件原型 lights.c  及 android.mk文件
#####5.1、文件位置

/hardware/qcom/display/项目名/liblight/Android.mk  





```

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

# HAL module implemenation, not prelinked and stored in
# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so

LOCAL_SRC_FILES := lights.c

LOCAL_MODULE_RELATIVE_PATH := hw

LOCAL_MODULE_TAGS := optional

LOCAL_SHARED_LIBRARIES := liblog

LOCAL_MODULE := lights.(项目名)

include $(BUILD_SHARED_LIBRARY)
```

hardware/qcom/display/项目名/liblight/lights.c

```
/*
 * Copyright (C) 2014 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 "lights"

#include <cutils/log.h>

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>

#include <sys/ioctl.h>
#include <sys/types.h>

#include <hardware/lights.h>
#include <hardware/hardware.h>

#define ALOG_ONCE(mask, op, ...)			\
	do {					\
		{		\
			ALOGE(__VA_ARGS__);	\
			mask |= op;		\
		}				\
	} while (0);
#define OP_WRITE_OPEN		(1 << 0)
#define OP_BRIGHTNESS_PATH	(1 << 1)
#define OP_BRIGHTNESS_VALUE	(1 << 2)
#define OP_BRIGHTNESS_WRITE	(1 << 3)
#define OP_MAX_BRIGHTNESS_PATH	(1 << 4)
#define OP_MAX_BRIGHTNESS_OPEN	(1 << 5)
#define OP_MAX_BRIGHTNESS_READ	(1 << 6)

struct dragon_lights {
	struct light_device_t base;

	pthread_mutex_t lock;
	char const *sysfs_path;

	int max_brightness;

	unsigned long logged_failures;
};

static char const * kBacklightPath =
	"/sys/class/backlight/pwm-backlight.0";  (注意此位置不同的设备可能有不同的设备节点)


static struct dragon_lights *to_dragon_lights(struct light_device_t *dev)
{
	return (struct dragon_lights *)dev;
}

static int write_brightness(struct dragon_lights *lights, int brightness)
{
	char buffer[20], path[PATH_MAX];
	int fd, bytes, amt, ret = 0;


	ALOGI("LIGHTS write_brightness %d", brightness);

	bytes = snprintf(path, sizeof(path), "%s/brightness",
			 lights->sysfs_path);
	if (bytes < 0 || (size_t)bytes >= sizeof(path)) {
		ALOG_ONCE(lights->logged_failures, OP_BRIGHTNESS_PATH,
			  "failed to create brightness path %d\n", bytes);
		return -EINVAL;
	}

	fd = open(path, O_RDWR);
	if (fd < 0) {
		ALOG_ONCE(lights->logged_failures, OP_WRITE_OPEN,
			  "write_int failed to open %s/%d\n", path, errno);
		return -errno;
	}

	bytes = snprintf(buffer, sizeof(buffer), "%d\n", brightness);
	if (bytes < 0 || (size_t)bytes >= sizeof(buffer)) {
		ALOG_ONCE(lights->logged_failures, OP_BRIGHTNESS_VALUE,
			  "failed to create brightness value %d/%d\n",
			  brightness, bytes);
		ret = -EINVAL;
		goto out;
	}
	amt = write(fd, buffer, bytes);
	if (amt != bytes) {
		ALOG_ONCE(lights->logged_failures, OP_BRIGHTNESS_WRITE,
			  "failed to write brightness value %d/%d\n", amt,
			  bytes);
		ret = amt == -1 ? -errno : -EINVAL;
		goto out;
	}

out:
	close(fd);
	return ret;
}

static int read_max_brightness(struct dragon_lights *lights, int *value)
{
	char buffer[20], path[PATH_MAX];
	int ret = 0, fd, bytes;

	bytes = snprintf(path, sizeof(path), "%s/max_brightness",
			 lights->sysfs_path);
	if (bytes < 0 || (size_t)bytes >= sizeof(path)) {
		ALOG_ONCE(lights->logged_failures, OP_MAX_BRIGHTNESS_PATH,
			  "failed to create max_brightness path %d\n", bytes);
		return -EINVAL;
	}

	fd = open(path, O_RDONLY);
	if (fd < 0) {
		ALOG_ONCE(lights->logged_failures, OP_MAX_BRIGHTNESS_OPEN,
			  "failed to open max_brightness %s/%d\n", path, errno);
		return -errno;
	}

	bytes = read(fd, buffer, sizeof(buffer));
	if (bytes <= 0) {
		ALOG_ONCE(lights->logged_failures, OP_MAX_BRIGHTNESS_READ,
			  "failed to read max_brightness %s/%d\n", path, errno);
		ret = -errno;
		goto out;
	}

	*value = atoi(buffer);

out:
	close(fd);
	return ret;
}

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)
{
	struct dragon_lights *lights = to_dragon_lights(dev);
	int err, brightness_idx;
	int brightness = rgb_to_brightness(state);

	if(brightness < 0){
		brightness = 0;
	}

	if(brightness >255){
		brightness = 255;
	}


	pthread_mutex_lock(&lights->lock);
	err = write_brightness(lights, brightness);
	pthread_mutex_unlock(&lights->lock);

	return err;
}

static int close_lights(struct hw_device_t *dev)
{
	struct dragon_lights *lights = (struct dragon_lights *)dev;
	if (lights)
		free(lights);
	return 0;
}

static int open_lights(const struct hw_module_t *module, char const *name,
		       struct hw_device_t **device)
{
	struct dragon_lights *lights;
	int ret;

	// Only support backlight at the moment
	if (strcmp(LIGHT_ID_BACKLIGHT, name))
		return -EINVAL;

	lights = malloc(sizeof(*lights));
	if (lights == NULL) {
		ALOGE("failed to allocate lights memory");
		return -ENOMEM;
	}
	memset(lights, 0, sizeof(*lights));

	pthread_mutex_init(&lights->lock, NULL);

	lights->sysfs_path = kBacklightPath;

	ret = read_max_brightness(lights, &lights->max_brightness);
	if (ret) {
		close_lights((struct hw_device_t *)lights);
		return ret;
	}

	lights->base.common.tag = HARDWARE_DEVICE_TAG;
	lights->base.common.version = 0;
	lights->base.common.module = (struct hw_module_t *)module;
	lights->base.common.close = close_lights;
	lights->base.set_light = set_light_backlight;

	*device = (struct hw_device_t *)lights;
	return 0;
}

static struct hw_module_methods_t lights_methods = {
	.open =  open_lights,
};

struct hw_module_t HAL_MODULE_INFO_SYM = {
	.tag = HARDWARE_MODULE_TAG,
	.version_major = 1,
	.version_minor = 0,
	.id = LIGHTS_HARDWARE_MODULE_ID,
	.name = "jindory lights module",
	.author = "thundersoft",
	.methods = &lights_methods,
};

```


文件参考:

1、 android 设置系统屏幕亮度 
http://blog.csdn.net/zhuangxujun/article/details/8601392#comments
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值