tizen 2.3 release
[framework/system/deviced.git] / src / display / alpm.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19
20 #include <stdbool.h>
21 #include <fcntl.h>
22
23 #include "util.h"
24 #include "core.h"
25 #include "display-ops.h"
26 #include "weaks.h"
27 #include "core/edbus-handler.h"
28 #include "core/devices.h"
29
30 /*
31  * this definition will be removed,
32  * after the key is merge to all branch.
33  */
34 #ifndef VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL
35 #define VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL "db/setting/ambient_mode"
36 #endif
37
38 #define ALPM_BUS_NAME           "org.tizen.graphics.alpmclock"
39 #define ALPM_OBJECT_PATH        "/Org/Tizen/Graphics/AlpmClock"
40 #define ALPM_PATH_LCD           ALPM_OBJECT_PATH"/LCD"
41 #define ALPM_INTERFACE_LCD      ALPM_BUS_NAME".LCD"
42 #define ALPM_NODE_STATUS        "alpm_node_status"
43
44 #define ON              "on"
45 #define OFF             "off"
46
47 #define SIGNAL_ALPM_ON                  "ALPMOn"
48 #define SIGNAL_ALPM_OFF                 "ALPMOff"
49 #define CLOCK_START                     "clockstart"
50 #define CLOCK_END                       "clockend"
51 #define TIMEOUT_NONE                    (-1)
52 #define ALPM_CLOCK_WAITING_TIME 5000 /* ms */
53
54 static char *alpm_path;
55 static int update_count;
56 static int alpm_state;
57 static pid_t alpm_pid;
58 static int ambient_mode;
59
60 int get_ambient_mode(void)
61 {
62         return ambient_mode;
63 }
64
65 void broadcast_alpm_state(int state)
66 {
67         char *signal;
68
69         signal = (state == true ? SIGNAL_ALPM_ON : SIGNAL_ALPM_OFF);
70
71         broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
72             signal, NULL, NULL);
73 }
74
75 bool check_suspend_direct(pid_t pid)
76 {
77         struct state *st;
78
79         if (pm_cur_state == S_NORMAL ||
80             pm_cur_state == S_LCDDIM)
81                 return false;
82
83         if (pid != alpm_pid)
84                 return false;
85
86         if (check_lock_state(S_SLEEP) == true)
87                 return false;
88
89         if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF)
90                 return false;
91
92         _I("goto sleep state direct!");
93
94         reset_timeout(TIMEOUT_NONE);
95         pm_old_state = pm_cur_state;
96         pm_cur_state = S_SLEEP;
97         st = &states[pm_cur_state];
98
99         if (st->action)
100                 st->action(TIMEOUT_NONE);
101
102         return true;
103 }
104
105 int alpm_get_state(void)
106 {
107         char state[4];
108         int ret, alpm;
109
110         if (!alpm_path)
111                 return -ENODEV;
112
113         ret = sys_get_str(alpm_path, state);
114         if (ret < 0)
115                 return ret;
116
117         if (!strncmp(state, ON, strlen(ON)))
118                 alpm = true;
119         else if (!strncmp(state, OFF, strlen(OFF)))
120                 alpm = false;
121         else
122                 alpm = -EINVAL;
123
124         return alpm;
125 }
126
127 int alpm_set_state(int on)
128 {
129         if (!ambient_mode)
130                 return 0;
131
132         if (!alpm_path)
133                 return -ENODEV;
134
135         broadcast_alpm_state(on);
136
137         update_count = 0;
138
139         if (!on)
140                 alpm_pid = 0;
141
142         _D("ALPM is %s", (on ? ON : OFF));
143
144         alpm_state = on;
145
146         return sys_set_str(alpm_path, (on ? ON : OFF));
147 }
148
149 int check_alpm_lcdon_ready(void)
150 {
151         int ret;
152
153         if (!ambient_mode) {
154                 _E("It's not always on mode");
155                 return 0;
156         }
157
158         if (alpm_get_state() == false) {
159                 _E("Now alpm node is off!");
160                 return 0;
161         }
162
163         _D("wating until updating alpm clock");
164
165         ret = dbus_method_sync(ALPM_BUS_NAME,
166                 ALPM_PATH_LCD, ALPM_INTERFACE_LCD,
167                 ALPM_NODE_STATUS, NULL, NULL);
168
169         _D("it's ready for lcd on");
170
171         return ret;
172 }
173
174 void check_alpm_invalid_state(void)
175 {
176         if (backlight_ops.get_lcd_power() == PM_LCD_POWER_OFF)
177                 return;
178
179         if (alpm_get_state() == false)
180                 return;
181
182         _E("Invalid state! alpm state is change to off!");
183
184         /* If lcd_power is on and alpm state is true
185          * when pm state is changed to sleep
186          * deviced doesn't get the clock signal.
187          * deviced just turns off lcd in this case. */
188
189         alpm_set_state(false);
190         backlight_ops.off(NORMAL_MODE);
191 }
192
193 static void start_clock(void)
194 {
195         if (pm_cur_state == S_NORMAL ||
196             pm_cur_state == S_LCDDIM ||
197             alpm_state == false)
198                 return;
199
200         pm_lock_internal(INTERNAL_LOCK_ALPM,
201             LCD_OFF, STAY_CUR_STATE, ALPM_CLOCK_WAITING_TIME);
202 }
203
204 static void end_clock(pid_t pid)
205 {
206         if (pm_cur_state == S_NORMAL ||
207             pm_cur_state == S_LCDDIM ||
208             alpm_state == false)
209                 return;
210
211         if (update_count == 0) {
212                 _D("lcd off");
213                 backlight_ops.off(NORMAL_MODE);
214                 pm_unlock_internal(INTERNAL_LOCK_ALPM,
215                     LCD_OFF, PM_SLEEP_MARGIN);
216         }
217
218         update_count++;
219
220         _I("enter real alpm state by %d (%d)",
221             alpm_pid, update_count);
222
223         alpm_pid = pid;
224 }
225
226 int set_alpm_screen(char *screen, pid_t pid)
227 {
228         if (!screen)
229                 return -EINVAL;
230
231         if (!alpm_path)
232                 return -ENODEV;
233
234         if (!strncmp(screen, CLOCK_START,
235             strlen(CLOCK_START))) {
236                 start_clock();
237         } else if (!strncmp(screen, CLOCK_END,
238             strlen(CLOCK_END))) {
239                 end_clock(pid);
240         }
241
242         return 0;
243 }
244
245 static void set_ambient_mode(keynode_t *key_nodes, void *data)
246 {
247         if (key_nodes == NULL) {
248                 _E("wrong parameter, key_nodes is null");
249                 return;
250         }
251
252         ambient_mode = vconf_keynode_get_bool(key_nodes);
253         _I("ambient mode is %d", ambient_mode);
254
255         if (!ambient_mode)
256                 pm_unlock_internal(INTERNAL_LOCK_ALPM, LCD_OFF,
257                     PM_SLEEP_MARGIN);
258
259         set_dim_state(ambient_mode ? false : true);
260 }
261
262 static void alpm_init(void *data)
263 {
264         int fd;
265         int ret;
266
267         ret = vconf_get_bool(VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL,
268             &ambient_mode);
269         if (ret < 0) {
270                 _E("Failed to get ambient mode! (%d)", ret);
271                 ambient_mode = false;
272         }
273         _I("ambient mode is %d", ambient_mode);
274
275         vconf_notify_key_changed(VCONFKEY_SETAPPL_AMBIENT_MODE_BOOL,
276             set_ambient_mode, NULL);
277
278         alpm_path = getenv("ALPM_NODE");
279
280         /* Check alpm node is valid */
281         fd = open(alpm_path, O_RDONLY);
282         if (fd < 0) {
283                 _E("alpm node is invalid");
284                 alpm_path = NULL;
285                 return;
286         } else {
287                 _I("alpm path[%s] is initialized!", alpm_path);
288         }
289         close(fd);
290 }
291
292 static void alpm_exit(void *data)
293 {
294         alpm_set_state(false);
295 }
296
297 static const struct display_ops display_alpm_ops = {
298         .name     = "alpm",
299         .init     = alpm_init,
300         .exit     = alpm_exit,
301 };
302
303 DISPLAY_OPS_REGISTER(&display_alpm_ops)
304