From d73697b9b61be2fa227b93b5c4c8e30badd32e71 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 5 Mar 2015 15:09:23 -0800 Subject: radio service binder interfaces Added definiiton and implemention of binder interfaces fro native broadcastradio service. Change-Id: Id5a93bc3146229dffc74b56c29ba48e02b9a5518 --- radio/IRadio.cpp | 344 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 radio/IRadio.cpp (limited to 'radio/IRadio.cpp') diff --git a/radio/IRadio.cpp b/radio/IRadio.cpp new file mode 100644 index 0000000..242df77 --- /dev/null +++ b/radio/IRadio.cpp @@ -0,0 +1,344 @@ +/* +** +** Copyright 2015, The Android Open Source Project +** +** 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. +*/ + +#define LOG_TAG "IRadio" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +enum { + DETACH = IBinder::FIRST_CALL_TRANSACTION, + SET_CONFIGURATION, + GET_CONFIGURATION, + SET_MUTE, + GET_MUTE, + SCAN, + STEP, + TUNE, + CANCEL, + GET_PROGRAM_INFORMATION, + HAS_CONTROL +}; + +class BpRadio: public BpInterface +{ +public: + BpRadio(const sp& impl) + : BpInterface(impl) + { + } + + void detach() + { + ALOGV("detach"); + Parcel data, reply; + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + remote()->transact(DETACH, data, &reply); + } + + virtual status_t setConfiguration(const struct radio_band_config *config) + { + Parcel data, reply; + if (config == NULL) { + return BAD_VALUE; + } + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + data.write(config, sizeof(struct radio_band_config)); + status_t status = remote()->transact(SET_CONFIGURATION, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + + virtual status_t getConfiguration(struct radio_band_config *config) + { + Parcel data, reply; + if (config == NULL) { + return BAD_VALUE; + } + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + status_t status = remote()->transact(GET_CONFIGURATION, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + if (status == NO_ERROR) { + reply.read(config, sizeof(struct radio_band_config)); + } + } + return status; + } + + virtual status_t setMute(bool mute) + { + Parcel data, reply; + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + data.writeInt32(mute ? 1 : 0); + status_t status = remote()->transact(SET_MUTE, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + + virtual status_t getMute(bool *mute) + { + Parcel data, reply; + if (mute == NULL) { + return BAD_VALUE; + } + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + status_t status = remote()->transact(GET_MUTE, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + if (status == NO_ERROR) { + int muteread = reply.readInt32(); + *mute = muteread != 0; + } + } + return status; + } + + virtual status_t scan(radio_direction_t direction, bool skipSubChannel) + { + Parcel data, reply; + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + data.writeInt32(direction); + data.writeInt32(skipSubChannel ? 1 : 0); + status_t status = remote()->transact(SCAN, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + + virtual status_t step(radio_direction_t direction, bool skipSubChannel) + { + Parcel data, reply; + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + data.writeInt32(direction); + data.writeInt32(skipSubChannel ? 1 : 0); + status_t status = remote()->transact(STEP, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + + virtual status_t tune(unsigned int channel, unsigned int subChannel) + { + Parcel data, reply; + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + data.writeInt32(channel); + data.writeInt32(subChannel); + status_t status = remote()->transact(TUNE, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + + virtual status_t cancel() + { + Parcel data, reply; + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + status_t status = remote()->transact(CANCEL, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + } + return status; + } + + virtual status_t getProgramInformation(struct radio_program_info *info) + { + Parcel data, reply; + if (info == NULL) { + return BAD_VALUE; + } + radio_metadata_t *metadata = info->metadata; + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + status_t status = remote()->transact(GET_PROGRAM_INFORMATION, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + if (status == NO_ERROR) { + reply.read(info, sizeof(struct radio_program_info)); + info->metadata = metadata; + if (metadata == NULL) { + return status; + } + size_t size = (size_t)reply.readInt32(); + if (size == 0) { + return status; + } + metadata = + (radio_metadata_t *)calloc(size / sizeof(unsigned int), sizeof(unsigned int)); + if (metadata == NULL) { + return NO_MEMORY; + } + reply.read(metadata, size); + status = radio_metadata_add_metadata(&info->metadata, metadata); + free(metadata); + } + } + return status; + } + + virtual status_t hasControl(bool *hasControl) + { + Parcel data, reply; + if (hasControl == NULL) { + return BAD_VALUE; + } + data.writeInterfaceToken(IRadio::getInterfaceDescriptor()); + status_t status = remote()->transact(HAS_CONTROL, data, &reply); + if (status == NO_ERROR) { + status = (status_t)reply.readInt32(); + if (status == NO_ERROR) { + *hasControl = reply.readInt32() != 0; + } + } + return status; + } +}; + +IMPLEMENT_META_INTERFACE(Radio, "android.hardware.IRadio"); + +// ---------------------------------------------------------------------- + +status_t BnRadio::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case DETACH: { + ALOGV("DETACH"); + CHECK_INTERFACE(IRadio, data, reply); + detach(); + return NO_ERROR; + } break; + case SET_CONFIGURATION: { + CHECK_INTERFACE(IRadio, data, reply); + struct radio_band_config config; + data.read(&config, sizeof(struct radio_band_config)); + status_t status = setConfiguration(&config); + reply->writeInt32(status); + return NO_ERROR; + } + case GET_CONFIGURATION: { + CHECK_INTERFACE(IRadio, data, reply); + struct radio_band_config config; + status_t status = getConfiguration(&config); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&config, sizeof(struct radio_band_config)); + } + return NO_ERROR; + } + case SET_MUTE: { + CHECK_INTERFACE(IRadio, data, reply); + bool mute = data.readInt32() != 0; + status_t status = setMute(mute); + reply->writeInt32(status); + return NO_ERROR; + } + case GET_MUTE: { + CHECK_INTERFACE(IRadio, data, reply); + bool mute; + status_t status = getMute(&mute); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(mute ? 1 : 0); + } + return NO_ERROR; + } + case SCAN: { + CHECK_INTERFACE(IRadio, data, reply); + radio_direction_t direction = (radio_direction_t)data.readInt32(); + bool skipSubChannel = data.readInt32() == 1; + status_t status = scan(direction, skipSubChannel); + reply->writeInt32(status); + return NO_ERROR; + } + case STEP: { + CHECK_INTERFACE(IRadio, data, reply); + radio_direction_t direction = (radio_direction_t)data.readInt32(); + bool skipSubChannel = data.readInt32() == 1; + status_t status = step(direction, skipSubChannel); + reply->writeInt32(status); + return NO_ERROR; + } + case TUNE: { + CHECK_INTERFACE(IRadio, data, reply); + unsigned int channel = (unsigned int)data.readInt32(); + unsigned int subChannel = (unsigned int)data.readInt32(); + status_t status = tune(channel, subChannel); + reply->writeInt32(status); + return NO_ERROR; + } + case CANCEL: { + CHECK_INTERFACE(IRadio, data, reply); + status_t status = cancel(); + reply->writeInt32(status); + return NO_ERROR; + } + case GET_PROGRAM_INFORMATION: { + CHECK_INTERFACE(IRadio, data, reply); + struct radio_program_info info; + + status_t status = radio_metadata_allocate(&info.metadata, 0, 0); + if (status != NO_ERROR) { + return status; + } + status = getProgramInformation(&info); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&info, sizeof(struct radio_program_info)); + int count = radio_metadata_get_count(info.metadata); + if (count > 0) { + size_t size = radio_metadata_get_size(info.metadata); + reply->writeInt32(size); + reply->write(info.metadata, size); + } else { + reply->writeInt32(0); + } + } + radio_metadata_deallocate(info.metadata); + return NO_ERROR; + } + case HAS_CONTROL: { + CHECK_INTERFACE(IRadio, data, reply); + bool control; + status_t status = hasControl(&control); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(control ? 1 : 0); + } + return NO_ERROR; + } + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android -- cgit v1.1