Home | History | Annotate | Download | only in heart_rate
      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 #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 
     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:
     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:
     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 
     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   main_loop.Run();
    157 
    158   LOG(INFO) << "Exiting";
    159   return EXIT_SUCCESS;
    160 }
    161