1abb336013107cbe39fb382ebb82d60a4bb973cb
[apps/native/starter.git] / src / wearable / hw_key.c
1 /*
2  * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <bundle.h>
18 #include <Elementary.h>
19 #include <Ecore_Input.h>
20 #include <Ecore_Wl2.h>
21
22 #include <dd-display.h>
23 #include <feedback.h>
24 #include <vconf.h>
25 #include <aul.h>
26 #include <rua.h>
27 #include <pkgmgr-info.h>
28
29 #include "hw_key.h"
30 #include "util.h"
31 #include "status.h"
32 #include "dbus_util.h"
33 #include "home_mgr.h"
34 #include "process_mgr.h"
35
36 #define LONG_PRESS_TIMER_SEC 0.7
37 #define POWERKEY_LCDOFF_TIMER_SEC 0.4
38 #define POWERKEY_TIMER_SEC 0.25
39
40 #define APP_CONTROL_OPERATION_MAIN_KEY "__APP_SVC_OP_TYPE__"
41 #define APP_CONTROL_OPERATION_MAIN_VALUE "http://tizen.org/appcontrol/operation/main"
42
43 #define USE_DBUS_POWEROFF 1
44
45 const char *key_name[KEY_NAME_MAX] = {
46         "XF86AudioRaiseVolume",
47         "XF86AudioLowerVolume",
48         "XF86PowerOff",
49         "XF86Menu",
50         "XF86Home",
51         "XF86Back",
52         "XF86Camera",
53         "XF86Camera_Full",
54         "XF86Search",
55         "XF86AudioPlay",
56         "XF86AudioPause",
57         "XF86AudioStop",
58         "XF86AudioNext",
59         "XF86AudioPrev",
60         "XF86AudioRewind",
61         "XF86AudioForward",
62         "XF86AudioMedia",
63         "XF86AudioPlayPause",
64         "XF86AudioMute",
65         "XF86AudioRecord",
66         "Cancel",
67         "XF86SoftKBD",
68         "XF86QuickPanel",
69         "XF86TaskPane",
70         "XF86HomePage",
71         "XF86WWW",
72         "XF86Mail",
73         "XF86ScreenSaver",
74         "XF86MonBrightnessDown",
75         "XF86MonBrightnessUp",
76         "XF86Voice",
77         "Hangul",
78         "XF86Apps",
79         "XF86Call",
80         "XF86Game",
81         "XF86VoiceWakeUp_LPSD",
82         "XF86VoiceWakeUp",
83 };
84
85 static struct {
86         Ecore_Event_Handler *key_up;
87         Ecore_Event_Handler *key_down;
88         Ecore_Timer *home_long_press_timer;
89         Ecore_Timer *home_multi_press_timer;
90         Ecore_Timer *keygrab_timer;
91         Eina_Bool cancel;
92         int homekey_count;
93
94         Ecore_Timer *power_long_press_timer;
95         Ecore_Timer *power_release_timer;
96         Eina_Bool is_lcd_on;
97         Eina_Bool is_long_press;
98         int powerkey_count;
99         Eina_Bool is_cancel;
100         Eina_Bool is_home_focused;
101 } key_info = {
102         .key_up = NULL,
103         .key_down = NULL,
104         .home_long_press_timer = NULL,
105         .home_multi_press_timer = NULL,
106         .keygrab_timer = NULL,
107         .cancel = EINA_FALSE,
108         .homekey_count = 0,
109
110         .power_long_press_timer = NULL,
111         .power_release_timer = NULL,
112         .is_lcd_on = EINA_FALSE,
113         .is_long_press = EINA_FALSE,
114         .powerkey_count = 0,
115         .is_cancel = EINA_FALSE,
116         .is_home_focused = EINA_FALSE,
117 };
118
119
120
121 static Eina_Bool _long_press_timer_cb(void* data)
122 {
123         key_info.power_long_press_timer = NULL;
124         key_info.is_long_press = EINA_TRUE;
125         key_info.powerkey_count = 0;
126
127         if (0 < status_passive_get()->remote_lock_islocked) {
128                 _W("remote lock is on top (%d), -> just turn off LCD", status_passive_get()->remote_lock_islocked);
129                 return ECORE_CALLBACK_CANCEL;
130         }
131
132         if (key_info.power_release_timer) {
133                 ecore_timer_del(key_info.power_release_timer);
134                 key_info.power_release_timer = NULL;
135                 _D("delete power_release_timer");
136         }
137
138 #if USE_DBUS_POWEROFF
139         dbus_util_send_poweroff_signal();
140 #else
141         _D("launch power off syspopup");
142         process_mgr_syspopup_launch("poweroff-syspopup", NULL, NULL, NULL, NULL);
143 #endif
144
145         feedback_initialize();
146         feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_HOLD);
147         feedback_deinitialize();
148
149         return ECORE_CALLBACK_CANCEL;
150 }
151
152
153
154 static void _launch_last_app(void)
155 {
156         struct rua_rec record;
157         char **table = NULL;
158         int nrows = 0;
159         int ncols = 0;
160         int row = 0;
161         pkgmgrinfo_appinfo_h handle;
162         bool is_taskmanage = false;
163         char *last_app = NULL;
164
165         if (rua_init()) {
166                 _E("Failed to initialize rua");
167                 return;
168         }
169
170         if (rua_history_load_db(&table, &nrows, &ncols) || !table) {
171                 _E("Failed to load rua history db");
172
173                 if (rua_fini()) {
174                         _E("Failed to finalize rua");
175                 }
176
177                 return;
178         }
179
180         for (row = 0; row < nrows; row++) {
181                 if (rua_history_get_rec(&record, table, nrows, ncols, row)) {
182                         _E("Failed to get rua history record");
183                         continue;
184                 }
185
186                 _D("[%d] rua history(%s)", row, record.pkg_name);
187
188                 if (!strcmp(record.pkg_name, HOMESCREEN_PKG_NAME) ||
189                                 !strcmp(record.pkg_name, ISE_DEFAULT_PKG_NAME) ||
190                                 !strcmp(record.pkg_name, status_passive_get()->wms_clocks_set_idle)) {
191                         continue;
192                 }
193
194                 if (PMINFO_R_OK != pkgmgrinfo_appinfo_get_appinfo(record.pkg_name, &handle)) {
195                         _E("Failed to get app info(%s)", record.pkg_name);
196                         continue;
197                 }
198
199                 if (PMINFO_R_OK != pkgmgrinfo_appinfo_is_taskmanage(handle, &is_taskmanage)) {
200                         _E("Failed to get taskmanage info");
201                         pkgmgrinfo_appinfo_destroy_appinfo(handle);
202                         continue;
203                 }
204
205                 if (!is_taskmanage) {
206                         _E("This app(%s) is not showing on taskmanager", record.pkg_name);
207                         pkgmgrinfo_appinfo_destroy_appinfo(handle);
208                         continue;
209                 }
210
211                 if (PMINFO_R_OK != pkgmgrinfo_appinfo_get_pkgid(handle, &last_app)) {
212                         _E("Failed to get pkgid");
213                         pkgmgrinfo_appinfo_destroy_appinfo(handle);
214                         continue;
215                 }
216
217                 if (last_app == NULL) {
218                         _E("last pkg name is NULL");
219                         pkgmgrinfo_appinfo_destroy_appinfo(handle);
220                         continue;
221                 }
222
223                 _D("last app : %s", last_app);
224                 process_mgr_must_launch(last_app, NULL, NULL, NULL, NULL);
225
226                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
227
228                 break;
229         }
230
231         if (rua_history_unload_db(&table)) {
232                 _E("Failed to unload rua history db");
233         }
234
235         if (rua_fini()) {
236                 _E("Failed to finalize rua");
237         }
238 }
239
240
241
242 static void _do_double_home_key_operation(void)
243 {
244         int op = 0;
245         int is_watch_face_shown = 0;
246
247         op = status_passive_get()->setappl_double_press_home_key;
248         _D("Dobule home key operation : %d", op);
249
250         is_watch_face_shown = status_passive_get()->homescreen_watch_face_visibility;
251         _D("Watch face status : %d", is_watch_face_shown);
252
253         switch (op) {
254         case VCONFKEY_DOUBLE_PRESS_HOME_KEY_NONE:
255                 break;
256         case VCONFKEY_DOUBLE_PRESS_HOME_KEY_LAST_APP:
257                 if (is_watch_face_shown) {
258                         _launch_last_app();
259                 } else {
260                         home_mgr_launch_home_by_power((key_info.is_home_focused == EINA_TRUE) ? "powerkey_focused" : "powerkey_unfocused");
261                 }
262                 break;
263         case VCONFKEY_DOUBLE_PRESS_HOME_KEY_RECENT_APPS:
264                 process_mgr_must_launch(TASKMGR_PKG_NAME, NULL, NULL, NULL, NULL);
265                 break;
266         default:
267                 _E("invalid operation(%d)", op);
268                 break;
269         }
270 }
271
272
273
274 static Eina_Bool _powerkey_timer_cb(void *data)
275 {
276         _W("%s, powerkey count[%d]", __func__, key_info.powerkey_count);
277
278         key_info.power_release_timer = NULL;
279
280         if (VCONFKEY_PM_KEY_LOCK == status_passive_get()->pm_key_ignore) {
281                 _E("Critical Low Batt Clock Mode");
282                 key_info.powerkey_count = 0;
283                 if (key_info.is_lcd_on) {
284                         _W("just turn off LCD");
285                         display_change_state(LCD_OFF);
286                 } else {
287                         _W("just turn on LCD by powerkey.. starter ignore powerkey operation");
288                 }
289                 return ECORE_CALLBACK_CANCEL;
290         }
291
292         if (key_info.powerkey_count % 2 == 0) {
293                 /* double press */
294                 _W("powerkey double press");
295                 key_info.powerkey_count = 0;
296                 _do_double_home_key_operation();
297                 return ECORE_CALLBACK_CANCEL;
298         }
299         key_info.powerkey_count = 0;
300
301         if (key_info.is_lcd_on) {
302                 if (VCONFKEY_PM_STATE_LCDOFF <= status_active_get()->pm_state) {
303                         _E("Already lcd state was changed while powerkey op. starter ignore powerkey operation");
304                         return ECORE_CALLBACK_CANCEL;
305                 }
306         } else {
307                 _W("just turn on LCD by powerkey.. starter ignore powerkey operation");
308                 return ECORE_CALLBACK_CANCEL;
309         }
310
311         if (VCONFKEY_CALL_VOICE_ACTIVE == status_passive_get()->call_state) {
312                 _W("call state is [%d] -> just turn off LCD");
313                 display_change_state(LCD_OFF);
314                 return ECORE_CALLBACK_CANCEL;
315         }
316
317         if (VCONFKEY_IDLE_LOCK == status_passive_get()->idle_lock_state) {
318                 _W("lock state is [%d] -> just turn off LCD");
319                 display_change_state(LCD_OFF);
320                 return ECORE_CALLBACK_CANCEL;
321         }
322
323         if (0 < status_passive_get()->remote_lock_islocked) {
324                 _W("remote lock is on top (%d), -> just turn off LCD", status_passive_get()->remote_lock_islocked);
325                 display_change_state(LCD_OFF);
326                 return ECORE_CALLBACK_CANCEL;
327         }
328
329         home_mgr_launch_home_by_power((key_info.is_home_focused == EINA_TRUE) ? "powerkey_focused" : "powerkey_unfocused");
330
331         return ECORE_CALLBACK_CANCEL;
332 }
333
334
335
336 static Eina_Bool _key_release_cb(void *data, int type, void *event)
337 {
338         Evas_Event_Key_Up *ev = event;
339
340         retv_if(!ev, ECORE_CALLBACK_RENEW);
341         retv_if(!ev->keyname, ECORE_CALLBACK_RENEW);
342
343         _D("_key_release_cb : %s Released", ev->keyname);
344
345         if (!strcmp(ev->keyname, key_name[KEY_POWER])) {
346                 _W("POWER Key is released");
347
348                 if (key_info.power_long_press_timer) {
349                         ecore_timer_del(key_info.power_long_press_timer);
350                         key_info.power_long_press_timer = NULL;
351                         _D("delete long press timer");
352                 }
353
354                 // Check powerkey timer
355                 if (key_info.power_release_timer) {
356                         ecore_timer_del(key_info.power_release_timer);
357                         key_info.power_release_timer = NULL;
358                         _D("delete powerkey timer");
359                 }
360
361                 // Cancel key operation
362                 if (EINA_TRUE == key_info.is_cancel) {
363                         _D("Cancel key is activated");
364                         key_info.is_cancel = EINA_FALSE;
365                         key_info.powerkey_count = 0; //initialize powerkey count
366                         return ECORE_CALLBACK_RENEW;
367                 }
368
369                 // Check long press operation
370                 if (key_info.is_long_press) {
371                         _D("ignore power key release by long poress");
372                         key_info.is_long_press = EINA_FALSE;
373                         return ECORE_CALLBACK_RENEW;
374                 }
375
376                 if (key_info.is_lcd_on) {
377                         key_info.power_release_timer = ecore_timer_add(POWERKEY_TIMER_SEC, _powerkey_timer_cb, NULL);
378                 } else {
379                         _D("lcd off --> [%f]sec timer", POWERKEY_LCDOFF_TIMER_SEC);
380                         key_info.power_release_timer = ecore_timer_add(POWERKEY_LCDOFF_TIMER_SEC, _powerkey_timer_cb, NULL);
381                 }
382                 if (!key_info.power_release_timer) {
383                         _E("Critical, cannot add a timer for powerkey");
384                 }
385         } else if (!strcmp(ev->keyname, key_name[KEY_CANCEL])) {
386                 _D("CANCEL Key is released");
387                 key_info.is_cancel = EINA_FALSE;
388         }
389
390         return ECORE_CALLBACK_RENEW;
391 }
392
393
394
395 static Eina_Bool _key_press_cb(void *data, int type, void *event)
396 {
397         Evas_Event_Key_Down *ev = event;
398
399         retv_if(!ev, ECORE_CALLBACK_RENEW);
400         retv_if(!ev->keyname, ECORE_CALLBACK_RENEW);
401
402         _D("_key_press_cb : %s Pressed", ev->keyname);
403
404         if (!strcmp(ev->keyname, key_name[KEY_POWER])) {
405                 int status = 0;
406
407                 _W("POWER Key is pressed");
408
409                 /**
410                  * lcd status
411                  * 1 : lcd normal
412                  * 2 : lcd dim
413                  * 3 : lcd off
414                  * 4 : suspend
415                  */
416                 if (VCONFKEY_PM_STATE_LCDDIM >= status_active_get()->pm_state) {
417                         key_info.is_lcd_on = EINA_TRUE;
418                 } else if (VCONFKEY_PM_STATE_LCDOFF <= status_active_get()->pm_state) {
419                         key_info.is_lcd_on = EINA_FALSE;
420                 }
421
422                 key_info.powerkey_count++;
423                 _W("powerkey count : %d", key_info.powerkey_count);
424
425                 if (key_info.power_release_timer) {
426                         ecore_timer_del(key_info.power_release_timer);
427                         key_info.power_release_timer = NULL;
428                 }
429
430                 if (key_info.power_long_press_timer) {
431                         ecore_timer_del(key_info.power_long_press_timer);
432                         key_info.power_long_press_timer = NULL;
433                 }
434
435                 key_info.is_long_press = EINA_FALSE;
436                 key_info.power_long_press_timer = ecore_timer_add(LONG_PRESS_TIMER_SEC, _long_press_timer_cb, NULL);
437                 if (!key_info.power_long_press_timer) {
438                         _E("Failed to add power_long_press_timer");
439                 }
440
441                 status = aul_app_get_status("org.tizen.w-home");
442                 key_info.is_home_focused = (status == STATUS_FOCUS) ? EINA_TRUE : EINA_FALSE;
443                 _D("home focus status : %d", key_info.is_home_focused);
444         } else if (!strcmp(ev->keyname, key_name[KEY_CANCEL])) {
445                 _D("CANCEL key is pressed");
446                 key_info.is_cancel = EINA_TRUE;
447         }
448
449         return ECORE_CALLBACK_RENEW;
450 }
451
452
453
454 static Eina_Bool __keygrab_timer_cb(void *data)
455 {
456         int i = 0;
457         int ret = 0;
458
459         for (i = 0; i < KEY_NAME_MAX; i++) {
460                 ret = ecore_wl2_window_keygrab_set(NULL, key_name[i], 0, 0, 0, ECORE_WL2_WINDOW_KEYGRAB_SHARED);
461                 _D("key grab : %s / ret : %d", key_name[i], ret);
462         }
463
464         key_info.key_up = ecore_event_handler_add(ECORE_EVENT_KEY_UP, _key_release_cb, NULL);
465         if (!key_info.key_up) {
466                 _E("Failed to register a key up event handler");
467         }
468
469         key_info.key_down = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _key_press_cb, NULL);
470         if (!key_info.key_down) {
471                 _E("Failed to register a key down event handler");
472         }
473
474         return ECORE_CALLBACK_CANCEL;
475 }
476
477
478
479 void hw_key_create_window(void)
480 {
481         if (key_info.keygrab_timer) {
482                 ecore_timer_del(key_info.keygrab_timer);
483                 key_info.keygrab_timer = NULL;
484         }
485
486         key_info.keygrab_timer = ecore_timer_add(1.0f, __keygrab_timer_cb, NULL);
487         if (!key_info.keygrab_timer) {
488                 _E("Failed to add timer for keygrab");
489         }
490 }
491
492
493
494 void hw_key_destroy_window(void)
495 {
496         int i = 0;
497
498         for (i = 0; i < KEY_NAME_MAX; i++) {
499                 ecore_wl2_window_keygrab_unset(NULL, key_name[i], 0, 0);
500         }
501
502         if (key_info.keygrab_timer) {
503                 ecore_timer_del(key_info.keygrab_timer);
504                 key_info.keygrab_timer = NULL;
505         }
506
507         if (key_info.key_up) {
508                 ecore_event_handler_del(key_info.key_up);
509                 key_info.key_up = NULL;
510         }
511
512         if (key_info.key_down) {
513                 ecore_event_handler_del(key_info.key_down);
514                 key_info.key_down = NULL;
515         }
516 }
517
518 // End of a file