summaryrefslogtreecommitdiffstats
path: root/radio
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2015-03-05 15:09:23 -0800
committerEric Laurent <elaurent@google.com>2015-03-10 18:18:12 -0700
commitd73697b9b61be2fa227b93b5c4c8e30badd32e71 (patch)
tree6defe5ad10e0fabf1c5d72afb661863aac2bec80 /radio
parenta5c5ad3615613ac0f15012e9e07a34582da7fe77 (diff)
downloadframeworks_av-d73697b9b61be2fa227b93b5c4c8e30badd32e71.zip
frameworks_av-d73697b9b61be2fa227b93b5c4c8e30badd32e71.tar.gz
frameworks_av-d73697b9b61be2fa227b93b5c4c8e30badd32e71.tar.bz2
radio service binder interfaces
Added definiiton and implemention of binder interfaces fro native broadcastradio service. Change-Id: Id5a93bc3146229dffc74b56c29ba48e02b9a5518
Diffstat (limited to 'radio')
-rw-r--r--radio/Android.mk38
-rw-r--r--radio/IRadio.cpp344
-rw-r--r--radio/IRadioClient.cpp75
-rw-r--r--radio/IRadioService.cpp181
4 files changed, 638 insertions, 0 deletions
diff --git a/radio/Android.mk b/radio/Android.mk
new file mode 100644
index 0000000..bddc3c2
--- /dev/null
+++ b/radio/Android.mk
@@ -0,0 +1,38 @@
+# Copyright 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ IRadio.cpp \
+ IRadioClient.cpp \
+ IRadioService.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ liblog \
+ libbinder \
+ libhardware \
+ libradio_metadata
+
+#LOCAL_C_INCLUDES += \
+ system/media/camera/include \
+ system/media/private/camera/include
+
+LOCAL_MODULE:= libradio
+
+include $(BUILD_SHARED_LIBRARY)
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 <utils/Log.h>
+#include <utils/Errors.h>
+#include <binder/IMemory.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadioClient.h>
+#include <system/radio.h>
+#include <system/radio_metadata.h>
+
+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<IRadio>
+{
+public:
+ BpRadio(const sp<IBinder>& impl)
+ : BpInterface<IRadio>(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
diff --git a/radio/IRadioClient.cpp b/radio/IRadioClient.cpp
new file mode 100644
index 0000000..033ca49
--- /dev/null
+++ b/radio/IRadioClient.cpp
@@ -0,0 +1,75 @@
+/*
+**
+** 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.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <radio/IRadioClient.h>
+
+namespace android {
+
+enum {
+ ON_EVENT = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpRadioClient: public BpInterface<IRadioClient>
+{
+
+public:
+ BpRadioClient(const sp<IBinder>& impl)
+ : BpInterface<IRadioClient>(impl)
+ {
+ }
+
+ virtual void onEvent(const sp<IMemory>& eventMemory)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IRadioClient::getInterfaceDescriptor());
+ data.writeStrongBinder(IInterface::asBinder(eventMemory));
+ remote()->transact(ON_EVENT,
+ data,
+ &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(RadioClient,
+ "android.hardware.IRadioClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnRadioClient::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case ON_EVENT: {
+ CHECK_INTERFACE(IRadioClient, data, reply);
+ sp<IMemory> eventMemory = interface_cast<IMemory>(
+ data.readStrongBinder());
+ onEvent(eventMemory);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ } return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/radio/IRadioService.cpp b/radio/IRadioService.cpp
new file mode 100644
index 0000000..8c2b3ef
--- /dev/null
+++ b/radio/IRadioService.cpp
@@ -0,0 +1,181 @@
+/*
+**
+** 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 "BpRadioService"
+//
+#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <radio/IRadioService.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioClient.h>
+
+namespace android {
+
+enum {
+ LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
+ ATTACH,
+};
+
+#define MAX_ITEMS_PER_LIST 1024
+
+class BpRadioService: public BpInterface<IRadioService>
+{
+public:
+ BpRadioService(const sp<IBinder>& impl)
+ : BpInterface<IRadioService>(impl)
+ {
+ }
+
+ virtual status_t listModules(struct radio_properties *properties,
+ uint32_t *numModules)
+ {
+ if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
+ unsigned int numModulesReq = (properties == NULL) ? 0 : *numModules;
+ data.writeInt32(numModulesReq);
+ status_t status = remote()->transact(LIST_MODULES, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ *numModules = (unsigned int)reply.readInt32();
+ }
+ ALOGV("listModules() status %d got *numModules %d", status, *numModules);
+ if (status == NO_ERROR) {
+ if (numModulesReq > *numModules) {
+ numModulesReq = *numModules;
+ }
+ if (numModulesReq > 0) {
+ reply.read(properties, numModulesReq * sizeof(struct radio_properties));
+ }
+ }
+ return status;
+ }
+
+ virtual status_t attach(radio_handle_t handle,
+ const sp<IRadioClient>& client,
+ const struct radio_band_config *config,
+ bool withAudio,
+ sp<IRadio>& radio)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
+ data.writeInt32(handle);
+ data.writeStrongBinder(IInterface::asBinder(client));
+ ALOGV("attach() config %p withAudio %d region %d type %d", config, withAudio, config->region, config->band.type);
+ if (config == NULL) {
+ data.writeInt32(0);
+ } else {
+ data.writeInt32(1);
+ data.write(config, sizeof(struct radio_band_config));
+ }
+ data.writeInt32(withAudio ? 1 : 0);
+ status_t status = remote()->transact(ATTACH, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readInt32();
+ if (reply.readInt32() != 0) {
+ radio = interface_cast<IRadio>(reply.readStrongBinder());
+ }
+ return status;
+ }
+};
+
+IMPLEMENT_META_INTERFACE(RadioService, "android.hardware.IRadioService");
+
+// ----------------------------------------------------------------------
+
+status_t BnRadioService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case LIST_MODULES: {
+ CHECK_INTERFACE(IRadioService, data, reply);
+ unsigned int numModulesReq = data.readInt32();
+ if (numModulesReq > MAX_ITEMS_PER_LIST) {
+ numModulesReq = MAX_ITEMS_PER_LIST;
+ }
+ unsigned int numModules = numModulesReq;
+ struct radio_properties *properties =
+ (struct radio_properties *)calloc(numModulesReq,
+ sizeof(struct radio_properties));
+ if (properties == NULL) {
+ reply->writeInt32(NO_MEMORY);
+ reply->writeInt32(0);
+ return NO_ERROR;
+ }
+
+ status_t status = listModules(properties, &numModules);
+ reply->writeInt32(status);
+ reply->writeInt32(numModules);
+ ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
+
+ if (status == NO_ERROR) {
+ if (numModulesReq > numModules) {
+ numModulesReq = numModules;
+ }
+ reply->write(properties,
+ numModulesReq * sizeof(struct radio_properties));
+ }
+ free(properties);
+ return NO_ERROR;
+ } break;
+
+ case ATTACH: {
+ CHECK_INTERFACE(IRadioService, data, reply);
+ radio_handle_t handle = data.readInt32();
+ sp<IRadioClient> client =
+ interface_cast<IRadioClient>(data.readStrongBinder());
+ struct radio_band_config config;
+ struct radio_band_config *configPtr = NULL;
+ if (data.readInt32() != 0) {
+ data.read(&config, sizeof(struct radio_band_config));
+ configPtr = &config;
+ }
+ bool withAudio = data.readInt32() != 0;
+ ALOGV("ATTACH configPtr %p withAudio %d", configPtr, withAudio);
+ sp<IRadio> radio;
+ status_t status = attach(handle, client, configPtr, withAudio, radio);
+ reply->writeInt32(status);
+ if (radio != 0) {
+ reply->writeInt32(1);
+ reply->writeStrongBinder(IInterface::asBinder(radio));
+ } else {
+ reply->writeInt32(0);
+ }
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android