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