Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d73697b9 authored by Eric Laurent's avatar Eric Laurent
Browse files

radio service binder interfaces

Added definiiton and implemention of binder
interfaces fro native broadcastradio service.

Change-Id: Id5a93bc3146229dffc74b56c29ba48e02b9a5518
parent a5c5ad36
Loading
Loading
Loading
Loading

include/radio/IRadio.h

0 → 100644
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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.
 */

#ifndef ANDROID_HARDWARE_IRADIO_H
#define ANDROID_HARDWARE_IRADIO_H

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
#include <system/radio.h>

namespace android {

class IRadio : public IInterface
{
public:

    DECLARE_META_INTERFACE(Radio);

    virtual void detach() = 0;

    virtual status_t setConfiguration(const struct radio_band_config *config) = 0;

    virtual status_t getConfiguration(struct radio_band_config *config) = 0;

    virtual status_t setMute(bool mute) = 0;

    virtual status_t getMute(bool *mute) = 0;

    virtual status_t step(radio_direction_t direction, bool skipSubChannel) = 0;

    virtual status_t scan(radio_direction_t direction, bool skipSubChannel) = 0;

    virtual status_t tune(unsigned int channel, unsigned int subChannel) = 0;

    virtual status_t cancel() = 0;

    virtual status_t getProgramInformation(struct radio_program_info *info) = 0;

    virtual status_t hasControl(bool *hasControl) = 0;
};

// ----------------------------------------------------------------------------

class BnRadio: public BnInterface<IRadio>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

}; // namespace android

#endif //ANDROID_HARDWARE_IRADIO_H
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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.
 */

#ifndef ANDROID_HARDWARE_IRADIO_CLIENT_H
#define ANDROID_HARDWARE_IRADIO_CLIENT_H

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>

namespace android {

class IRadioClient : public IInterface
{
public:

    DECLARE_META_INTERFACE(RadioClient);

    virtual void onEvent(const sp<IMemory>& eventMemory) = 0;

};

// ----------------------------------------------------------------------------

class BnRadioClient : public BnInterface<IRadioClient>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

}; // namespace android

#endif //ANDROID_HARDWARE_IRADIO_CLIENT_H
+59 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 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.
 */

#ifndef ANDROID_HARDWARE_IRADIO_SERVICE_H
#define ANDROID_HARDWARE_IRADIO_SERVICE_H

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <system/radio.h>

namespace android {

class IRadio;
class IRadioClient;

class IRadioService : public IInterface
{
public:

    DECLARE_META_INTERFACE(RadioService);

    virtual status_t listModules(struct radio_properties *properties,
                                 uint32_t *numModules) = 0;

    virtual status_t attach(const radio_handle_t handle,
                            const sp<IRadioClient>& client,
                            const struct radio_band_config *config,
                            bool withAudio,
                            sp<IRadio>& radio) = 0;
};

// ----------------------------------------------------------------------------

class BnRadioService: public BnInterface<IRadioService>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

}; // namespace android

#endif //ANDROID_HARDWARE_IRADIO_SERVICE_H

radio/Android.mk

0 → 100644
+38 −0
Original line number Diff line number Diff line
# 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)

radio/IRadio.cpp

0 → 100644
+344 −0
Original line number Diff line number Diff line
/*
**
** 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
Loading