summaryrefslogtreecommitdiff
path: root/system/service/example/heart_rate/server_main.cc
blob: f8953f16a4bce35ac971066f4af26ceae6a55922 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//
//  Copyright 2015 Google, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at:
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#include <base/at_exit.h>
#include <base/bind.h>
#include <base/command_line.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/run_loop.h>

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>

#include <android/bluetooth/IBluetooth.h>

#include "abstract_message_loop.h"
#include "heart_rate_server.h"

using android::sp;
using android::OK;
using android::bluetooth::IBluetooth;

using android::getService;

namespace {

std::string kServiceName = "bluetooth-service";

void QuitMessageLoop() {
  base::RunLoop().Quit();
}

// Handles the case where the Bluetooth process dies.
class BluetoothDeathRecipient : public android::IBinder::DeathRecipient {
 public:
  explicit BluetoothDeathRecipient(
      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
      : main_task_runner_(main_task_runner) {}

  ~BluetoothDeathRecipient() override = default;

  // android::IBinder::DeathRecipient override:
  void binderDied(const android::wp<android::IBinder>& /* who */) override {
    LOG(ERROR) << "The Bluetooth daemon has died. Aborting.";

    // binderDied executes on a dedicated thread. We need to stop the main loop
    // on the main thread so we post a message to it here. The main loop only
    // runs on the main thread.
    main_task_runner_->PostTask(FROM_HERE, base::Bind(&QuitMessageLoop));

    android::IPCThreadState::self()->stopProcess();
  }

 private:
  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
};

}  // namespace

int main(int argc, char* argv[]) {
  base::AtExitManager exit_manager;
  base::CommandLine::Init(argc, argv);
  logging::LoggingSettings log_settings;

  // Initialize global logging based on command-line parameters (this is a
  // libchrome pattern).
  if (!logging::InitLogging(log_settings)) {
    LOG(ERROR) << "Failed to set up logging";
    return EXIT_FAILURE;
  }

  // Set up a message loop so that we can schedule timed Heart Rate
  // notifications.
  btbase::AbstractMessageLoop main_loop;

  LOG(INFO) << "Starting GATT Heart Rate Service sample";

  sp<IBluetooth> bluetooth;
  status_t status = getService(String16(kServiceName.c_str()), &bluetooth);
  if (status != OK) {
    LOG(ERROR) << "Failed to get service binder: '" << kServiceName
               << "' status=" << status;
    return EXIT_FAILURE;
  }

  // Bluetooth needs to be enabled for our demo to work.
  bool enabled;
  bluetooth->IsEnabled(&enabled);
  if (!enabled) {
    LOG(ERROR) << "Bluetooth is not enabled.";
    return EXIT_FAILURE;
  }

  // Register for death notifications on the IBluetooth binder. This let's us
  // handle the case where the Bluetooth daemon process (bluetoothtbd) dies
  // outside of our control.
  sp<BluetoothDeathRecipient> dr(
      new BluetoothDeathRecipient(main_loop.task_runner()));
  if (android::IInterface::asBinder(bluetooth.get())->linkToDeath(dr) !=
      android::NO_ERROR) {
    LOG(ERROR) << "Failed to register DeathRecipient for IBluetooth";
    return EXIT_FAILURE;
  }

  // Initialize the Binder process thread pool. We have to set this up,
  // otherwise, incoming callbacks from the Bluetooth daemon would block the
  // main thread (in other words, we have to do this as we are a "Binder
  // server").
  android::ProcessState::self()->startThreadPool();

  // heart_rate::HeartRateServer notifies success or failure asynchronously
  // using a closure, so we set up a lambda for that here.
  auto callback = [&](bool success) {
    if (success) {
      LOG(INFO) << "Heart Rate service started successfully";
      return;
    }

    LOG(ERROR) << "Starting Heart Rate server failed asynchronously";
    base::RunLoop().QuitWhenIdle();
  };

  bool advertise =
      base::CommandLine::ForCurrentProcess()->HasSwitch("advertise");

  // Create the Heart Rate server.
  std::unique_ptr<heart_rate::HeartRateServer> hr(
      new heart_rate::HeartRateServer(bluetooth, main_loop.task_runner(),
                                      advertise));
  if (!hr->Run(callback)) {
    LOG(ERROR) << "Failed to start Heart Rate server";
    return EXIT_FAILURE;
  }

  // Run the main loop on the main process thread. Binder callbacks will be
  // received in dedicated threads set up by the ProcessState::startThreadPool
  // call above but we use this main loop for sending out heart rate
  // notifications.
  base::RunLoop().Run();

  LOG(INFO) << "Exiting";
  return EXIT_SUCCESS;
}