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