1 //
2 //  Copyright 2016 The Android Open Source Project
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 "service/ipc/dbus/bluetooth_adapter.h"
18 #include <base/files/file_util.h>
19 #include <base/logging.h>
20 #include "service/hal/bluetooth_interface.h"
21 
22 using ::dbus::Bus;
23 using ::dbus::ExportedObject;
24 using ::dbus::MethodCall;
25 using ::dbus::MessageWriter;
26 using ::dbus::Response;
27 using ::dbus::ObjectPath;
28 using ::dbus::ErrorResponse;
29 
30 namespace {
31 
32 const std::string kBluetoothAdapterInterface = "org.fluoride.BluetoothAdapter";
33 const std::string kEnable = "Enable";
34 const std::string kDisable = "Disable";
35 const std::string kBluetoothAdapter = "org.fluoride.BluetoothAdapter";
36 const std::string kBluetoothAdapterPath = "/org/fluoride/BluetoothAdapter";
37 
38 // TODO(jpawlowski): right now xml interface files are in service/ipc/dbus/
39 // folder.  Make a script to move them into /usr/share/dbus-1/interfaces
40 const char kBindingsPath[] =
41     "/usr/share/dbus-1/interfaces/org.fluoride.BluetoothAdapter.xml";
42 const char kDBusIntrospectMethod[] = "Introspect";
43 
44 }  // namespace
45 
46 namespace ipc {
47 namespace dbus {
48 
49 #if defined(BASE_VER) && BASE_VER > 780000
50 // New libchrome treats ResponseSender as base::OnceCallback so we need to move
51 // ownership before calling ::Run()
RunResponse(std::unique_ptr<Response> response,ExportedObject::ResponseSender & response_sender)52 inline void RunResponse(std::unique_ptr<Response> response,
53                         ExportedObject::ResponseSender& response_sender) {
54   std::move(response_sender).Run(std::move(response));
55 }
56 #else
57 inline void RunResponse(std::unique_ptr<Response> response,
58                         ExportedObject::ResponseSender& response_sender) {
59   response_sender.Run(std::move(response));
60 }
61 #endif
62 
BluetoothAdapter(scoped_refptr<Bus> bus,bluetooth::Adapter * adapter)63 BluetoothAdapter::BluetoothAdapter(scoped_refptr<Bus> bus,
64                                    bluetooth::Adapter* adapter)
65     : adapter_(adapter) {
66   exported_object_ = bus->GetExportedObject(ObjectPath(kBluetoothAdapterPath));
67 
68   CHECK(exported_object_->ExportMethodAndBlock(
69       kBluetoothAdapterInterface, kEnable,
70       base::Bind(&BluetoothAdapter::Enable, base::Unretained(this))));
71 
72   CHECK(exported_object_->ExportMethodAndBlock(
73       kBluetoothAdapterInterface, kDisable,
74       base::Bind(&BluetoothAdapter::Disable, base::Unretained(this))));
75 
76   CHECK(exported_object_->ExportMethodAndBlock(
77       DBUS_INTERFACE_INTROSPECTABLE, kDBusIntrospectMethod,
78       base::Bind(&BluetoothAdapter::Introspect, base::Unretained(this))));
79 
80   CHECK(bus->RequestOwnershipAndBlock(kBluetoothAdapter, Bus::REQUIRE_PRIMARY))
81       << "Unable to take ownership of " << kBluetoothAdapter
82       << ". Make sure you have proper busconfig file "
83          "/etc/dbus-1/system.d/org.fluoride.conf";
84 }
85 
Enable(MethodCall * method_call,ExportedObject::ResponseSender response_sender)86 void BluetoothAdapter::Enable(MethodCall* method_call,
87                               ExportedObject::ResponseSender response_sender) {
88   VLOG(1) << __func__;
89   adapter_->Enable();
90   RunResponse(Response::FromMethodCall(method_call), response_sender);
91 }
92 
Disable(MethodCall * method_call,ExportedObject::ResponseSender response_sender)93 void BluetoothAdapter::Disable(MethodCall* method_call,
94                                ExportedObject::ResponseSender response_sender) {
95   VLOG(1) << __func__;
96   adapter_->Disable();
97   RunResponse(Response::FromMethodCall(method_call), response_sender);
98 }
99 
Introspect(MethodCall * method_call,ExportedObject::ResponseSender response_sender)100 void BluetoothAdapter::Introspect(
101     MethodCall* method_call, ExportedObject::ResponseSender response_sender) {
102   VLOG(1) << __func__;
103 
104   std::string output;
105   if (!base::ReadFileToString(base::FilePath(kBindingsPath), &output)) {
106     PLOG(ERROR) << "Can't read XML bindings from disk:";
107     RunResponse(ErrorResponse::FromMethodCall(
108                     method_call, "Can't read XML bindings from disk.", ""),
109                 response_sender);
110   }
111 
112   std::unique_ptr<Response> response(Response::FromMethodCall(method_call));
113   MessageWriter writer(response.get());
114   writer.AppendString(output);
115 
116   RunResponse(std::move(response), response_sender);
117 }
118 
~BluetoothAdapter()119 BluetoothAdapter::~BluetoothAdapter() {}
120 
121 }  // namespace dbus
122 }  // namespace ipc
123