Release version 1.4.8
[platform/core/appfw/app-core.git] / src / legacy / appcore-rotation.c
1 /*
2  * Copyright (c) 2000 - 2017 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 <errno.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20
21 #include <sensor_internal.h>
22 #include <vconf.h>
23 #include "appcore-internal.h"
24
25 struct rot_s {
26         int handle;
27         int (*callback) (void *event_info, enum appcore_rm, void *);
28         enum appcore_rm mode;
29         int lock;
30         void *cbdata;
31         int cb_set;
32         int sensord_started;
33
34         struct ui_wm_rotate* wm_rotate;
35 };
36 static struct rot_s rot;
37
38 struct rot_evt {
39         enum auto_rotation_state re;
40         enum appcore_rm rm;
41 };
42
43 static struct rot_evt re_to_rm[] = {
44         {
45                 AUTO_ROTATION_DEGREE_0,
46                 APPCORE_RM_PORTRAIT_NORMAL,
47         },
48         {
49                 AUTO_ROTATION_DEGREE_90,
50                 APPCORE_RM_LANDSCAPE_NORMAL,
51         },
52         {
53                 AUTO_ROTATION_DEGREE_180,
54                 APPCORE_RM_PORTRAIT_REVERSE,
55         },
56         {
57                 AUTO_ROTATION_DEGREE_270,
58                 APPCORE_RM_LANDSCAPE_REVERSE,
59         },
60 };
61
62 static enum appcore_rm __get_mode(sensor_data_t data)
63 {
64         int i;
65         int event;
66         enum appcore_rm m;
67
68         m = APPCORE_RM_UNKNOWN;
69         if (data.value_count > 0) {
70                 event = (int)data.values[0];
71         } else {
72                 _ERR("Failed to get sensor data");
73                 return -1;
74         }
75
76         for (i = 0; i < sizeof(re_to_rm) / sizeof(re_to_rm[0]); i++) {
77                 if (re_to_rm[i].re == event) {
78                         m = re_to_rm[i].rm;
79                         break;
80                 }
81         }
82
83         return m;
84 }
85
86 static void __changed_cb(sensor_t sensor, unsigned int event_type,
87                 sensor_data_t *data, void *user_data)
88 {
89         enum appcore_rm m;
90
91         if (rot.lock)
92                 return;
93
94         if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT) {
95                 errno = EINVAL;
96                 return;
97         }
98
99         m = __get_mode(*data);
100
101         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
102
103         if (rot.callback) {
104                 if (rot.cb_set && rot.mode != m) {
105                         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
106                         rot.callback((void *)&m, m, user_data);
107                         rot.mode = m;
108                 }
109         }
110 }
111
112 static void __lock_cb(keynode_t *node, void *data)
113 {
114         int r;
115         enum appcore_rm m;
116
117         rot.lock = !vconf_keynode_get_bool(node);
118
119         if (rot.lock) {
120                 m = APPCORE_RM_PORTRAIT_NORMAL;
121                 if (rot.mode != m) {
122                         rot.callback((void *)&m, m, data);
123                         rot.mode = m;
124                 }
125                 _DBG("[APP %d] Rotation locked", getpid());
126                 return;
127         }
128
129         _DBG("[APP %d] Rotation unlocked", getpid());
130         if (rot.callback) {
131                 if (rot.cb_set) {
132                         r = appcore_get_rotation_state(&m);
133                         _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(),
134                              rot.mode, m);
135                         if (!r && rot.mode != m) {
136                                 rot.callback((void *)&m, m, data);
137                                 rot.mode = m;
138                         }
139                 }
140         }
141 }
142
143 static void __add_rotlock(void *data)
144 {
145         int r;
146         int lock;
147
148         lock = 0;
149         r = vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
150         if (r)
151                 _DBG("[APP %d] Rotation vconf get bool failed", getpid());
152
153         rot.lock = !lock;
154
155         vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb,
156                                  data);
157 }
158
159 static void __del_rotlock(void)
160 {
161         vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb);
162         rot.lock = 0;
163 }
164
165 EXPORT_API int appcore_set_rotation_cb(int (*cb) (void *evnet_info, enum appcore_rm, void *),
166                                        void *data)
167 {
168         if (rot.wm_rotate)
169                 return rot.wm_rotate->set_rotation_cb(cb, data);
170         else {
171                 bool r;
172                 int handle;
173                 sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
174
175                 if (cb == NULL) {
176                         errno = EINVAL;
177                         return -1;
178                 }
179
180                 if (rot.callback != NULL) {
181                         errno = EALREADY;
182                         return -1;
183                 }
184
185                 handle = sensord_connect(sensor);
186                 if (handle < 0) {
187                         _ERR("sensord_connect failed: %d", handle);
188                         return -1;
189                 }
190
191                 r = sensord_register_event(handle, AUTO_ROTATION_CHANGE_STATE_EVENT,
192                                       SENSOR_INTERVAL_NORMAL, 0, __changed_cb, data);
193                 if (!r) {
194                         _ERR("sensord_register_event failed");
195                         sensord_disconnect(handle);
196                         return -1;
197                 }
198
199                 rot.cb_set = 1;
200                 rot.callback = cb;
201                 rot.cbdata = data;
202
203                 r = sensord_start(handle, 0);
204                 if (!r) {
205                         _ERR("sensord_start failed");
206                         r = sensord_unregister_event(handle, AUTO_ROTATION_CHANGE_STATE_EVENT);
207                         if (!r)
208                                 _ERR("sensord_unregister_event failed");
209
210                         rot.callback = NULL;
211                         rot.cbdata = NULL;
212                         rot.cb_set = 0;
213                         rot.sensord_started = 0;
214                         sensord_disconnect(handle);
215                         return -1;
216                 }
217                 rot.sensord_started = 1;
218
219                 rot.handle = handle;
220                 __add_rotlock(data);
221         }
222         return 0;
223 }
224
225 EXPORT_API int appcore_unset_rotation_cb(void)
226 {
227         if (rot.wm_rotate)
228                 return rot.wm_rotate->unset_rotation_cb();
229         else {
230                 bool r;
231
232                 _retv_if(rot.callback == NULL, 0);
233
234                 __del_rotlock();
235
236                 if (rot.cb_set) {
237                         r = sensord_unregister_event(rot.handle,
238                                                 AUTO_ROTATION_CHANGE_STATE_EVENT);
239                         if (!r) {
240                                 _ERR("sensord_unregister_event failed");
241                                 return -1;
242                         }
243                         rot.cb_set = 0;
244                 }
245                 rot.callback = NULL;
246                 rot.cbdata = NULL;
247
248                 if (rot.sensord_started == 1) {
249                         r = sensord_stop(rot.handle);
250                         if (!r) {
251                                 _ERR("sensord_stop failed");
252                                 return -1;
253                         }
254                         rot.sensord_started = 0;
255                 }
256
257                 r = sensord_disconnect(rot.handle);
258                 if (!r) {
259                         _ERR("sensord_disconnect failed");
260                         return -1;
261                 }
262                 rot.handle = -1;
263         }
264         return 0;
265 }
266
267 EXPORT_API int appcore_get_rotation_state(enum appcore_rm *curr)
268 {
269         if (rot.wm_rotate)
270                 return rot.wm_rotate->get_rotation_state(curr);
271         else {
272                 bool r;
273                 sensor_data_t data;
274
275                 if (curr == NULL) {
276                         errno = EINVAL;
277                         return -1;
278                 }
279
280                 r = sensord_get_data(rot.handle, AUTO_ROTATION_SENSOR, &data);
281                 if (!r) {
282                         _ERR("sensord_get_data failed");
283                         *curr = APPCORE_RM_UNKNOWN;
284                         return -1;
285                 }
286
287                 *curr = __get_mode(data);
288         }
289         return 0;
290 }
291
292