304 lines
8.8 KiB
C++
304 lines
8.8 KiB
C++
//
|
|
// Copyright (C) 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 "service/common/bluetooth/binder/IBluetoothLowEnergy.h"
|
|
|
|
#include <base/logging.h>
|
|
#include <binder/Parcel.h>
|
|
|
|
#include "service/common/bluetooth/binder/parcel_helpers.h"
|
|
|
|
using android::IBinder;
|
|
using android::interface_cast;
|
|
using android::Parcel;
|
|
using android::sp;
|
|
using android::status_t;
|
|
|
|
using bluetooth::AdvertiseData;
|
|
using bluetooth::AdvertiseSettings;
|
|
|
|
namespace ipc {
|
|
namespace binder {
|
|
|
|
// static
|
|
const char IBluetoothLowEnergy::kServiceName[] =
|
|
"bluetooth-low-energy-service";
|
|
|
|
// BnBluetoothLowEnergy (server) implementation
|
|
// ========================================================
|
|
|
|
status_t BnBluetoothLowEnergy::onTransact(
|
|
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
|
|
VLOG(2) << "IBluetoothLowEnergy: " << code;
|
|
if (!data.checkInterface(this))
|
|
return android::PERMISSION_DENIED;
|
|
|
|
switch (code) {
|
|
case REGISTER_CLIENT_TRANSACTION: {
|
|
sp<IBinder> callback = data.readStrongBinder();
|
|
bool result = RegisterClient(
|
|
interface_cast<IBluetoothLowEnergyCallback>(callback));
|
|
|
|
reply->writeInt32(result);
|
|
|
|
return android::NO_ERROR;
|
|
}
|
|
case UNREGISTER_CLIENT_TRANSACTION: {
|
|
int client_id = data.readInt32();
|
|
UnregisterClient(client_id);
|
|
return android::NO_ERROR;
|
|
}
|
|
case UNREGISTER_ALL_TRANSACTION: {
|
|
UnregisterAll();
|
|
return android::NO_ERROR;
|
|
}
|
|
case CONNECT_TRANSACTION: {
|
|
int client_id = data.readInt32();
|
|
const char* address = data.readCString();
|
|
bool is_direct = data.readBool();
|
|
|
|
bool result = Connect(client_id, address, is_direct);
|
|
reply->writeInt32(result);
|
|
|
|
return android::NO_ERROR;
|
|
}
|
|
case DISCONNECT_TRANSACTION: {
|
|
int client_id = data.readInt32();
|
|
const char* address = data.readCString();
|
|
|
|
bool result = Disconnect(client_id, address);
|
|
reply->writeInt32(result);
|
|
|
|
return android::NO_ERROR;
|
|
}
|
|
case SET_MTU_TRANSACTION: {
|
|
int client_id = data.readInt32();
|
|
const char* address = data.readCString();
|
|
int mtu = data.readInt32();
|
|
|
|
bool result = SetMtu(client_id, address, mtu);
|
|
reply->writeInt32(result);
|
|
|
|
return android::NO_ERROR;
|
|
}
|
|
case START_SCAN_TRANSACTION: {
|
|
int client_id = data.readInt32();
|
|
auto settings = CreateScanSettingsFromParcel(data);
|
|
CHECK(settings);
|
|
std::vector<bluetooth::ScanFilter> filters;
|
|
|
|
int list_meta_data = data.readInt32();
|
|
CHECK(list_meta_data == kParcelValList);
|
|
|
|
int filter_count = data.readInt32();
|
|
if (filter_count >= 0) { // Make sure |filter_count| isn't negative.
|
|
for (int i = 0; i < filter_count; i++) {
|
|
auto filter = CreateScanFilterFromParcel(data);
|
|
CHECK(filter);
|
|
filters.push_back(*filter);
|
|
}
|
|
}
|
|
|
|
bool result = StartScan(client_id, *settings, filters);
|
|
reply->writeInt32(result);
|
|
|
|
return android::NO_ERROR;
|
|
}
|
|
case STOP_SCAN_TRANSACTION: {
|
|
int client_id = data.readInt32();
|
|
bool result = StopScan(client_id);
|
|
reply->writeInt32(result);
|
|
return android::NO_ERROR;
|
|
}
|
|
case START_MULTI_ADVERTISING_TRANSACTION: {
|
|
int client_id = data.readInt32();
|
|
std::unique_ptr<AdvertiseData> adv_data =
|
|
CreateAdvertiseDataFromParcel(data);
|
|
std::unique_ptr<AdvertiseData> scan_rsp =
|
|
CreateAdvertiseDataFromParcel(data);
|
|
std::unique_ptr<AdvertiseSettings> adv_settings =
|
|
CreateAdvertiseSettingsFromParcel(data);
|
|
|
|
bool result = StartMultiAdvertising(
|
|
client_id, *adv_data, *scan_rsp, *adv_settings);
|
|
|
|
reply->writeInt32(result);
|
|
|
|
return android::NO_ERROR;
|
|
}
|
|
case STOP_MULTI_ADVERTISING_TRANSACTION: {
|
|
int client_id = data.readInt32();
|
|
bool result = StopMultiAdvertising(client_id);
|
|
|
|
reply->writeInt32(result);
|
|
|
|
return android::NO_ERROR;
|
|
}
|
|
default:
|
|
return BBinder::onTransact(code, data, reply, flags);
|
|
}
|
|
}
|
|
|
|
// BpBluetoothLowEnergy (client) implementation
|
|
// ========================================================
|
|
|
|
BpBluetoothLowEnergy::BpBluetoothLowEnergy(const sp<IBinder>& impl)
|
|
: BpInterface<IBluetoothLowEnergy>(impl) {
|
|
}
|
|
|
|
bool BpBluetoothLowEnergy::RegisterClient(
|
|
const sp<IBluetoothLowEnergyCallback>& callback) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeStrongBinder(IInterface::asBinder(callback.get()));
|
|
|
|
remote()->transact(IBluetoothLowEnergy::REGISTER_CLIENT_TRANSACTION,
|
|
data, &reply);
|
|
|
|
return reply.readInt32();
|
|
}
|
|
|
|
void BpBluetoothLowEnergy::UnregisterClient(int client_id) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeInt32(client_id);
|
|
|
|
remote()->transact(IBluetoothLowEnergy::UNREGISTER_CLIENT_TRANSACTION,
|
|
data, &reply);
|
|
}
|
|
|
|
void BpBluetoothLowEnergy::UnregisterAll() {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
|
|
remote()->transact(IBluetoothLowEnergy::UNREGISTER_ALL_TRANSACTION,
|
|
data, &reply);
|
|
}
|
|
|
|
bool BpBluetoothLowEnergy::Connect(int client_id, const char* address,
|
|
bool is_direct) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeInt32(client_id);
|
|
data.writeCString(address);
|
|
data.writeBool(is_direct);
|
|
|
|
remote()->transact(IBluetoothLowEnergy::CONNECT_TRANSACTION,
|
|
data, &reply);
|
|
|
|
return reply.readInt32();
|
|
}
|
|
|
|
bool BpBluetoothLowEnergy::Disconnect(int client_id, const char* address) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeInt32(client_id);
|
|
data.writeCString(address);
|
|
|
|
remote()->transact(IBluetoothLowEnergy::DISCONNECT_TRANSACTION,
|
|
data, &reply);
|
|
|
|
return reply.readInt32();
|
|
}
|
|
|
|
bool BpBluetoothLowEnergy::SetMtu(int client_id, const char* address, int mtu) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeInt32(client_id);
|
|
data.writeCString(address);
|
|
data.writeInt32(mtu);
|
|
|
|
remote()->transact(IBluetoothLowEnergy::SET_MTU_TRANSACTION, data, &reply);
|
|
return reply.readInt32();
|
|
}
|
|
|
|
bool BpBluetoothLowEnergy::StartScan(
|
|
int client_id,
|
|
const bluetooth::ScanSettings& settings,
|
|
const std::vector<bluetooth::ScanFilter>& filters) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeInt32(client_id);
|
|
WriteScanSettingsToParcel(settings, &data);
|
|
|
|
// The Java equivalent of |filters| is a List<ScanFilter>. Parcel.java inserts
|
|
// a metadata value of VAL_LIST (11) for this so I'm doing it here for
|
|
// compatibility.
|
|
data.writeInt32(kParcelValList);
|
|
data.writeInt32(filters.size());
|
|
for (const auto& filter : filters)
|
|
WriteScanFilterToParcel(filter, &data);
|
|
|
|
remote()->transact(IBluetoothLowEnergy::START_SCAN_TRANSACTION,
|
|
data, &reply);
|
|
|
|
return reply.readInt32();
|
|
}
|
|
|
|
bool BpBluetoothLowEnergy::StopScan(int client_id) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeInt32(client_id);
|
|
|
|
remote()->transact(IBluetoothLowEnergy::STOP_SCAN_TRANSACTION,
|
|
data, &reply);
|
|
|
|
return reply.readInt32();
|
|
}
|
|
|
|
bool BpBluetoothLowEnergy::StartMultiAdvertising(
|
|
int client_id,
|
|
const AdvertiseData& advertise_data,
|
|
const AdvertiseData& scan_response,
|
|
const AdvertiseSettings& settings) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeInt32(client_id);
|
|
WriteAdvertiseDataToParcel(advertise_data, &data);
|
|
WriteAdvertiseDataToParcel(scan_response, &data);
|
|
WriteAdvertiseSettingsToParcel(settings, &data);
|
|
|
|
remote()->transact(IBluetoothLowEnergy::START_MULTI_ADVERTISING_TRANSACTION,
|
|
data, &reply);
|
|
|
|
return reply.readInt32();
|
|
}
|
|
|
|
bool BpBluetoothLowEnergy::StopMultiAdvertising(int client_id) {
|
|
Parcel data, reply;
|
|
|
|
data.writeInterfaceToken(IBluetoothLowEnergy::getInterfaceDescriptor());
|
|
data.writeInt32(client_id);
|
|
|
|
remote()->transact(IBluetoothLowEnergy::STOP_MULTI_ADVERTISING_TRANSACTION,
|
|
data, &reply);
|
|
|
|
return reply.readInt32();
|
|
}
|
|
|
|
IMPLEMENT_META_INTERFACE(BluetoothLowEnergy, IBluetoothLowEnergy::kServiceName);
|
|
|
|
} // namespace binder
|
|
} // namespace ipc
|