blob: f75076c38b1ff3077156217b493c1ccbcee21dd6 [file] [log] [blame]
David Sodmanbbcb0522014-09-19 10:34:07 -07001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
Dominik Behrf50c98f2016-03-31 14:05:29 -07007#if DBUS
8#include <dbus/dbus.h>
David Sodmanbbcb0522014-09-19 10:34:07 -07009#include <stdlib.h>
David Sodman8ef20062015-01-06 09:23:40 -080010
Stéphane Marchesin62561a12015-12-11 17:32:37 -080011#include "dbus.h"
David Sodman8ef20062015-01-06 09:23:40 -080012#include "dbus_interface.h"
13#include "image.h"
Dominik Behr46c567f2016-03-08 15:11:48 -080014#include "main.h"
David Sodman8ef20062015-01-06 09:23:40 -080015#include "term.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070016#include "util.h"
17
Dominik Behr5f6742f2016-03-10 18:03:54 -080018#define DBUS_WAIT_DELAY_US (50000)
David Sodman8ef20062015-01-06 09:23:40 -080019#define DBUS_DEFAULT_DELAY 3000
Dominik Behr5f6742f2016-03-10 18:03:54 -080020#define DBUS_INIT_TIMEOUT_MS (60*1000)
David Sodman8ef20062015-01-06 09:23:40 -080021
Dominik Behr797a3832016-01-11 15:53:11 -080022typedef struct _dbus_t dbus_t;
23
Dominik Behr46c567f2016-03-08 15:11:48 -080024static void (*login_prompt_visible_callback)(void*) = NULL;
25static void* login_prompt_visible_callback_userptr = NULL;
Dominik Behr1883c042016-04-27 12:31:02 -070026static void (*suspend_done_callback)(void*) = NULL;
27static void* suspend_done_callback_userptr = NULL;
Dominik Behr46c567f2016-03-08 15:11:48 -080028static bool chrome_is_already_up = false;
Dominik Behr5f6742f2016-03-10 18:03:54 -080029static bool dbus_connect_fail = false;
30static int64_t dbus_connect_fail_time;
31static bool dbus_first_init = true;
32static int64_t dbus_first_init_time;
Dominik Behr46c567f2016-03-08 15:11:48 -080033
David Sodmanbbcb0522014-09-19 10:34:07 -070034struct _dbus_t {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080035 DBusConnection* conn;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080036 DBusWatch* watch;
David Sodman8ef20062015-01-06 09:23:40 -080037 int fd;
David Sodmanbbcb0522014-09-19 10:34:07 -070038};
39
Dominik Behr797a3832016-01-11 15:53:11 -080040static dbus_t *dbus = NULL;
41
Stéphane Marchesin8fc13522015-12-14 17:02:28 -080042static void frecon_dbus_unregister(DBusConnection* connection, void* user_data)
David Sodman8ef20062015-01-06 09:23:40 -080043{
44}
45
Stéphane Marchesin8fc13522015-12-14 17:02:28 -080046static DBusHandlerResult frecon_dbus_message_handler(DBusConnection* connection,
47 DBusMessage* message,
48 void* user_data)
David Sodman8ef20062015-01-06 09:23:40 -080049{
David Sodman8ef20062015-01-06 09:23:40 -080050 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
David Sodman8ef20062015-01-06 09:23:40 -080051}
52
53static DBusObjectPathVTable
54frecon_vtable = {
Stéphane Marchesinaf9e9ff2015-12-11 17:49:12 -080055 frecon_dbus_unregister,
56 frecon_dbus_message_handler,
David Sodman8ef20062015-01-06 09:23:40 -080057 NULL
58};
59
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080060static dbus_bool_t add_watch(DBusWatch* w, void* data)
David Sodman8ef20062015-01-06 09:23:40 -080061{
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080062 dbus_t* dbus = (dbus_t*)data;
David Sodman8ef20062015-01-06 09:23:40 -080063 dbus->watch = w;
64
65 return TRUE;
66}
67
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080068static void remove_watch(DBusWatch* w, void* data)
David Sodman8ef20062015-01-06 09:23:40 -080069{
70}
71
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080072static void toggle_watch(DBusWatch* w, void* data)
David Sodman8ef20062015-01-06 09:23:40 -080073{
74}
75
Dominik Behr46c567f2016-03-08 15:11:48 -080076static DBusHandlerResult handle_login_prompt_visible(DBusMessage* message)
77{
78 if (login_prompt_visible_callback) {
79 login_prompt_visible_callback(login_prompt_visible_callback_userptr);
80 login_prompt_visible_callback = NULL;
81 login_prompt_visible_callback_userptr = NULL;
82 }
83 chrome_is_already_up = true;
84
85 return DBUS_HANDLER_RESULT_HANDLED;
86}
87
Dominik Behr1883c042016-04-27 12:31:02 -070088static DBusHandlerResult handle_suspend_done(DBusMessage* message)
89{
90 if (suspend_done_callback)
91 suspend_done_callback(suspend_done_callback_userptr);
92
93 return DBUS_HANDLER_RESULT_HANDLED;
94}
95
Dominik Behr46c567f2016-03-08 15:11:48 -080096static DBusHandlerResult frecon_dbus_message_filter(DBusConnection* connection,
97 DBusMessage* message,
98 void* user_data)
99{
100 if (dbus_message_is_signal(message,
Dominik Behr5f6742f2016-03-10 18:03:54 -0800101 kSessionManagerInterface, kLoginPromptVisibleSignal))
Dominik Behr46c567f2016-03-08 15:11:48 -0800102 return handle_login_prompt_visible(message);
Dominik Behr1883c042016-04-27 12:31:02 -0700103 else if (dbus_message_is_signal(message,
104 kPowerManagerInterface, kSuspendDoneSignal))
105 return handle_suspend_done(message);
Dominik Behr46c567f2016-03-08 15:11:48 -0800106
107 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
108}
109
Dominik Behr797a3832016-01-11 15:53:11 -0800110bool dbus_is_initialized(void)
111{
112 return !!dbus;
113}
114
115bool dbus_init()
David Sodmanbbcb0522014-09-19 10:34:07 -0700116{
117 dbus_t* new_dbus;
118 DBusError err;
David Sodman8ef20062015-01-06 09:23:40 -0800119 int result;
120 dbus_bool_t stat;
David Sodmanbbcb0522014-09-19 10:34:07 -0700121
Dominik Behr5f6742f2016-03-10 18:03:54 -0800122 if (dbus_first_init) {
123 dbus_first_init = false;
124 dbus_first_init_time = get_monotonic_time_ms();
125 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700126 dbus_error_init(&err);
127
128 new_dbus = (dbus_t*)calloc(1, sizeof(*new_dbus));
Stéphane Marchesinc236e0b2015-12-14 15:29:15 -0800129
130 if (!new_dbus)
Dominik Behr797a3832016-01-11 15:53:11 -0800131 return false;
Stéphane Marchesinc236e0b2015-12-14 15:29:15 -0800132
David Sodman8ef20062015-01-06 09:23:40 -0800133 new_dbus->fd = -1;
David Sodmanbbcb0522014-09-19 10:34:07 -0700134
135 new_dbus->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
136 if (dbus_error_is_set(&err)) {
Dominik Behr5f6742f2016-03-10 18:03:54 -0800137 if (!dbus_connect_fail) {
138 LOG(ERROR, "Cannot get DBUS connection");
139 dbus_connect_fail = true;
140 dbus_connect_fail_time = get_monotonic_time_ms();
141 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700142 free(new_dbus);
Dominik Behr797a3832016-01-11 15:53:11 -0800143 return false;
David Sodmanbbcb0522014-09-19 10:34:07 -0700144 }
145
Dominik Behr5f6742f2016-03-10 18:03:54 -0800146 if (dbus_connect_fail) {
147 int64_t t = get_monotonic_time_ms() - dbus_connect_fail_time;
148 LOG(INFO, "DBUS connected after %.1f seconds", (float)t / 1000.0f);
149 }
150
David Sodman8ef20062015-01-06 09:23:40 -0800151 result = dbus_bus_request_name(new_dbus->conn, kFreconDbusInterface,
152 DBUS_NAME_FLAG_DO_NOT_QUEUE, &err);
153
154 if (result <= 0) {
155 LOG(ERROR, "Unable to get name for server");
156 }
157
158 stat = dbus_connection_register_object_path(new_dbus->conn,
159 kFreconDbusPath,
160 &frecon_vtable,
161 NULL);
162
163 if (!stat) {
164 LOG(ERROR, "failed to register object path");
165 }
166
Dominik Behr46c567f2016-03-08 15:11:48 -0800167 dbus_bus_add_match(new_dbus->conn, kLoginPromptVisibleRule, &err);
Dominik Behr1883c042016-04-27 12:31:02 -0700168 dbus_bus_add_match(new_dbus->conn, kSuspendDoneRule, &err);
Dominik Behr46c567f2016-03-08 15:11:48 -0800169
170 stat = dbus_connection_add_filter(new_dbus->conn, frecon_dbus_message_filter, NULL, NULL);
171 if (!stat) {
172 LOG(ERROR, "failed to add message filter");
173 }
174
David Sodman8ef20062015-01-06 09:23:40 -0800175 stat = dbus_connection_set_watch_functions(new_dbus->conn,
176 add_watch, remove_watch, toggle_watch,
177 new_dbus, NULL);
178
179 if (!stat) {
180 LOG(ERROR, "Failed to set watch functions");
181 }
182
David Sodmanbbcb0522014-09-19 10:34:07 -0700183 dbus_connection_set_exit_on_disconnect(new_dbus->conn, FALSE);
184
Dominik Behr797a3832016-01-11 15:53:11 -0800185 dbus = new_dbus;
186 return true;
David Sodmanbbcb0522014-09-19 10:34:07 -0700187}
188
Dominik Behr5f6742f2016-03-10 18:03:54 -0800189bool dbus_init_wait()
190{
191 while (!dbus_is_initialized()) {
192 if (!dbus_init()) {
193 int64_t t = get_monotonic_time_ms() - dbus_first_init_time;
194 if (t >= DBUS_INIT_TIMEOUT_MS) {
195 LOG(ERROR, "DBUS init failed after a timeout of %u sec", DBUS_INIT_TIMEOUT_MS/1000);
196 return false;
197 }
198 }
199 usleep(DBUS_WAIT_DELAY_US);
200 }
201 return true;
202}
203
Dominik Behr797a3832016-01-11 15:53:11 -0800204static bool dbus_method_call0(const char* service_name,
205 const char* service_path,
206 const char* service_interface,
207 const char* method)
David Sodman003faed2014-11-03 09:02:10 -0800208{
Dominik Behr797a3832016-01-11 15:53:11 -0800209 DBusMessage* msg = NULL;
210 if (!dbus) {
211 LOG(ERROR, "dbus not initialized");
212 return false;
213 }
David Sodman003faed2014-11-03 09:02:10 -0800214
215 msg = dbus_message_new_method_call(service_name,
216 service_path, service_interface, method);
217
218 if (!msg)
219 return false;
220
221 if (!dbus_connection_send_with_reply_and_block(dbus->conn,
David Sodman8ef20062015-01-06 09:23:40 -0800222 msg, DBUS_DEFAULT_DELAY, NULL)) {
David Sodman003faed2014-11-03 09:02:10 -0800223 dbus_message_unref(msg);
224 return false;
225 }
226
227 dbus_connection_flush(dbus->conn);
228 dbus_message_unref(msg);
229
230 return true;
231}
232
Dominik Behr797a3832016-01-11 15:53:11 -0800233static bool dbus_method_call1(const char* service_name,
234 const char* service_path,
235 const char* service_interface,
236 const char* method, int arg_type, void* param)
David Sodmanbbcb0522014-09-19 10:34:07 -0700237{
Dominik Behr797a3832016-01-11 15:53:11 -0800238 DBusMessage* msg = NULL;
239 if (!dbus) {
240 LOG(ERROR, "dbus not initialized");
241 return false;
242 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700243
244 msg = dbus_message_new_method_call(service_name,
245 service_path, service_interface, method);
246
247 if (!msg)
248 return false;
249
250 if (!dbus_message_append_args(msg,
David Sodman19e4f9d2015-03-10 11:11:09 -0700251 arg_type, param, DBUS_TYPE_INVALID)) {
David Sodmanbbcb0522014-09-19 10:34:07 -0700252 dbus_message_unref(msg);
253 return false;
254 }
255
256 if (!dbus_connection_send_with_reply_and_block(dbus->conn,
David Sodman8ef20062015-01-06 09:23:40 -0800257 msg, DBUS_DEFAULT_DELAY, NULL)) {
David Sodmanbbcb0522014-09-19 10:34:07 -0700258 dbus_message_unref(msg);
259 return false;
260 }
261
262 dbus_connection_flush(dbus->conn);
263 dbus_message_unref(msg);
264
265 return true;
266}
267
Dominik Behr797a3832016-01-11 15:53:11 -0800268void dbus_destroy(void)
David Sodmanbbcb0522014-09-19 10:34:07 -0700269{
270 /* FIXME - not sure what the right counterpart to
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800271 * dbus_bus_get() is, unref documentation is rather
272 * unclear. Not a big issue but it would be nice to
273 * clean up properly here
274 */
David Sodmanbbcb0522014-09-19 10:34:07 -0700275 /* dbus_connection_unref(dbus->conn); */
Dominik Behr797a3832016-01-11 15:53:11 -0800276 if (dbus) {
David Sodman8ef20062015-01-06 09:23:40 -0800277 free(dbus);
Dominik Behr797a3832016-01-11 15:53:11 -0800278 dbus = NULL;
279 }
David Sodman8ef20062015-01-06 09:23:40 -0800280}
281
Dominik Behrd7112672016-01-20 16:59:34 -0800282void dbus_add_fds(fd_set* read_set, fd_set* exception_set, int *maxfd)
David Sodman8ef20062015-01-06 09:23:40 -0800283{
Dominik Behr797a3832016-01-11 15:53:11 -0800284 if (!dbus)
Dominik Behrd7112672016-01-20 16:59:34 -0800285 return;
Dominik Behr797a3832016-01-11 15:53:11 -0800286
David Sodman8ef20062015-01-06 09:23:40 -0800287 if (dbus->fd < 0)
288 dbus->fd = dbus_watch_get_unix_fd(dbus->watch);
289
290 if (dbus->fd >= 0) {
291 FD_SET(dbus->fd, read_set);
292 FD_SET(dbus->fd, exception_set);
293 }
David Sodman8ef20062015-01-06 09:23:40 -0800294
Dominik Behrd7112672016-01-20 16:59:34 -0800295 if (dbus->fd > *maxfd)
296 *maxfd = dbus->fd;
David Sodman8ef20062015-01-06 09:23:40 -0800297}
298
Dominik Behr797a3832016-01-11 15:53:11 -0800299void dbus_dispatch_io(void)
David Sodman8ef20062015-01-06 09:23:40 -0800300{
Dominik Behr797a3832016-01-11 15:53:11 -0800301 if (!dbus)
302 return;
303
David Sodman8ef20062015-01-06 09:23:40 -0800304 dbus_watch_handle(dbus->watch, DBUS_WATCH_READABLE);
305 while (dbus_connection_get_dispatch_status(dbus->conn)
306 == DBUS_DISPATCH_DATA_REMAINS) {
307 dbus_connection_dispatch(dbus->conn);
308 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700309}
Dominik Behr797a3832016-01-11 15:53:11 -0800310
311void dbus_report_user_activity(int activity_type)
312{
313 dbus_bool_t allow_off = false;
314 if (!dbus)
315 return;
316
317 dbus_method_call1(kPowerManagerServiceName,
318 kPowerManagerServicePath,
319 kPowerManagerInterface,
320 kHandleUserActivityMethod,
321 DBUS_TYPE_INT32, &activity_type);
322
323 switch (activity_type) {
324 case USER_ACTIVITY_BRIGHTNESS_UP_KEY_PRESS:
325 (void)dbus_method_call0(kPowerManagerServiceName,
326 kPowerManagerServicePath,
327 kPowerManagerInterface,
328 kIncreaseScreenBrightnessMethod);
329 break;
330 case USER_ACTIVITY_BRIGHTNESS_DOWN_KEY_PRESS:
331 /*
332 * Shouldn't allow the screen to go
333 * completely off while frecon is active
334 * so passing false to allow_off
335 */
336 (void)dbus_method_call1(kPowerManagerServiceName,
337 kPowerManagerServicePath,
338 kPowerManagerInterface,
339 kDecreaseScreenBrightnessMethod,
340 DBUS_TYPE_BOOLEAN, &allow_off);
341 break;
342 }
343}
344
Dominik Behr46c567f2016-03-08 15:11:48 -0800345/*
346 * tell Chrome to take ownership of the display (DRM master)
347 */
Dominik Behr797a3832016-01-11 15:53:11 -0800348void dbus_take_display_ownership(void)
349{
350 if (!dbus)
351 return;
352 (void)dbus_method_call0(kLibCrosServiceName,
353 kLibCrosServicePath,
354 kLibCrosServiceInterface,
355 kTakeDisplayOwnership);
356}
357
Dominik Behr46c567f2016-03-08 15:11:48 -0800358/*
359 * ask Chrome to give up display ownership (DRM master)
360 */
Dominik Behr83864df2016-04-21 12:35:08 -0700361bool dbus_release_display_ownership(void)
Dominik Behr797a3832016-01-11 15:53:11 -0800362{
363 if (!dbus)
Dominik Behr83864df2016-04-21 12:35:08 -0700364 return true;
365 return dbus_method_call0(kLibCrosServiceName,
366 kLibCrosServicePath,
367 kLibCrosServiceInterface,
368 kReleaseDisplayOwnership);
Dominik Behr797a3832016-01-11 15:53:11 -0800369}
370
Dominik Behr46c567f2016-03-08 15:11:48 -0800371void dbus_set_login_prompt_visible_callback(void (*callback)(void*),
372 void* userptr)
373{
374 if (chrome_is_already_up) {
375 if (callback)
376 callback(userptr);
377 } else {
378 if (login_prompt_visible_callback && callback) {
379 LOG(ERROR, "trying to register login prompt visible callback multiple times");
380 return;
381 }
382 login_prompt_visible_callback = callback;
383 login_prompt_visible_callback_userptr = userptr;
384 }
385}
Dominik Behrf50c98f2016-03-31 14:05:29 -0700386
Dominik Behr1883c042016-04-27 12:31:02 -0700387void dbus_set_suspend_done_callback(void (*callback)(void*),
388 void* userptr)
389{
390 if (suspend_done_callback && callback) {
391 LOG(ERROR, "trying to register login prompt visible callback multiple times");
392 return;
393 }
394 suspend_done_callback = callback;
395 suspend_done_callback_userptr = userptr;
396}
397
Dominik Behrf50c98f2016-03-31 14:05:29 -0700398#else
399
400#include <stdlib.h>
401#include <stdbool.h>
402
403bool dbus_init()
404{
405 return true;
406}
407
408bool dbus_init_wait()
409{
410 return true;
411}
412
413void dbus_destroy(void)
414{
415}
416
417void dbus_add_fds(fd_set* read_set, fd_set* exception_set, int *maxfd)
418{
419}
420
421void dbus_dispatch_io(void)
422{
423}
424
425void dbus_report_user_activity(int activity_type)
426{
427}
428
429void dbus_take_display_ownership(void)
430{
431}
432
Dominik Behr83864df2016-04-21 12:35:08 -0700433bool dbus_release_display_ownership(void)
Dominik Behrf50c98f2016-03-31 14:05:29 -0700434{
Dominik Behr83864df2016-04-21 12:35:08 -0700435 return true;
Dominik Behrf50c98f2016-03-31 14:05:29 -0700436}
437
438bool dbus_is_initialized(void)
439{
440 return true;
441}
442
443void dbus_set_login_prompt_visible_callback(void (*callback)(void*),
444 void* userptr)
445{
446}
447
Dominik Behr1883c042016-04-27 12:31:02 -0700448void dbus_set_suspend_done_callback(void (*callback)(void*),
449 void* userptr)
450{
451}
452
Dominik Behrf50c98f2016-03-31 14:05:29 -0700453#endif