summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortaeyoung <ty317.kim@samsung.com>2017-03-18 17:13:54 +0900
committerlokilee73 <changjoo.lee@samsung.com>2017-04-04 15:47:17 +0900
commit8d0ea5a283913979fd13433bd79dca9037b478e7 (patch)
tree778ba9e3005acf15273022bd890b306552f40e98
parentd21aa8a09e168abd2168a43719b0572a891f0b30 (diff)
downloaddeviced-8d0ea5a283913979fd13433bd79dca9037b478e7.tar.gz
deviced-8d0ea5a283913979fd13433bd79dca9037b478e7.tar.bz2
deviced-8d0ea5a283913979fd13433bd79dca9037b478e7.zip
display: add ambient mode
- Ambient mode turns off the CPU but does not turn off the display. - Currently, turning off CPU is not supported by kernel, and thus just display operation is added. - "ambient condition" value shows that the Ambient Mode is allowed or not by the User trough the settings app. This value is handled by vconf key VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL. Even if the value is true, the target can be the normal mode (not Ambient Mode). - "ambient state" value shows whether or not the Ambient Mode is enabled. "ambient state" can be true only if "ambient condition" is true. - If "ambient condition" is true, display off operation works little bit different. The operation checks "ambient condition" value and enables the Ambient Mode by setting "ambient state". The Ambient Mode is one of the display off states, and thus "LCDOff" and "LCDOffCompleted" signal also need to be broadcasted like the normal mode. However, the "LCDOffCompleted" signal is broadcasted after launching ambient clock. For the operation, "HomeScreen" signal is delivered from the ambient clock application. Change-Id: I4630459d8af1c8f179009c1b325b983a352efdf3 Signed-off-by: taeyoung <ty317.kim@samsung.com>
-rw-r--r--src/core/device-notifier.h2
-rw-r--r--src/core/devices.h1
-rw-r--r--src/display/ambient-mode.c209
-rw-r--r--src/display/ambient-mode.h30
-rw-r--r--src/display/core.c58
-rw-r--r--src/display/core.h2
-rw-r--r--src/display/device-interface.c14
-rw-r--r--src/display/display-dbus.c41
-rw-r--r--src/display/key-filter.c14
-rw-r--r--src/display/poll.h1
-rw-r--r--src/display/setting.c6
-rw-r--r--src/touchscreen/touchscreen.c2
12 files changed, 373 insertions, 7 deletions
diff --git a/src/core/device-notifier.h b/src/core/device-notifier.h
index 349e55de..087edb36 100644
--- a/src/core/device-notifier.h
+++ b/src/core/device-notifier.h
@@ -33,6 +33,8 @@ enum device_notifier_type {
DEVICE_NOTIFIER_BATTERY_PRESENT,
DEVICE_NOTIFIER_BATTERY_OVP,
DEVICE_NOTIFIER_BATTERY_CHARGING,
+ DEVICE_NOTIFIER_DISPLAY_AMBIENT_CONDITION,
+ DEVICE_NOTIFIER_DISPLAY_AMBIENT_STATE,
DEVICE_NOTIFIER_DISPLAY_LOCK,
DEVICE_NOTIFIER_POWER_RESUME,
DEVICE_NOTIFIER_POWEROFF,
diff --git a/src/core/devices.h b/src/core/devices.h
index 68a90f10..40f73682 100644
--- a/src/core/devices.h
+++ b/src/core/devices.h
@@ -31,6 +31,7 @@ enum device_priority {
enum device_flags {
NORMAL_MODE = 0x00000001,
+ AMBIENT_MODE = 0x00000002,
CORE_LOGIC_MODE = 0x00010000,
TOUCH_SCREEN_OFF_MODE = 0x00020000,
LCD_PANEL_OFF_MODE = 0x00040000,
diff --git a/src/display/ambient-mode.c b/src/display/ambient-mode.c
new file mode 100644
index 00000000..3c1d64c2
--- /dev/null
+++ b/src/display/ambient-mode.c
@@ -0,0 +1,209 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 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 "util.h"
+#include "core.h"
+#include "display-ops.h"
+#include "core/edbus-handler.h"
+#include "core/device-notifier.h"
+#include "core/devices.h"
+
+#define ON "on"
+#define OFF "off"
+
+#define SIGNAL_AMBIENT_MODE "AmbientMode"
+#define CLOCK_START "clockstart"
+#define CLOCK_END "clockend"
+#define TIMEOUT_NONE (-1)
+#define AMBIENT_CLOCK_WAITING_TIME 5000 /* ms */
+
+static int ambient_state;
+static pid_t ambient_pid; /* Ambient Clock pid */
+static int ambient_condition;
+static unsigned int update_count;
+
+void broadcast_ambient_state(int state)
+{
+ char *param[1];
+ char st[8];
+
+ snprintf(st, sizeof(st), "%d", (state == 0 ? 0 : 1));
+ param[0] = st;
+
+ broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
+ SIGNAL_AMBIENT_MODE, "i", param);
+}
+
+int ambient_get_condition(void)
+{
+ return ambient_condition;
+}
+
+int ambient_get_state(void)
+{
+ return ambient_state;
+}
+
+static void ambient_set_condition(keynode_t *key_nodes, void *data)
+{
+ int state;
+
+ if (key_nodes == NULL) {
+ _E("wrong parameter, key_nodes is null");
+ return;
+ }
+
+ ambient_condition = vconf_keynode_get_bool(key_nodes);
+ _I("ambient mode condition is %d", ambient_condition);
+
+ state = (ambient_condition == 0 ? 0 : 1);
+ device_notify(DEVICE_NOTIFIER_DISPLAY_AMBIENT_CONDITION, (void *)&state);
+
+ set_dim_state(state);
+}
+
+int ambient_set_state(int on)
+{
+ if (!ambient_condition)
+ return 0;
+
+ broadcast_ambient_state(on);
+
+ update_count = 0;
+
+ if (!on)
+ ambient_pid = 0;
+
+ _D("AMBIENT is %s", (on ? ON : OFF));
+
+ ambient_state = on;
+
+ device_notify(DEVICE_NOTIFIER_DISPLAY_AMBIENT_STATE, (void *)&ambient_state);
+
+ return 0;
+}
+
+void ambient_check_invalid_state(pid_t pid)
+{
+ if (pid != INTERNAL_LOCK_AMBIENT)
+ return;
+
+ if (backlight_ops.get_lcd_power() == DPMS_OFF)
+ return;
+
+ if (is_emulator()) {
+ /* In emulator, deviced does not turn off the display. */
+ if (backlight_ops.get_lcd_power() == DPMS_ON)
+ return;
+ }
+
+ if (ambient_get_state() == false)
+ return;
+
+ _E("Invalid state! Ambient state is change to off!");
+
+ /* If lcd_power is on and ambient state is true
+ * when pm state is changed to sleep,
+ * deviced doesn't get the clock signal.
+ * deviced just turns off lcd in this case. */
+
+ ambient_set_state(false);
+ backlight_ops.off(NORMAL_MODE);
+}
+
+static void start_clock(void)
+{
+ if (pm_cur_state == S_NORMAL ||
+ pm_cur_state == S_LCDDIM ||
+ ambient_state == false)
+ return;
+
+ pm_lock_internal(INTERNAL_LOCK_AMBIENT,
+ LCD_OFF, STAY_CUR_STATE, AMBIENT_CLOCK_WAITING_TIME);
+}
+
+static void end_clock(pid_t pid)
+{
+ if (pm_cur_state == S_NORMAL ||
+ pm_cur_state == S_LCDDIM ||
+ ambient_state == false)
+ return;
+
+ if (update_count == 0)
+ broadcast_lcd_off_late(LCD_OFF_LATE_MODE);
+
+ pm_unlock_internal(INTERNAL_LOCK_AMBIENT,
+ LCD_OFF, PM_SLEEP_MARGIN);
+
+ update_count++;
+ if (update_count == UINT_MAX)
+ update_count = 1;
+ ambient_pid = pid;
+
+ _I("enter real ambient state by %d",
+ ambient_pid);
+}
+
+int ambient_set_screen(char *screen, pid_t pid)
+{
+ if (!screen)
+ return -EINVAL;
+
+ if (!strncmp(screen, CLOCK_START, strlen(CLOCK_START)))
+ start_clock();
+ else if (!strncmp(screen, CLOCK_END, strlen(CLOCK_END)))
+ end_clock(pid);
+
+ return 0;
+}
+
+static void ambient_init(void *data)
+{
+ int ret;
+
+ ret = vconf_get_bool(VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL,
+ &ambient_condition);
+ if (ret < 0) {
+ _E("Failed to get ambient mode condition ! (%d)", ret);
+ ambient_condition = false;
+ }
+ _I("ambient mode condition is %d", ambient_condition);
+
+ vconf_notify_key_changed(VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL,
+ ambient_set_condition, NULL);
+}
+
+static void ambient_exit(void *data)
+{
+ ambient_set_state(false);
+ vconf_ignore_key_changed(VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL,
+ ambient_set_condition);
+}
+
+static const struct display_ops ambient_ops = {
+ .name = "ambient",
+ .init = ambient_init,
+ .exit = ambient_exit,
+};
+
+DISPLAY_OPS_REGISTER(&ambient_ops)
+
diff --git a/src/display/ambient-mode.h b/src/display/ambient-mode.h
new file mode 100644
index 00000000..7c74187d
--- /dev/null
+++ b/src/display/ambient-mode.h
@@ -0,0 +1,30 @@
+/*
+ * deviced
+ *
+ * Copyright (c) 2012 - 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.
+ */
+
+#ifndef __AMBIENT_MODE_H__
+#define __AMBIENT_MODE_H__
+
+#define AMBIENT_CLOCK_WAITING_TIME 5000 /* ms */
+
+int ambient_get_condition(void);
+int ambient_get_state(void);
+int ambient_set_state(int on);
+void ambient_check_invalid_state(pid_t pid);
+int ambient_set_screen(char *screen, pid_t pid);
+
+#endif /* __AMBIENT_MODE_H__ */
diff --git a/src/display/core.c b/src/display/core.c
index 5ae406de..346deeba 100644
--- a/src/display/core.c
+++ b/src/display/core.c
@@ -39,6 +39,7 @@
#include <Ecore.h>
#include <tzplatform_config.h>
+#include "ambient-mode.h"
#include "util.h"
#include "core.h"
#include "device-node.h"
@@ -340,6 +341,16 @@ static void broadcast_lcd_off(enum signal_type type, enum device_flags flags)
signal, "s", arr);
}
+void broadcast_lcd_off_late(enum device_flags flags)
+{
+ static enum device_flags late_flags;
+
+ if (flags & LCD_OFF_LATE_MODE)
+ broadcast_lcd_off(SIGNAL_POST, late_flags);
+ else
+ late_flags = flags;
+}
+
static unsigned long get_lcd_on_flags(void)
{
unsigned long flags = NORMAL_MODE;
@@ -350,6 +361,11 @@ static unsigned long get_lcd_on_flags(void)
if (stay_touchscreen_off)
flags |= TOUCH_SCREEN_OFF_MODE;
+ if (ambient_get_condition() == true) {
+ flags |= AMBIENT_MODE;
+ flags |= LCD_PHASED_TRANSIT_MODE;
+ }
+
return flags;
}
@@ -371,6 +387,13 @@ void lcd_on_procedure(int state, enum device_flags flag)
lcdon_broadcast = true;
}
+ if (flags & AMBIENT_MODE) {
+ if (ambient_get_state() == false &&
+ backlight_ops.get_lcd_power() == DPMS_ON)
+ return;
+ ambient_set_state(false);
+ }
+
if (!(flags & LCD_PHASED_TRANSIT_MODE)) {
/* Update brightness level */
if (state == LCD_DIM)
@@ -395,16 +418,33 @@ void lcd_on_procedure(int state, enum device_flags flag)
touch_blocked = false;
}
+static inline unsigned long get_lcd_off_flags(void)
+{
+ unsigned long flags = NORMAL_MODE;
+
+ if (ambient_get_condition() == true) {
+ flags |= AMBIENT_MODE;
+ flags |= LCD_PHASED_TRANSIT_MODE;
+ }
+
+ return flags;
+}
+
+
inline void lcd_off_procedure(enum device_flags flag)
{
dd_list *l = NULL;
const struct device_ops *ops = NULL;
- unsigned long flags = NORMAL_MODE;
+ unsigned long flags = get_lcd_off_flags();
flags |= flag;
touch_blocked = true;
- set_setting_pmstate(S_LCDOFF);
+ if (flags & AMBIENT_MODE) {
+ if (ambient_get_state() == true)
+ return;
+ ambient_set_state(true);
+ }
if (lcdon_broadcast) {
broadcast_lcd_off(SIGNAL_PRE, flags);
@@ -413,10 +453,18 @@ inline void lcd_off_procedure(enum device_flags flag)
if (CHECK_OPS(keyfilter_ops, backlight_enable))
keyfilter_ops->backlight_enable(false);
+ set_setting_pmstate(S_LCDOFF);
+
DD_LIST_REVERSE_FOREACH(lcdon_ops, l, ops)
ops->stop(flags);
- broadcast_lcd_off(SIGNAL_POST, flags);
+ if (flags & AMBIENT_MODE)
+ /* Do not broadcast the post signal here.
+ * The signal will be broadcasted
+ * after showing Ambient clock */
+ broadcast_lcd_off_late(flags);
+ else
+ broadcast_lcd_off(SIGNAL_POST, flags);
}
void set_stay_touchscreen_off(int val)
@@ -962,6 +1010,9 @@ static void proc_condition_unlock(PMMsg *data)
if (state == S_LCDOFF)
set_process_active(EINA_FALSE, pid);
+ if (ambient_get_state())
+ ambient_check_invalid_state(pid);
+
_SD("[%s] unlocked by pid %d - process %s\n",
states[state].name, pid, pname);
set_unlock_time(pname, state);
@@ -2136,6 +2187,7 @@ static void display_init(void *data)
register_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground);
register_notifier(DEVICE_NOTIFIER_POWEROFF, device_poweroff);
+
for (i = INIT_SETTING; i < INIT_END; i++) {
switch (i) {
case INIT_SETTING:
diff --git a/src/display/core.h b/src/display/core.h
index 6908c9ec..f835c299 100644
--- a/src/display/core.h
+++ b/src/display/core.h
@@ -195,6 +195,8 @@ void lcd_off_procedure(enum device_flags flag);
int check_holdkey_block(enum state_t state);
bool touch_event_blocked(void);
int device_poweroff(void *data);
+void broadcast_lcd_off_late(enum device_flags flags);
+void set_dim_state(bool on);
/* poll.c */
int check_dimstay(int next_state, int flag);
diff --git a/src/display/device-interface.c b/src/display/device-interface.c
index 79aca9f4..1ed8b013 100644
--- a/src/display/device-interface.c
+++ b/src/display/device-interface.c
@@ -31,6 +31,7 @@
#include <errno.h>
#include <hw/display.h>
+#include "ambient-mode.h"
#include "core/log.h"
#include "core/devices.h"
#include "core/common.h"
@@ -116,7 +117,7 @@ static int bl_onoff(int on)
if (!display_dev || !display_dev->set_state)
return dpms_set_power(on);
- switch(on) {
+ switch (on) {
case DPMS_ON:
val = DISPLAY_ON;
break;
@@ -213,6 +214,9 @@ static int get_lcd_power(void)
enum display_state val;
int ret;
+ if (ambient_get_state())
+ return DPMS_OFF;
+
if (!display_dev || !display_dev->get_state) {
ret = dpms_get_power(&state);
if (ret < 0)
@@ -224,7 +228,7 @@ static int get_lcd_power(void)
if (ret < 0)
return ret;
- switch(val) {
+ switch (val) {
case DISPLAY_ON:
return DPMS_ON;
case DISPLAY_STANDBY:
@@ -298,6 +302,9 @@ static int backlight_off(enum device_flags flags)
_I("LCD off %x", flags);
+ if (flags & AMBIENT_MODE)
+ return 0;
+
ret = bl_onoff(DPMS_OFF);
if (ret < 0)
_E("Failed to turn off backlight (%d)", ret);
@@ -332,6 +339,9 @@ static int backlight_off(enum device_flags flags)
change_brightness(default_brightness,
LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
+ if (flags & AMBIENT_MODE)
+ return 0;
+
ret = bl_onoff(DPMS_OFF);
if (ret < 0)
_E("Failed to turn off backlight");
diff --git a/src/display/display-dbus.c b/src/display/display-dbus.c
index 9a5e1218..9cff1485 100644
--- a/src/display/display-dbus.c
+++ b/src/display/display-dbus.c
@@ -28,6 +28,7 @@
#include <Ecore.h>
#include <device-node.h>
+#include "ambient-mode.h"
#include "core/log.h"
#include "util.h"
#include "core.h"
@@ -39,6 +40,8 @@
#include "display-actor.h"
#include "display-ops.h"
+#define SIGNAL_HOMESCREEN "HomeScreen"
+
#define DISPLAY_DIM_BRIGHTNESS 0
#define DUMP_MODE_WATING_TIME 600000
@@ -1232,6 +1235,36 @@ static const struct edbus_method edbus_methods[] = {
/* Add methods here */
};
+static void homescreen_signal_handler(void *data, DBusMessage *msg)
+{
+ DBusError err;
+ int ret;
+ char *screen;
+ pid_t pid;
+
+ ret = dbus_message_is_signal(msg, DEVICED_INTERFACE_NAME,
+ SIGNAL_HOMESCREEN);
+ if (!ret) {
+ _E("there is no homescreen signal");
+ return;
+ }
+
+ dbus_error_init(&err);
+
+ ret = dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &screen,
+ DBUS_TYPE_INVALID);
+ if (!ret) {
+ _E("no message : [%s:%s]", err.name, err.message);
+ dbus_error_free(&err);
+ }
+
+ _D("screen : %s", screen);
+
+ pid = get_edbus_sender_pid(msg);
+ ambient_set_screen(screen, pid);
+}
+
+
/*
* Default capability
* api := LCDON | LCDOFF | BRIGHTNESS
@@ -1263,6 +1296,14 @@ int init_pm_dbus(void)
return ret;
}
+ ret = register_edbus_signal_handler(DEVICED_OBJECT_PATH,
+ DEVICED_INTERFACE_NAME, SIGNAL_HOMESCREEN,
+ homescreen_signal_handler);
+ if (ret < 0 && ret != -EEXIST) {
+ _E("Failed to register signal handler! %d", ret);
+ return ret;
+ }
+
return 0;
}
diff --git a/src/display/key-filter.c b/src/display/key-filter.c
index ede465fd..9ba15da4 100644
--- a/src/display/key-filter.c
+++ b/src/display/key-filter.c
@@ -24,6 +24,8 @@
#include <assert.h>
#include <vconf.h>
#include <Ecore.h>
+
+#include "ambient-mode.h"
#include "util.h"
#include "core.h"
#include "poll.h"
@@ -196,8 +198,10 @@ static inline bool switch_on_lcd(void)
if (current_state_in_on())
return false;
- if (backlight_ops.get_lcd_power() == DPMS_ON)
- return false;
+ if (backlight_ops.get_lcd_power() == DPMS_ON) {
+ if (ambient_get_state() == false)
+ return false;
+ }
broadcast_lcdon_by_powerkey();
@@ -607,6 +611,12 @@ static int check_key_filter(void *data, int fd)
case EV_ABS:
if (current_state_in_on())
ignore = false;
+
+ if (ambient_get_condition() == true) {
+ switch_on_lcd();
+ ignore = false;
+ }
+
restore_custom_brightness();
touch_pressed =
diff --git a/src/display/poll.h b/src/display/poll.h
index 2f236b6a..361b877e 100644
--- a/src/display/poll.h
+++ b/src/display/poll.h
@@ -61,6 +61,7 @@ enum {
INTERNAL_LOCK_POWERKEY,
INTERNAL_LOCK_PM,
INTERNAL_LOCK_HALLIC,
+ INTERNAL_LOCK_AMBIENT,
};
#define SIGNAL_NAME_LCD_CONTROL "lcdcontol"
diff --git a/src/display/setting.c b/src/display/setting.c
index f45c40e8..10e33874 100644
--- a/src/display/setting.c
+++ b/src/display/setting.c
@@ -24,6 +24,7 @@
#include <bundle.h>
#include <eventsystem.h>
+#include "ambient-mode.h"
#include "core.h"
#include "util.h"
#include "setting.h"
@@ -149,6 +150,11 @@ void get_dim_timeout(int *dim_timeout)
return;
}
+ if (ambient_get_condition() == true) {
+ *dim_timeout = LCD_MIN_DIM_TIMEOUT;
+ return;
+ }
+
ret = vconf_get_int(setting_keys[SETTING_TO_NORMAL], &vconf_timeout);
if (ret != 0) {
_E("Failed ro get setting timeout!");
diff --git a/src/touchscreen/touchscreen.c b/src/touchscreen/touchscreen.c
index 4ddfee97..17a908fe 100644
--- a/src/touchscreen/touchscreen.c
+++ b/src/touchscreen/touchscreen.c
@@ -106,6 +106,8 @@ static int touchscreen_start(enum device_flags flags)
static int touchscreen_stop(enum device_flags flags)
{
+ if (flags & AMBIENT_MODE)
+ return 0;
return touchscreen_set_state(TOUCHSCREEN_OFF);
}