1 //
2 // Copyright 2015 Google, Inc.
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 <base/at_exit.h>
18 #include <base/bind.h>
19 #include <base/command_line.h>
20 #include <base/location.h>
21 #include <base/logging.h>
22 #include <base/message_loop/message_loop.h>
23 #include <base/run_loop.h>
24
25 #include <binder/IPCThreadState.h>
26 #include <binder/IServiceManager.h>
27 #include <binder/ProcessState.h>
28
29 #include <android/bluetooth/IBluetooth.h>
30
31 #include "heart_rate_server.h"
32
33 using android::sp;
34 using android::OK;
35 using android::bluetooth::IBluetooth;
36
37 using android::getService;
38
39 namespace {
40
41 std::string kServiceName = "bluetooth-service";
42
QuitMessageLoop()43 void QuitMessageLoop() {
44 base::RunLoop().Quit();
45 }
46
47 // Handles the case where the Bluetooth process dies.
48 class BluetoothDeathRecipient : public android::IBinder::DeathRecipient {
49 public:
BluetoothDeathRecipient(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)50 explicit BluetoothDeathRecipient(
51 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
52 : main_task_runner_(main_task_runner) {}
53
54 ~BluetoothDeathRecipient() override = default;
55
56 // android::IBinder::DeathRecipient override:
binderDied(const android::wp<android::IBinder> &)57 void binderDied(const android::wp<android::IBinder>& /* who */) override {
58 LOG(ERROR) << "The Bluetooth daemon has died. Aborting.";
59
60 // binderDied executes on a dedicated thread. We need to stop the main loop
61 // on the main thread so we post a message to it here. The main loop only
62 // runs on the main thread.
63 main_task_runner_->PostTask(FROM_HERE, base::Bind(&QuitMessageLoop));
64
65 android::IPCThreadState::self()->stopProcess();
66 }
67
68 private:
69 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
70 };
71
72 } // namespace
73
main(int argc,char * argv[])74 int main(int argc, char* argv[]) {
75 base::AtExitManager exit_manager;
76 base::CommandLine::Init(argc, argv);
77 logging::LoggingSettings log_settings;
78
79 // Initialize global logging based on command-line parameters (this is a
80 // libchrome pattern).
81 if (!logging::InitLogging(log_settings)) {
82 LOG(ERROR) << "Failed to set up logging";
83 return EXIT_FAILURE;
84 }
85
86 // Set up a message loop so that we can schedule timed Heart Rate
87 // notifications.
88 base::MessageLoop main_loop;
89
90 LOG(INFO) << "Starting GATT Heart Rate Service sample";
91
92 sp<IBluetooth> bluetooth;
93 status_t status = getService(String16(kServiceName.c_str()), &bluetooth);
94 if (status != OK) {
95 LOG(ERROR) << "Failed to get service binder: '" << kServiceName
96 << "' status=" << status;
97 return EXIT_FAILURE;
98 }
99
100 // Bluetooth needs to be enabled for our demo to work.
101 bool enabled;
102 bluetooth->IsEnabled(&enabled);
103 if (!enabled) {
104 LOG(ERROR) << "Bluetooth is not enabled.";
105 return EXIT_FAILURE;
106 }
107
108 // Register for death notifications on the IBluetooth binder. This let's us
109 // handle the case where the Bluetooth daemon process (bluetoothtbd) dies
110 // outside of our control.
111 sp<BluetoothDeathRecipient> dr(
112 new BluetoothDeathRecipient(main_loop.task_runner()));
113 if (android::IInterface::asBinder(bluetooth.get())->linkToDeath(dr) !=
114 android::NO_ERROR) {
115 LOG(ERROR) << "Failed to register DeathRecipient for IBluetooth";
116 return EXIT_FAILURE;
117 }
118
119 // Initialize the Binder process thread pool. We have to set this up,
120 // otherwise, incoming callbacks from the Bluetooth daemon would block the
121 // main thread (in other words, we have to do this as we are a "Binder
122 // server").
123 android::ProcessState::self()->startThreadPool();
124
125 // heart_rate::HeartRateServer notifies success or failure asynchronously
126 // using a closure, so we set up a lambda for that here.
127 auto callback = [&](bool success) {
128 if (success) {
129 LOG(INFO) << "Heart Rate service started successfully";
130 return;
131 }
132
133 LOG(ERROR) << "Starting Heart Rate server failed asynchronously";
134 base::RunLoop().QuitWhenIdle();
135 };
136
137 bool advertise =
138 base::CommandLine::ForCurrentProcess()->HasSwitch("advertise");
139
140 // Create the Heart Rate server.
141 std::unique_ptr<heart_rate::HeartRateServer> hr(
142 new heart_rate::HeartRateServer(bluetooth, main_loop.task_runner(),
143 advertise));
144 if (!hr->Run(callback)) {
145 LOG(ERROR) << "Failed to start Heart Rate server";
146 return EXIT_FAILURE;
147 }
148
149 // Run the main loop on the main process thread. Binder callbacks will be
150 // received in dedicated threads set up by the ProcessState::startThreadPool
151 // call above but we use this main loop for sending out heart rate
152 // notifications.
153 base::RunLoop().Run();
154
155 LOG(INFO) << "Exiting";
156 return EXIT_SUCCESS;
157 }
158