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