<policy user="system_fw">
<allow send_destination="org.tizen.system.deviced" send_interface="org.tizen.system.deviced.Battery" send_member="power_supply"/>
<allow send_destination="org.tizen.system.deviced" send_interface="org.tizen.system.deviced.ExtCon"/>
+ <allow send_destination="org.tizen.system.deviced" send_interface="org.tizen.system.deviced.display" send_member="AutoBrightnessChanged"/>
</policy>
<policy user="security_fw">
PowerKeyDoublePressSupport=yes
AccelSensorOn=no
ContinuousSampling=no
-Dimming=no
\ No newline at end of file
+Dimming=no
+LBMsupport=yes
+Level=4
+BrtTable=1,20,40,50,60,70,80,90,95,100
+AodBrightnessLevel=40
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <vconf.h>
+
+#include "hbm.h"
+#include "lbm.h"
+#include "auto-brightness-sensorhub.h"
+#include "display/util.h"
+#include "display/core.h"
+#include "display/display-ops.h"
+#include "core/device-notifier.h"
+#include "battery/power-supply.h"
+
+#define SPECIFIC_MODE_OFF 0
+#define LBM_LEVEL 110
+#define HBM_LEVEL 120
+
+#define LOWBATCAPACITY 5
+
+static int auto_brightness_state = SETTING_BRIGHTNESS_AUTOMATIC_OFF;
+
+static void change_brightness_transit(int start, int end)
+{
+ backlight_ops.transit_brt(start, end,
+ display_conf.brightness_change_step);
+}
+
+static void set_brightness_level(int level)
+{
+ int old_level = 0;
+ if (pm_cur_state != S_NORMAL)
+ return;
+/*
+ if (battery.capacity <= LOWBATCAPACITY && battery.charge_now != CHARGER_CHARGING)
+ return;
+*/
+ _I("level changed! %d", level);
+
+ if ((level > PM_MAX_BRIGHTNESS || level < PM_MIN_BRIGHTNESS) &&
+ (level != LBM_LEVEL && level != HBM_LEVEL && level != SPECIFIC_MODE_OFF)) {
+ _E("Invalid level %d", level);
+ return;
+ }
+
+ backlight_ops.get_brightness(&old_level);
+
+ switch (level) {
+ case LBM_LEVEL:
+ /*
+ * received LBM enable
+ * change brightness to under LBM_BRIGHTNESS_LOW and set lbm state
+ */
+ if (hbm_get_state()) {
+ hbm_set_state(false);
+ _I("HBM mode disabled.");
+ }
+ if (!lbm_get_state()) {
+ lbm_set_state(true);
+ _I("LBM mode enabled.");
+ }
+ break;
+ case HBM_LEVEL:
+ /* HBM must do not turn on at DIM_STY state. */
+ if (pm_status_flag & DIM_MASK)
+ break;
+
+ /*
+ * received HBM enable
+ * change brightness to MAX value and set hbm state
+ */
+ if (lbm_get_state()) {
+ lbm_set_state(false);
+ _I("Disabling LBM before enabling HBM.");
+ }
+
+ change_brightness_transit(old_level, PM_MAX_BRIGHTNESS);
+ hbm_set_state(true);
+ _I("HBM mode enabled.");
+
+ break;
+ case SPECIFIC_MODE_OFF:
+ /*
+ * received HBM disable
+ * unset hbm state and change brightness to setting value
+ */
+
+ level = backlight_ops.get_default_brt();
+
+ if (hbm_get_state())
+ hbm_set_state(false);
+
+ if (lbm_get_state())
+ lbm_set_state(false);
+
+ change_brightness_transit(old_level, level);
+
+ break;
+ default:
+ /*
+ * received automatic brightness by the light sensor
+ */
+ if (auto_brightness_state != SETTING_BRIGHTNESS_AUTOMATIC_ON)
+ return;
+
+ if (hbm_get_state())
+ hbm_set_state(false);
+
+ if (lbm_get_state())
+ lbm_set_state(false);
+
+ if (old_level != level) {
+ change_brightness_transit(old_level, level);
+ backlight_ops.set_default_brt(level);
+ }
+
+ break;
+ }
+
+ device_notify(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, NULL);
+}
+
+static void set_default_brightness(void)
+{
+ int default_brt;
+
+ default_brt = backlight_ops.get_default_brt();
+ backlight_ops.set_default_brt(default_brt);
+ backlight_ops.update();
+}
+
+static void set_automatic_state_cb(keynode_t *key_nodes, void *data)
+{
+ if (key_nodes == NULL) {
+ _E("Wrong parameter, key_nodes is null.");
+ return;
+ }
+ auto_brightness_state = vconf_keynode_get_int(key_nodes);
+
+ switch (auto_brightness_state) {
+ case SETTING_BRIGHTNESS_AUTOMATIC_OFF:
+ if (hbm_get_state())
+ hbm_set_state(false);
+ /* escape dim state if it's in low battery.*/
+ set_brightness_changed_state();
+ set_default_brightness();
+ break;
+ case SETTING_BRIGHTNESS_AUTOMATIC_PAUSE:
+ if (hbm_get_state())
+ hbm_set_state(false);
+ break;
+ case SETTING_BRIGHTNESS_AUTOMATIC_ON:
+ set_brightness_changed_state();
+ break;
+ default:
+ _E("Invalid value %d.", auto_brightness_state);
+ }
+}
+
+int prepare_level_handler(void)
+{
+ int status, ret;
+
+ display_info.set_brightness_level = set_brightness_level;
+
+ ret = vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &status);
+ if (ret >= 0)
+ auto_brightness_state = status;
+
+ vconf_notify_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+ set_automatic_state_cb, NULL);
+
+ return 0;
+}
+
+void exit_level_handler(void)
+{
+ vconf_ignore_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT,
+ set_automatic_state_cb);
+ set_default_brightness();
+}
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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.
+ */
+
+
+/**
+ * @file auto-brightness-sensorhub.h
+ * @brief auto-brightness-sensorhub header file
+ */
+#ifndef __AUTO_BRT_SENSORHUB_H__
+#define __AUTO_BRT_SENSORHUB_H__
+
+int prepare_level_handler(void);
+void exit_level_handler(void);
+
+#endif
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <error.h>
+#include <device-node.h>
+
+#include "auto-brightness-sensorhub.h"
+#include "core/device-notifier.h"
+#include "display/util.h"
+#include "display/core.h"
+#include "display/poll.h"
+#include "core/common.h"
+#include "core/devices.h"
+#include "display/display-actor.h"
+#include "display/display-ops.h"
+#include "display-info.h"
+
+#define CHARGER_LCD_NODE "/sys/class/power_supply/battery/lcd"
+
+enum charging_lcd_state {
+ CHARGING_LCD_OFF = 0,
+ CHARGING_LCD_ON = 1,
+};
+
+static GVariant *dbus_autobrightnesschanged(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = 0;
+ int level;
+
+ g_variant_get(param, "(i)", &level);
+
+ if (display_info.set_brightness_level)
+ display_info.set_brightness_level(level);
+ else
+ ret = -ENOTSUP;
+
+ return g_variant_new("(i)", ret);
+}
+
+static const dbus_method_s dbus_methods[] = {
+ { "AutoBrightnessChanged", "i", "i", dbus_autobrightnesschanged },
+};
+
+static const dbus_interface_u dbus_interface = {
+ .oh = NULL,
+ .name = DEVICED_INTERFACE_DISPLAY,
+ .methods = dbus_methods,
+ .nr_methods = ARRAY_SIZE(dbus_methods),
+};
+
+static int display_state_changed(void *data)
+{
+ enum state_t state;
+ int ret = 0;
+
+ state = DATA_VALUE_INT(data);
+
+ if (state == S_LCDON)
+ ret = sys_set_int(CHARGER_LCD_NODE, CHARGING_LCD_ON);
+ else
+ ret = sys_set_int(CHARGER_LCD_NODE, CHARGING_LCD_OFF);
+
+ if (ret < 0)
+ _E("Can't write %s node %d.", CHARGER_LCD_NODE, state);
+
+ return 0;
+}
+
+static void display_handler_init(void *data)
+{
+ int ret;
+
+ prepare_level_handler();
+ register_notifier(DEVICE_NOTIFIER_LCD, display_state_changed);
+
+ ret = sys_set_int(CHARGER_LCD_NODE, CHARGING_LCD_ON);
+ if (ret < 0)
+ _E("Can't write %s node.", CHARGER_LCD_NODE);
+
+ ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_DISPLAY, &dbus_interface);
+ if (ret < 0)
+ _E("Failed to register dbus object.");
+}
+
+static const struct display_ops display_handler_ops = {
+ .name = "dislay-handler",
+ .init = display_handler_init,
+};
+
+DISPLAY_OPS_REGISTER(&display_handler_ops)
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <stdbool.h>
+#include <fcntl.h>
+
+#include "weaks.h"
+#include "display-info.h"
+#include "display/util.h"
+#include "display/core.h"
+#include "display/display-ops.h"
+#include "core/common.h"
+#include "core/device-notifier.h"
+#include "core/config-parser.h"
+
+#define BOARD_CONF_FILE "/etc/deviced/display.conf"
+
+#define ON "on"
+#define OFF "off"
+
+#define SIGNAL_HBM_ON "HBMOn"
+#define SIGNAL_HBM_OFF "HBMOff"
+
+#define HBM_LEVEL 120
+#define DEFAULT_BRIGHTNESS_LEVEL 80
+
+#define LCD_PATH "sys/class/lcd/"
+#define HBM_PATH "/hbm"
+#define DEVICE_PATH "/device"
+#define PATH_BUFFER_MAX 256
+
+static guint timer;
+static struct timespec offtime;
+static char *hbm_path;
+
+static void broadcast_hbm_state(char *state)
+{
+ dbus_handle_emit_dbus_signal(NULL,
+ DEVICED_PATH_DISPLAY,
+ DEVICED_INTERFACE_DISPLAY,
+ state,
+ NULL);
+}
+
+static void hbm_set_offtime(int timeout)
+{
+ struct timespec now;
+
+ if (timeout <= 0) {
+ offtime.tv_sec = 0;
+ return;
+ }
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ offtime.tv_sec = now.tv_sec + timeout;
+}
+
+static gboolean hbm_off_cb(void *data)
+{
+ int ret;
+
+ timer = 0;
+
+ if (pm_cur_state != S_NORMAL) {
+ _D("Hbm timeout, but it's not display normal.");
+ return G_SOURCE_REMOVE;
+ }
+ hbm_set_offtime(0);
+
+ ret = sys_set_str(hbm_path, OFF);
+ if (ret < 0)
+ _E("Failed to off hbm.");
+
+ ret = vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
+ DEFAULT_BRIGHTNESS_LEVEL);
+ if (ret < 0) {
+ _E("Failed to set vconf value lcd brightness, %d.", ret);
+ return G_SOURCE_REMOVE;
+ }
+ backlight_ops.set_default_brt(DEFAULT_BRIGHTNESS_LEVEL);
+ backlight_ops.update();
+ broadcast_hbm_state(SIGNAL_HBM_OFF);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void hbm_start_timer(int timeout)
+{
+ if (timer) {
+ g_source_remove(timer);
+ timer = 0;
+ }
+ if (!timer) {
+ timer = g_timeout_add_seconds(timeout, hbm_off_cb, NULL);
+ }
+}
+
+static void hbm_end_timer(void)
+{
+ if (timer) {
+ g_source_remove(timer);
+ timer = 0;
+ }
+}
+
+int hbm_get_state(void)
+{
+ char state[5];
+ int ret, hbm;
+
+ if (!hbm_path)
+ return -ENODEV;
+
+ ret = sys_get_str(hbm_path, state, sizeof(state));
+ if (ret < 0)
+ return ret;
+
+ if (!strncmp(state, ON, strlen(ON)))
+ hbm = true;
+ else if (!strncmp(state, OFF, strlen(OFF)))
+ hbm = false;
+ else
+ hbm = -EINVAL;
+
+ return hbm;
+}
+
+int hbm_set_state(int hbm)
+{
+ if (!hbm_path)
+ return -ENODEV;
+
+ if (hbm)
+ broadcast_hbm_state(SIGNAL_HBM_ON);
+ else
+ broadcast_hbm_state(SIGNAL_HBM_OFF);
+
+ return sys_set_str(hbm_path, (hbm ? ON : OFF));
+}
+
+static void hbm_turn_on(void)
+{
+ if (!hbm_get_state())
+ hbm_set_state(true);
+}
+
+static void hbm_turn_off(void)
+{
+ if (hbm_get_state())
+ hbm_set_state(false);
+}
+
+static int hbm_set_state_with_timeout(int hbm, int timeout)
+{
+ int ret;
+
+ if (hbm && (timeout <= 0))
+ return -EINVAL;
+
+ ret = hbm_set_state(hbm);
+ if (ret < 0)
+ return ret;
+
+ _D("timeout is %d", timeout);
+
+ if (hbm) {
+ /*
+ * hbm is turned off after timeout.
+ */
+ hbm_set_offtime(timeout);
+ hbm_start_timer(timeout);
+ } else {
+ hbm_set_offtime(0);
+ hbm_end_timer();
+ broadcast_hbm_state(SIGNAL_HBM_OFF);
+ }
+
+ return 0;
+}
+
+void hbm_check_timeout(void)
+{
+ struct timespec now;
+ int ret;
+
+ if (timer) {
+ g_source_remove(timer);
+ timer = 0;
+ }
+
+ if (offtime.tv_sec == 0) {
+ if (hbm_get_state() == true) {
+ _E("It's invalid state. HBM is turned off.");
+ hbm_set_state(false);
+ }
+ return;
+ }
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ _D("now %ld, offtime %ld", now.tv_sec, offtime.tv_sec);
+
+ /* check it's timeout */
+ if (now.tv_sec >= offtime.tv_sec) {
+ hbm_set_offtime(0);
+
+ ret = sys_set_str(hbm_path, OFF);
+ if (ret < 0)
+ _E("Failed to off HBM.");
+ backlight_ops.update();
+ broadcast_hbm_state(SIGNAL_HBM_OFF);
+ } else {
+ _D("HBM state is restored.");
+ hbm_set_state(true);
+ hbm_start_timer(offtime.tv_sec - now.tv_sec);
+ }
+}
+
+static void hbm_get_level(GVariant *var, void *user_data, GError *err)
+{
+ int level, brt;
+
+ if (!var) {
+ _D("Invalid parameter.");
+ return;
+ }
+
+ if (!dh_get_param_from_var(var, "(i)", &level)) {
+ _E("Failed to get message, %s.", g_variant_get_type_string(var));
+ goto out;
+ }
+
+ if (level == HBM_LEVEL && hbm_get_state() == false) {
+ _I("Lux was high already, HBM enable");
+ backlight_ops.get_brightness(&brt);
+ backlight_ops.transit_brt(brt, PM_MAX_BRIGHTNESS,
+ display_conf.brightness_change_step);
+ hbm_set_state(true);
+ }
+out:
+ g_variant_unref(var);
+}
+
+static gboolean hbm_check_handler(gpointer data)
+{
+ int ret;
+
+ ret = dbus_handle_method_async_with_reply(COORD_BUS_NAME,
+ COORD_PATH_AUTOBRIGHTNESS,
+ COORD_INTERFACE_AUTOBRIGHTNESS,
+ "GetLevel",
+ NULL,
+ NULL,
+ hbm_get_level,
+ -1,
+ NULL);
+
+ if (ret < 0)
+ _D("Failed to call coord.autobrightness.GetLevel method, %d", ret);
+
+ return G_SOURCE_REMOVE;
+}
+
+static int display_state_changed(void *data)
+{
+ int state;
+ int ret;
+
+ state = DATA_VALUE_INT(data);
+
+ if (get_outdoor_setting)
+ if (get_outdoor_setting())
+ return 0;
+
+ switch (state) {
+ case S_NORMAL:
+ /*
+ * outdoor-enhance-mode not supported
+ * : check & restore hbm always.
+ * outdoor-enhance-mode supported
+ * : check & restore hbm when old state is dim only.
+ */
+ if (!get_outdoor_setting || pm_old_state == S_LCDDIM)
+ hbm_check_timeout();
+
+ (void) g_timeout_add(300, hbm_check_handler, NULL);
+ break;
+ case S_LCDDIM:
+ case S_LCDOFF:
+ case S_SLEEP:
+ if (hbm_get_state() == true) {
+ ret = hbm_set_state(false);
+ if (ret < 0)
+ _E("Failed to off hbm.");
+ }
+ hbm_end_timer();
+ break;
+ }
+
+ return 0;
+}
+
+static int display_off_changed(void *data)
+{
+ int brt;
+
+ if (hbm_get_state() == false)
+ return 0;
+
+ hbm_turn_off();
+
+ brt = backlight_ops.get_default_brt();
+ if (pm_status_flag & DIMSTAY_FLAG)
+ _D("skip auto change brightness");
+ else
+ backlight_ops.transit_brt(PM_MAX_BRIGHTNESS, brt, display_conf.brightness_change_step);
+
+ return 0;
+}
+
+static GVariant *dbus_gethbm(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ return g_variant_new("(i)", hbm_get_state());
+}
+
+static GVariant *dbus_sethbm_timeout(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int hbm, timeout, ret;
+
+ g_variant_get(param, "(ii)", &hbm, &timeout);
+
+ if (timeout <= 0) {
+ _E("Timeout can not be setting(%d).", timeout);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = hbm_set_state_with_timeout(hbm, timeout);
+
+ if (ret < 0)
+ _E("Failed to set HBM (ret=%d, hbm=%d, time=%d).", ret, hbm, timeout);
+ else
+ _I("Set hbm (ret=%d, hbm=%d, time=%d).", ret, hbm, timeout);
+
+out:
+ return g_variant_new("(i)", ret);
+}
+
+static const dbus_method_s dbus_methods[] = {
+ { "GetHBM", NULL, "i", dbus_gethbm },
+ { "SetHBMTimeout", "ii", "i", dbus_sethbm_timeout },
+};
+
+static const dbus_interface_u dbus_interface = {
+ .oh = NULL,
+ .name = DEVICED_INTERFACE_DISPLAY,
+ .methods = dbus_methods,
+ .nr_methods = ARRAY_SIZE(dbus_methods),
+};
+
+static int hbm_func(unsigned int cmd, void *arg)
+{
+ int ret = 0;
+ int *on;
+ struct hbmsetstate *hss;
+
+ switch (cmd) {
+ case HBM_GET_STATE:
+ ret = hbm_get_state();
+ break;
+ case HBM_SET_STATE:
+ on = (int *)arg;
+ ret = hbm_set_state(*on);
+ break;
+ case HBM_TURN_ON:
+ hbm_turn_on();
+ break;
+ case HBM_TURN_OFF:
+ hbm_turn_off();
+ break;
+ case HBM_SET_TIMEOUT_STATE:
+ hss = (struct hbmsetstate *)arg;
+ ret = hbm_set_state_with_timeout(hss->hbm, hss->timeout);
+ break;
+ case HBM_TURN_OFF_STATE:
+ hbm_turn_off();
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static char *check_and_copy_path(char *path)
+{
+ int fd;
+ char *buf = NULL;
+
+ fd = open(path, O_RDONLY);
+ if (fd >= 0) {
+ buf = strndup(path, strlen(path));
+ close(fd);
+ } else {
+ _E("Failed to open HBM node.");
+ }
+
+ return buf;
+}
+
+static char *find_hbm_node()
+{
+ DIR *d;
+ struct dirent *dir;
+ char buf[PATH_BUFFER_MAX];
+ char *result = NULL;
+
+ d = opendir(LCD_PATH);
+ if (!d)
+ return NULL;
+
+ while ((dir = readdir(d))) {
+ if (dir->d_name[0] == '.')
+ continue;
+
+ snprintf(buf, sizeof(buf), "%s%s%s", LCD_PATH,
+ dir->d_name, HBM_PATH);
+
+ result = check_and_copy_path(buf);
+ if (result)
+ break;
+
+ snprintf(buf, sizeof(buf), "%s%s%s%s", LCD_PATH,
+ dir->d_name, DEVICE_PATH, HBM_PATH);
+
+ result = check_and_copy_path(buf);
+ if (result)
+ break;
+ }
+ closedir(d);
+
+ return result;
+}
+
+static void hbm_init(void *data)
+{
+ int ret;
+
+ hbm_path = find_hbm_node();
+
+ if (!hbm_path) {
+ _E("Failed to find HBM node.");
+ return;
+ } else {
+ _I("HBM node: %s.", hbm_path);
+ }
+
+ ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_DISPLAY, &dbus_interface);
+ if (ret < 0)
+ _E("Failed to register dbus object.");
+
+ /* register notifier */
+ register_notifier(DEVICE_NOTIFIER_LCD, display_state_changed);
+ register_notifier(DEVICE_NOTIFIER_LCD_OFF, display_off_changed);
+}
+
+static void hbm_exit(void *data)
+{
+ /* unregister notifier */
+ unregister_notifier(DEVICE_NOTIFIER_LCD_OFF, display_off_changed);
+ unregister_notifier(DEVICE_NOTIFIER_LCD, display_state_changed);
+
+ /*
+ * set default brightness
+ * if display logic is stopped in hbm state.
+ */
+ if (hbm_get_state() == true) {
+ hbm_set_offtime(0);
+ _I("set brightness to default value!");
+ }
+}
+
+static const struct display_ops display_hbm_ops = {
+ .name = "hbm",
+ .init = hbm_init,
+ .exit = hbm_exit,
+ .func = hbm_func,
+};
+
+DISPLAY_OPS_REGISTER(&display_hbm_ops)
+
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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.
+ */
+
+
+/**
+ * @file hbm.h
+ * @brief High Brightness Mode header file
+ */
+#ifndef __HBM_H__
+#define __HBM_H__
+
+/*
+ * @brief Configuration structure
+ */
+struct hbm_config {
+ int on;
+ int off;
+ int on_count;
+ int off_count;
+};
+
+int hbm_get_state(void);
+int hbm_set_state(int hbm);
+
+/*
+ * Global variables
+ * hbm_conf : configuration of hbm
+ */
+extern struct hbm_config hbm_conf;
+
+/**
+ * @}
+ */
+
+#endif
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. Ltd. All rights reserved.
+ *
+ * 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.
+ */
+
+#include <stdbool.h>
+#include <math.h>
+
+#include "lbm.h"
+#include "display-info.h"
+#include "display/util.h"
+#include "display/core.h"
+#include "display/display-ops.h"
+#include "core/common.h"
+#include "core/config-parser.h"
+#include "core/device-notifier.h"
+
+#define DISPLAY_CONF_FILE "/etc/deviced/display.conf"
+
+#define SIGNAL_LBM_ON "LBMOn"
+#define SIGNAL_LBM_OFF "LBMOff"
+
+#define LCD_PHASED_DELAY 10000 /* microsecond */
+
+#define LBM_TRANSIT_STEP 20
+
+struct lbm_config lbm_conf = {
+ .support = 0,
+ .down_level = 0,
+ .brt_table_size = 0,
+ .brt_table = NULL,
+ .aod_brightness_level = 0,
+};
+
+static bool lbm_state;
+static int lbm_setting_mode;
+static int system_brightness;
+static struct display_device *display_dev;
+
+static void broadcast_lbm_state(int state)
+{
+ char *str;
+
+ if (state == 1)
+ str = SIGNAL_LBM_ON;
+ else
+ str = SIGNAL_LBM_OFF;
+
+ dbus_handle_emit_dbus_signal(NULL,
+ DEVICED_PATH_DISPLAY,
+ DEVICED_INTERFACE_DISPLAY,
+ str,
+ NULL);
+}
+
+static int get_level_by_brt(int brt)
+{
+ int iter;
+ for (iter = 0; iter < lbm_conf.brt_table_size; iter++) {
+ if (lbm_conf.brt_table[iter] == brt)
+ return iter;
+ }
+ return -EINVAL;
+}
+
+static int lbm_down_brt(int brt)
+{
+ int level;
+ int down_level;
+
+ if (lbm_conf.down_level == 0) {
+ _I("LBM down level setting is 0.");
+ return brt;
+ }
+
+ if (lbm_conf.brt_table == NULL || lbm_setting_mode == 0) {
+ _I("LBM setting mode is %d.", lbm_setting_mode);
+ return brt;
+ }
+
+ level = get_level_by_brt(brt);
+ down_level = level - lbm_conf.down_level;
+
+ if (down_level < 0)
+ down_level = 0;
+
+ return lbm_conf.brt_table[down_level];
+}
+
+int lbm_get_state(void)
+{
+ if (!lbm_conf.support)
+ return -ENODEV;
+
+ return lbm_state;
+}
+
+static int lbm_get_brightness(int *val)
+{
+ if (system_brightness == 0)
+ _E("Failed to get brightness.");
+
+ *val = system_brightness;
+
+ return 0;
+}
+
+static int lbm_set_brightness(int val)
+{
+ int brt = 0;
+
+ if (!display_dev || !display_dev->set_brightness) {
+ _E("There is no display device.");
+ return -ENOENT;
+ }
+
+ if (pm_status_flag & DIM_MASK)
+ val = 0;
+ else
+ brt = lbm_down_brt(val);
+
+ system_brightness = val;
+
+ _I("Set brightness(LBM on) system=%d, real=%d.", val, brt);
+ device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
+
+ return display_dev->set_brightness(brt);
+}
+
+static void lbm_change_brightness(int start, int end, int step)
+{
+ int diff, val;
+ int ret = -1;
+ int prev;
+
+ if (display_dimstay_check())
+ return;
+
+ ret = backlight_ops.get_brightness(&prev);
+
+ if (ret < 0) {
+ _E("Failed to get brightness, %d.", ret);
+ return;
+ }
+
+ if (prev == end)
+ return;
+
+ if (pm_status_flag & DIM_MASK)
+ end = 0;
+
+ _I("Start %d, end %d, step %d.", start, end, step);
+
+ if (display_dev && display_dev->set_multi_brightness) {
+ diff = lbm_down_brt(end);
+
+ ret = display_dev->set_multi_brightness(diff, step, LCD_PHASED_DELAY);
+ if (ret < 0)
+ _E("Failed to set_multi_brightness, %d.", ret);
+
+ backlight_ops.set_brightness(end);
+
+ return;
+ }
+
+ diff = end - start;
+
+ if (abs(diff) < step)
+ val = (diff > 0 ? 1 : -1);
+ else
+ val = (int)ceil((double)diff / step);
+
+ while (start != end) {
+ if (val == 0)
+ break;
+
+ start += val;
+ if ((val > 0 && start > end) ||
+ (val < 0 && start < end))
+ start = end;
+
+ usleep(LCD_PHASED_DELAY);
+ backlight_ops.set_brightness(start);
+ }
+}
+
+int lbm_set_state(int lbm)
+{
+ int brt;
+ _I("lbm_set_state");
+
+ if (lbm == lbm_state) {
+ _W("already lbm %s", (lbm_state ? "on" : "off"));
+ return 0;
+ }
+
+ if (!lbm || lbm_setting_mode) {
+ lbm_state = lbm;
+ broadcast_lbm_state(lbm_state);
+ }
+
+ brt = backlight_ops.get_default_brt();
+ _I("Default brightness: %d", brt);
+ if (lbm && lbm_setting_mode) {
+ _I("Lowering Brightness.");
+ backlight_ops.transit_brt(brt, lbm_down_brt(brt), LBM_TRANSIT_STEP);
+ backlight_ops.get_brightness(&system_brightness);
+ backlight_ops.set_brightness = lbm_set_brightness;
+ backlight_ops.get_brightness = lbm_get_brightness;
+ backlight_ops.transit_brt = lbm_change_brightness;
+ } else {
+ system_brightness = 0;
+ backlight_ops.restore_brightness_func();
+ backlight_ops.transit_brt(lbm_down_brt(brt), brt, display_conf.brightness_change_step);
+ }
+
+ backlight_ops.set_brightness(brt);
+
+ return 0;
+}
+
+static void lbm_table_load(char *value, struct lbm_config *c)
+{
+ char *p, *saveptr;
+ int level_count = 1;
+ int i;
+
+ if (value == '\0')
+ return;
+
+ for (i = 0; *(value + i) != '\0'; i++) {
+ if (*(value + i) == ',')
+ level_count++;
+ }
+
+ c->brt_table = malloc(sizeof(int) * level_count);
+ if (!c->brt_table) {
+ _E("Failed to allocate memory.");
+ return;
+ }
+ c->brt_table_size = level_count;
+
+ i = 0;
+ p = strtok_r(value, ",", &saveptr);
+ if (p)
+ c->brt_table[i++] = atoi(p);
+
+ while (p != NULL) {
+ p = strtok_r(NULL, ",", &saveptr);
+ if (p)
+ c->brt_table[i++] = atoi(p);
+ }
+}
+
+static int lbm_load_config(struct parse_result *result, void *user_data)
+{
+ struct lbm_config *c = user_data;
+
+ _D("%s,%s,%s.", result->section, result->name, result->value);
+
+ if (!c)
+ return -EINVAL;
+
+ if (!MATCH(result->section, "Display"))
+ return 0;
+
+ if (MATCH(result->name, "LBMsupport")) {
+ c->support = (MATCH(result->value, "yes") ? 1 : 0);
+ _D("lbm support is %d", c->support);
+ } else if (MATCH(result->name, "Level")) {
+ SET_CONF(c->down_level, atoi(result->value));
+ _D("lbm down level is %d", c->down_level);
+ } else if (MATCH(result->name, "BrtTable")) {
+ lbm_table_load(result->value, c);
+ _D("LBM table loaded.");
+ }
+
+ return 0;
+}
+
+static void lbm_mode_changed(keynode_t *key_nodes, void *data)
+{
+ int mode = vconf_keynode_get_bool(key_nodes);
+
+ _I("LBM setting value is %s.", mode ? "enable" : "disable");
+
+ lbm_setting_mode = mode;
+
+ if (lbm_get_state())
+ lbm_set_state(false);
+}
+
+static int display_off_changed(void *data)
+{
+ int brt;
+
+ backlight_ops.get_brightness(&brt);
+ backlight_ops.restore_brightness_func();
+ backlight_ops.set_brightness(brt);
+
+ lbm_state = 0;
+
+ return 0;
+}
+
+static GVariant *dbus_getlbm(GDBusConnection *conn,
+ const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+ GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int lbm;
+
+ lbm = lbm_get_state();
+ if (lbm < 0)
+ _E("Failed to get low brightness mode %d.", lbm);
+ else
+ _D("Get low brightness mode %d.", lbm);
+
+ return g_variant_new("(i)", lbm);
+}
+
+static const dbus_method_s dbus_methods[] = {
+ { "GetLBM", NULL, "i", dbus_getlbm },
+};
+
+static const dbus_interface_u dbus_interface = {
+ .oh = NULL,
+ .name = DEVICED_INTERFACE_DISPLAY,
+ .methods = dbus_methods,
+ .nr_methods = ARRAY_SIZE(dbus_methods),
+};
+static void lbm_init(void *data)
+{
+ int ret;
+
+ /* load configutation */
+ ret = config_parse(DISPLAY_CONF_FILE, lbm_load_config, &lbm_conf);
+ if (ret < 0)
+ _W("Failed to load %s, %d. Use default value.", DISPLAY_CONF_FILE, ret);
+
+ ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, &lbm_setting_mode);
+ if (ret < 0)
+ _E("Failed to get VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, %d.", ret);
+
+ vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, lbm_mode_changed, NULL);
+
+ ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_DISPLAY, &dbus_interface);
+ if (ret < 0)
+ _E("Failed to init dbus method, %d.", ret);
+
+ display_dev = display_dev_get();
+
+ _I("LBM setting value is %d.", lbm_setting_mode);
+
+ /* register notifier */
+ register_notifier(DEVICE_NOTIFIER_LCD_OFF_COMPLETE, display_off_changed);
+}
+
+static const struct display_ops display_lbm_ops = {
+ .name = "lbm",
+ .init = lbm_init,
+};
+
+DISPLAY_OPS_REGISTER(&display_lbm_ops)
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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.
+ */
+
+/**
+ * @file lbm.h
+ * @brief Low Brightness Mode header file
+ */
+#ifndef __LBM_H__
+#define __LBM_H__
+
+/*
+ * @brief Configuration structure
+ */
+struct lbm_config {
+ int support;
+ int down_level;
+ int brt_table_size;
+ int *brt_table;
+ int aod_brightness_level;
+};
+
+/*
+ * Global variables
+ * lbm_conf : configuration of lbm
+ */
+struct lbm_config lbm_conf;
+
+int lbm_get_state(void);
+int lbm_set_state(int lbm);
+
+/**
+ * @}
+ */
+
+#endif
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+
+#ifndef __DISPLAY_WEAKS_H__
+#define __DISPLAY_WEAKS_H__
+
+#include "core/common.h"
+#include "display/core.h"
+
+bool __WEAK__ get_outdoor_setting(void);
+
+#endif
+