1/*
2 * binder interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
5 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10#include <binder/IPCThreadState.h>
11#include <binder/IServiceManager.h>
12#include <binder/ProcessState.h>
13
14#include "binder_manager.h"
15
16extern "C" {
17#include "binder.h"
18#include "binder_i.h"
19#include "utils/common.h"
20#include "utils/eloop.h"
21#include "utils/includes.h"
22}
23
24void wpas_binder_sock_handler(int sock, void *eloop_ctx, void *sock_ctx)
25{
26	struct wpa_global *global = (wpa_global *)eloop_ctx;
27	struct wpas_binder_priv *priv = (wpas_binder_priv *)sock_ctx;
28
29	wpa_printf(
30	    MSG_DEBUG, "Processing binder events on FD %d", priv->binder_fd);
31	android::IPCThreadState::self()->handlePolledCommands();
32}
33
34struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global)
35{
36	struct wpas_binder_priv *priv;
37	wpa_supplicant_binder::BinderManager *binder_manager;
38
39	priv = (wpas_binder_priv *)os_zalloc(sizeof(*priv));
40	if (!priv)
41		return NULL;
42	priv->global = global;
43
44	android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
45	android::IPCThreadState::self()->disableBackgroundScheduling(true);
46	android::IPCThreadState::self()->setupPolling(&priv->binder_fd);
47	wpa_printf(MSG_INFO, "Process binder events on FD %d", priv->binder_fd);
48	if (priv->binder_fd < 0)
49		goto err;
50	/* Look for read events from the binder socket in the eloop. */
51	if (eloop_register_read_sock(
52		priv->binder_fd, wpas_binder_sock_handler, global, priv) < 0)
53		goto err;
54
55	binder_manager = wpa_supplicant_binder::BinderManager::getInstance();
56	if (!binder_manager)
57		goto err;
58	binder_manager->registerBinderService(global);
59	/* We may not need to store this binder manager reference in the
60	 * global data strucure because we've made it a singleton class. */
61	priv->binder_manager = (void *)binder_manager;
62
63	return priv;
64
65err:
66	wpas_binder_deinit(priv);
67	return NULL;
68}
69
70void wpas_binder_deinit(struct wpas_binder_priv *priv)
71{
72	if (!priv)
73		return;
74
75	wpa_supplicant_binder::BinderManager::destroyInstance();
76	eloop_unregister_read_sock(priv->binder_fd);
77	android::IPCThreadState::shutdown();
78}
79
80int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
81{
82	if (!wpa_s->global->binder)
83		return 1;
84
85	wpa_supplicant_binder::BinderManager *binder_manager =
86	    wpa_supplicant_binder::BinderManager::getInstance();
87	if (!binder_manager)
88		return 1;
89
90	return binder_manager->registerInterface(wpa_s);
91}
92
93int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
94{
95	if (!wpa_s->global->binder)
96		return 1;
97
98	wpa_supplicant_binder::BinderManager *binder_manager =
99	    wpa_supplicant_binder::BinderManager::getInstance();
100	if (!binder_manager)
101		return 1;
102
103	return binder_manager->unregisterInterface(wpa_s);
104}
105