OSDN Git Service

Revert "Revert "Initial implementation of broadcast radio HAL.""
authorEric Laurent <elaurent@google.com>
Mon, 21 Nov 2016 18:41:22 +0000 (10:41 -0800)
committerEric Laurent <elaurent@google.com>
Mon, 21 Nov 2016 18:41:22 +0000 (10:41 -0800)
This reverts commit 2c2df013b25bd96976af82db7e6f3480f0571c6e.

13 files changed:
audio/2.0/default/Android.mk
audio/2.0/default/service.cpp
broadcastradio/1.0/ITunerCallback.hal
broadcastradio/1.0/default/Android.mk [new file with mode: 0644]
broadcastradio/1.0/default/BroadcastRadio.cpp [new file with mode: 0644]
broadcastradio/1.0/default/BroadcastRadio.h [new file with mode: 0644]
broadcastradio/1.0/default/BroadcastRadioFactory.cpp [new file with mode: 0644]
broadcastradio/1.0/default/BroadcastRadioFactory.h [new file with mode: 0644]
broadcastradio/1.0/default/Tuner.cpp [new file with mode: 0644]
broadcastradio/1.0/default/Tuner.h [new file with mode: 0644]
broadcastradio/1.0/default/Utils.cpp [new file with mode: 0644]
broadcastradio/1.0/default/Utils.h [new file with mode: 0644]
broadcastradio/1.0/types.hal

index 5108448..2b1aa4f 100644 (file)
@@ -66,6 +66,7 @@ LOCAL_SHARED_LIBRARIES := \
     android.hardware.audio.common@2.0 \
     android.hardware.audio.effect@2.0 \
     android.hardware.soundtrigger@2.0 \
+    android.hardware.broadcastradio@1.0
 
 ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
 LOCAL_MULTILIB := 32
index 147f7b9..28ef660 100644 (file)
@@ -20,6 +20,7 @@
 #include <android/hardware/audio/2.0/IDevicesFactory.h>
 #include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
 
 using android::hardware::IPCThreadState;
 using android::hardware::ProcessState;
@@ -27,10 +28,12 @@ using android::hardware::audio::effect::V2_0::IEffectsFactory;
 using android::hardware::audio::V2_0::IDevicesFactory;
 using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
 using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
 
 int main(int /* argc */, char* /* argv */ []) {
     registerPassthroughServiceImplementation<IDevicesFactory>("audio_devices_factory");
     registerPassthroughServiceImplementation<IEffectsFactory>("audio_effects_factory");
     registerPassthroughServiceImplementation<ISoundTriggerHw>("sound_trigger.primary");
+    registerPassthroughServiceImplementation<IBroadcastRadioFactory>("broadcastradio");
     return android::hardware::launchRpcServer(16);
 }
index f805472..a7e1260 100644 (file)
@@ -72,7 +72,9 @@ interface ITunerCallback {
     /*
      * Method called by the HAL when metadata for current station
      * are updated.
-     * @param metadatas A list of all updated metada.
+     * @param channel The channel the metadata is associated with.
+     * @param subChannel The sub channel the metadata is associated with.
+     * @param metadata A list of all updated metada.
      */
-    oneway newMetadata(vec<MetaData>  metadatas);
+    oneway newMetadata(uint32_t channel, uint32_t subChannel, vec<MetaData>  metadata);
 };
\ No newline at end of file
diff --git a/broadcastradio/1.0/default/Android.mk b/broadcastradio/1.0/default/Android.mk
new file mode 100644 (file)
index 0000000..843b8de
--- /dev/null
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.broadcastradio@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    BroadcastRadio.cpp \
+    BroadcastRadioFactory.cpp \
+    Tuner.cpp \
+    Utils.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidl \
+    libhwbinder \
+    libutils \
+    liblog \
+    libhardware \
+    android.hardware.broadcastradio@1.0 \
+    libradio_metadata
+
+ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
+LOCAL_MULTILIB := 32
+else
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/broadcastradio/1.0/default/BroadcastRadio.cpp b/broadcastradio/1.0/default/BroadcastRadio.cpp
new file mode 100644 (file)
index 0000000..b97b609
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 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 "BroadcastRadio"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <hardware/radio.h>
+
+#include "BroadcastRadio.h"
+#include "Tuner.h"
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+BroadcastRadio::BroadcastRadio(Class classId)
+    : mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL)
+{
+}
+
+BroadcastRadio::~BroadcastRadio()
+{
+    if (mHwDevice != NULL) {
+        radio_hw_device_close(mHwDevice);
+    }
+}
+
+void BroadcastRadio::onFirstRef()
+{
+    const hw_module_t *mod;
+    int rc;
+    ALOGI("%s mClassId %d", __FUNCTION__, mClassId);
+
+    mHwDevice = NULL;
+    const char *classString = Utils::getClassString(mClassId);
+    if (classString == NULL) {
+        ALOGE("invalid class ID %d", mClassId);
+        mStatus = Result::INVALID_ARGUMENTS;
+        return;
+    }
+
+    ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s",
+          __FUNCTION__, RADIO_HARDWARE_MODULE_ID, classString);
+
+    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, classString, &mod);
+    if (rc != 0) {
+        ALOGE("couldn't load radio module %s.%s (%s)",
+              RADIO_HARDWARE_MODULE_ID, classString, strerror(-rc));
+        return;
+    }
+    rc = radio_hw_device_open(mod, &mHwDevice);
+    if (rc != 0) {
+        ALOGE("couldn't open radio hw device in %s.%s (%s)",
+              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
+        mHwDevice = NULL;
+        return;
+    }
+    if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
+        ALOGE("wrong radio hw device version %04x", mHwDevice->common.version);
+        radio_hw_device_close(mHwDevice);
+        mHwDevice = NULL;
+    } else {
+        mStatus = Result::OK;
+    }
+}
+
+int BroadcastRadio::closeHalTuner(const struct radio_tuner *halTuner)
+{
+    ALOGV("%s", __FUNCTION__);
+    if (mHwDevice == NULL) {
+        return -ENODEV;
+    }
+    if (halTuner == 0) {
+        return -EINVAL;
+    }
+    return mHwDevice->close_tuner(mHwDevice, halTuner);
+}
+
+
+// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadio follow.
+Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb)
+{
+    int rc;
+    radio_hal_properties_t halProperties;
+    Properties properties;
+
+    if (mHwDevice == NULL) {
+        rc = -ENODEV;
+        goto exit;
+    }
+    rc = mHwDevice->get_properties(mHwDevice, &halProperties);
+    if (rc == 0) {
+        Utils::convertPropertiesFromHal(&properties, &halProperties);
+    }
+
+exit:
+    _hidl_cb(Utils::convertHalResult(rc), properties);
+    return Void();
+}
+
+Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio,
+                                       const sp<ITunerCallback>& callback, openTuner_cb _hidl_cb)
+{
+    sp<Tuner> tunerImpl = new Tuner(callback, this);
+
+    radio_hal_band_config_t halConfig;
+    const struct radio_tuner *halTuner;
+    Utils::convertBandConfigToHal(&halConfig, &config);
+    int rc = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
+                                   Tuner::callback, tunerImpl.get(),
+                                   &halTuner);
+    if (rc == 0) {
+        tunerImpl->setHalTuner(halTuner);
+    }
+
+    _hidl_cb(Utils::convertHalResult(rc), tunerImpl);
+    return Void();
+}
+
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.0/default/BroadcastRadio.h b/broadcastradio/1.0/default/BroadcastRadio.h
new file mode 100644 (file)
index 0000000..dbd6e07
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_
+#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_
+
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
+#include <hidl/Status.h>
+#include <hardware/radio.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+struct BroadcastRadio : public IBroadcastRadio {
+
+            BroadcastRadio(Class classId);
+
+            // Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadio follow.
+            Return<void> getProperties(getProperties_cb _hidl_cb)  override;
+            Return<void> openTuner(const BandConfig& config, bool audio,
+                                   const sp<ITunerCallback>& callback,
+                                   openTuner_cb _hidl_cb)  override;
+
+
+    // RefBase
+    virtual void onFirstRef();
+
+            Result  initCheck() { return mStatus; }
+            int closeHalTuner(const struct radio_tuner *halTuner);
+
+private:
+    virtual     ~BroadcastRadio();
+
+    static const char * sClassModuleNames[];
+
+    Result convertHalResult(int rc);
+    void convertBandConfigFromHal(BandConfig *config,
+            const radio_hal_band_config_t *halConfig);
+    void convertPropertiesFromHal(Properties *properties,
+            const radio_hal_properties_t *halProperties);
+    void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
+            const BandConfig *config);
+
+    Result                   mStatus;
+    Class                    mClassId;
+    struct radio_hw_device  *mHwDevice;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadio_H_
diff --git a/broadcastradio/1.0/default/BroadcastRadioFactory.cpp b/broadcastradio/1.0/default/BroadcastRadioFactory.cpp
new file mode 100644 (file)
index 0000000..d5d214c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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 "BroadcastRadioFactory.h"
+#include "BroadcastRadio.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
+Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb)  {
+    sp<BroadcastRadio> impl = new BroadcastRadio(classId);
+    Result retval = Result::NOT_INITIALIZED;
+    if (impl != 0) {
+        retval = impl->initCheck();
+    }
+    _hidl_cb(retval, impl);
+    return Void();
+}
+
+
+IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* /* name */) {
+    return new BroadcastRadioFactory();
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.0/default/BroadcastRadioFactory.h b/broadcastradio/1.0/default/BroadcastRadioFactory.h
new file mode 100644 (file)
index 0000000..9b2ca17
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_
+#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_
+
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+struct BroadcastRadioFactory : public IBroadcastRadioFactory {
+    // Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
+    Return<void> connectModule(Class classId, connectModule_cb _hidl_cb)  override;
+
+};
+
+extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_BroadcastRadioFactory_H_
diff --git a/broadcastradio/1.0/default/Tuner.cpp b/broadcastradio/1.0/default/Tuner.cpp
new file mode 100644 (file)
index 0000000..0c1d8ab
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2016 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 "Tuner"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include "BroadcastRadio.h"
+#include "Tuner.h"
+#include "Utils.h"
+#include <system/radio_metadata.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+void Tuner::onCallback(radio_hal_event_t *halEvent)
+{
+    BandConfig config;
+    ProgramInfo info;
+    hidl_vec<MetaData> metadata;
+
+    if (mCallback != 0) {
+        switch(halEvent->type) {
+        case RADIO_EVENT_CONFIG:
+            Utils::convertBandConfigFromHal(&config, &halEvent->config);
+            mCallback->configChange(Utils::convertHalResult(halEvent->status), config);
+            break;
+        case RADIO_EVENT_ANTENNA:
+            mCallback->antennaStateChange(halEvent->on);
+            break;
+        case RADIO_EVENT_TUNED:
+            Utils::convertProgramInfoFromHal(&info, &halEvent->info, true);
+            mCallback->tuneComplete(Utils::convertHalResult(halEvent->status), info);
+            break;
+        case RADIO_EVENT_METADATA: {
+            uint32_t channel;
+            uint32_t sub_channel;
+            if (radio_metadata_get_channel(halEvent->metadata, &channel, &sub_channel) == 0) {
+                Utils::convertMetaDataFromHal(metadata, halEvent->metadata);
+                mCallback->newMetadata(channel, sub_channel, metadata);
+            }
+            } break;
+        case RADIO_EVENT_TA:
+            mCallback->trafficAnnouncement(halEvent->on);
+            break;
+        case RADIO_EVENT_AF_SWITCH:
+            Utils::convertProgramInfoFromHal(&info, &halEvent->info, true);
+            mCallback->afSwitch(info);
+            break;
+        case RADIO_EVENT_EA:
+            mCallback->emergencyAnnouncement(halEvent->on);
+            break;
+        case RADIO_EVENT_HW_FAILURE:
+        default:
+            mCallback->hardwareFailure();
+            break;
+        }
+    }
+}
+
+//static
+void Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
+{
+    wp<Tuner> weak(reinterpret_cast<Tuner*>(cookie));
+    sp<Tuner> tuner = weak.promote();
+    if (tuner == 0) return;
+    tuner->onCallback(halEvent);
+}
+
+Tuner::Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& parentDevice)
+    : mHalTuner(NULL), mCallback(callback), mParentDevice(parentDevice)
+{
+    ALOGV("%s", __FUNCTION__);
+}
+
+
+Tuner::~Tuner()
+{
+    ALOGV("%s", __FUNCTION__);
+    const sp<BroadcastRadio> parentDevice = mParentDevice.promote();
+    if (parentDevice != 0) {
+        parentDevice->closeHalTuner(mHalTuner);
+    }
+}
+
+// Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow.
+Return<Result> Tuner::setConfiguration(const BandConfig& config)  {
+    ALOGV("%s", __FUNCTION__);
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    radio_hal_band_config_t halConfig;
+    Utils::convertBandConfigToHal(&halConfig, &config);
+    int rc = mHalTuner->set_configuration(mHalTuner, &halConfig);
+    return Utils::convertHalResult(rc);
+}
+
+Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb)  {
+    int rc;
+    radio_hal_band_config_t halConfig;
+    BandConfig config;
+
+    ALOGV("%s", __FUNCTION__);
+    if (mHalTuner == NULL) {
+        rc = -ENODEV;
+        goto exit;
+    }
+    rc = mHalTuner->get_configuration(mHalTuner, &halConfig);
+    if (rc == 0) {
+        Utils::convertBandConfigFromHal(&config, &halConfig);
+    }
+
+exit:
+    _hidl_cb(Utils::convertHalResult(rc), config);
+    return Void();
+}
+
+Return<Result> Tuner::scan(Direction direction, bool skipSubChannel)  {
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    int rc = mHalTuner->scan(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
+    return Utils::convertHalResult(rc);
+}
+
+Return<Result> Tuner::step(Direction direction, bool skipSubChannel)  {
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    int rc = mHalTuner->step(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
+    return Utils::convertHalResult(rc);
+}
+
+Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel)  {
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    int rc = mHalTuner->tune(mHalTuner, channel, subChannel);
+    return Utils::convertHalResult(rc);
+}
+
+Return<Result> Tuner::cancel()  {
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    int rc = mHalTuner->cancel(mHalTuner);
+    return Utils::convertHalResult(rc);
+}
+
+Return<void> Tuner::getProgramInformation(bool withMetadata, getProgramInformation_cb _hidl_cb)  {
+    int rc;
+    radio_program_info_t halInfo;
+    ProgramInfo info;
+
+    ALOGV("%s", __FUNCTION__);
+    if (mHalTuner == NULL) {
+        rc = -ENODEV;
+        goto exit;
+    }
+    if (withMetadata) {
+        radio_metadata_allocate(&halInfo.metadata, 0, 0);
+    } else {
+        halInfo.metadata = NULL;
+    }
+    rc = mHalTuner->get_program_information(mHalTuner, &halInfo);
+    if (rc == 0) {
+        Utils::convertProgramInfoFromHal(&info, &halInfo, withMetadata);
+    }
+    if (withMetadata) {
+        radio_metadata_deallocate(halInfo.metadata);
+    }
+
+exit:
+    _hidl_cb(Utils::convertHalResult(rc), info);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.0/default/Tuner.h b/broadcastradio/1.0/default/Tuner.h
new file mode 100644 (file)
index 0000000..94e216e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 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 HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_
+#define HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_
+
+#include <android/hardware/broadcastradio/1.0/ITuner.h>
+#include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
+#include <hidl/Status.h>
+#include <hardware/radio.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+struct BroadcastRadio;
+
+struct Tuner : public ITuner {
+
+    Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& mParentDevice);
+
+    // Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow.
+    Return<Result> setConfiguration(const BandConfig& config)  override;
+    Return<void> getConfiguration(getConfiguration_cb _hidl_cb)  override;
+    Return<Result> scan(Direction direction, bool skipSubChannel)  override;
+    Return<Result> step(Direction direction, bool skipSubChannel)  override;
+    Return<Result> tune(uint32_t channel, uint32_t subChannel)  override;
+    Return<Result> cancel()  override;
+    Return<void> getProgramInformation(bool withMetadata,
+                                       getProgramInformation_cb _hidl_cb)  override;
+
+    static void callback(radio_hal_event_t *halEvent, void *cookie);
+           void onCallback(radio_hal_event_t *halEvent);
+
+    void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; }
+    const struct radio_tuner *getHalTuner() { return mHalTuner; }
+
+ private:
+    ~Tuner();
+
+    const struct radio_tuner    *mHalTuner;
+    const sp<ITunerCallback>     mCallback;
+    const wp<BroadcastRadio>     mParentDevice;
+};
+
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_broadcastradio_V1_0_Tuner_H_
diff --git a/broadcastradio/1.0/default/Utils.cpp b/broadcastradio/1.0/default/Utils.cpp
new file mode 100644 (file)
index 0000000..bdaae00
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2016 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 "BroadcastRadioHalUtils"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/misc.h>
+#include <system/radio_metadata.h>
+
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+const char *Utils::sClassModuleNames[] = {
+    RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
+    RADIO_HARDWARE_MODULE_ID_SAT,  /* corresponds to RADIO_CLASS_SAT */
+    RADIO_HARDWARE_MODULE_ID_DT,   /* corresponds to RADIO_CLASS_DT */
+};
+
+// make sure HIDL enum values are aligned with legacy values
+static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM),
+              "AM/FM class mismatch with legacy");
+static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT),
+              "SAT class mismatch with legacy");
+static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT),
+              "DT class mismatch with legacy");
+
+static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM),
+              "AM band mismatch with legacy");
+static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM),
+              "FM band mismatch with legacy");
+static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD),
+              "AM HD band mismatch with legacy");
+static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD),
+              "FM HD band mismatch with legacy");
+
+static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE),
+              "RDS NONE mismatch with legacy");
+static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD),
+              "RDS WORLD mismatch with legacy");
+static_assert(RADIO_RDS_US == static_cast<int>(Rds::US),
+              "RDS US mismatch with legacy");
+
+static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50),
+              "De-emphasis 50 mismatch with legacy");
+static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75),
+              "De-emphasis 75 mismatch with legacy");
+
+static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP),
+              "Direction Up mismatch with legacy");
+static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN),
+              "Direction Up mismatch with legacy");
+
+static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID),
+              "Metadata type INVALID mismatch with legacy");
+static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT),
+              "Metadata type INT mismatch with legacy");
+static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT),
+              "Metadata type TEXT mismatch with legacy");
+static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW),
+              "Metadata type RAW mismatch with legacy");
+static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK),
+              "Metadata type CLOCK mismatch with legacy");
+
+static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID),
+              "Metadata key INVALID mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI),
+              "Metadata key RDS_PI mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS),
+              "Metadata key RDS_PS mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY),
+              "Metadata key RDS_PTY mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY),
+              "Metadata key RBDS_PTY mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT),
+              "Metadata key RDS_RT mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE),
+              "Metadata key TITLE mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST),
+              "Metadata key ARTIST mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM),
+              "Metadata key ALBUM mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE),
+              "Metadata key GENRE mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON),
+              "Metadata key ICON mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART),
+              "Metadata key ART mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK),
+              "Metadata key CLOCK mismatch with legacy");
+
+
+//static
+const char * Utils::getClassString(Class ClassId)
+{
+    int id = static_cast<int>(ClassId);
+
+    if ((id < 0) ||
+            (id >= NELEM(sClassModuleNames))) {
+        ALOGE("invalid class ID %d", id);
+        return NULL;
+    }
+    return sClassModuleNames[id];
+}
+
+//static
+Result Utils::convertHalResult(int rc)
+{
+    switch (rc) {
+        case 0:
+            return Result::OK;
+        case -EINVAL:
+            return Result::INVALID_ARGUMENTS;
+        case -ENOSYS:
+            return Result::INVALID_STATE;
+        case -ETIMEDOUT:
+            return Result::TIMEOUT;
+        case -ENODEV:
+        default:
+            return Result::NOT_INITIALIZED;
+    }
+}
+
+//static
+void Utils::convertBandConfigFromHal(
+        BandConfig *config,
+        const radio_hal_band_config_t *halConfig)
+{
+
+    config->type = static_cast<Band>(halConfig->type);
+    config->antennaConnected = halConfig->antenna_connected;
+    config->lowerLimit = halConfig->lower_limit;
+    config->upperLimit = halConfig->upper_limit;
+    config->spacings.setToExternal(const_cast<unsigned int *>(&halConfig->spacings[0]),
+                                       halConfig->num_spacings * sizeof(uint32_t));
+    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+    config->spacings.resize(halConfig->num_spacings);
+
+    if (config->type == Band::FM) {
+        config->ext.fm.deemphasis = static_cast<Deemphasis>(halConfig->fm.deemphasis);
+        config->ext.fm.stereo = halConfig->fm.stereo;
+        config->ext.fm.rds = static_cast<Rds>(halConfig->fm.rds);
+        config->ext.fm.ta = halConfig->fm.ta;
+        config->ext.fm.af = halConfig->fm.af;
+        config->ext.fm.ea = halConfig->fm.ea;
+    } else {
+        config->ext.am.stereo = halConfig->am.stereo;
+    }
+}
+
+//static
+void Utils::convertPropertiesFromHal(
+        Properties *properties,
+        const radio_hal_properties_t *halProperties)
+{
+    properties->classId = static_cast<Class>(halProperties->class_id);
+    properties->implementor.setToExternal(halProperties->implementor, strlen(halProperties->implementor));
+    properties->product.setToExternal(halProperties->product, strlen(halProperties->product));
+    properties->version.setToExternal(halProperties->version, strlen(halProperties->version));
+    properties->serial.setToExternal(halProperties->serial, strlen(halProperties->serial));
+    properties->numTuners = halProperties->num_tuners;
+    properties->numAudioSources = halProperties->num_audio_sources;
+    properties->supportsCapture = halProperties->supports_capture;
+
+    BandConfig *bands =
+            new BandConfig[halProperties->num_bands];
+    for (size_t i = 0; i < halProperties->num_bands; i++) {
+        convertBandConfigFromHal(&bands[i], &halProperties->bands[i]);
+    }
+    properties->bands.setToExternal(bands, halProperties->num_bands);
+    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+    properties->bands.resize(halProperties->num_bands);
+    delete[] bands;
+}
+
+//static
+void Utils::convertBandConfigToHal(
+        radio_hal_band_config_t *halConfig,
+        const BandConfig *config)
+{
+
+    halConfig->type = static_cast<radio_band_t>(config->type);
+    halConfig->antenna_connected = config->antennaConnected;
+    halConfig->lower_limit = config->lowerLimit;
+    halConfig->upper_limit = config->upperLimit;
+    halConfig->num_spacings = config->spacings.size();
+    if (halConfig->num_spacings > RADIO_NUM_SPACINGS_MAX) {
+        halConfig->num_spacings = RADIO_NUM_SPACINGS_MAX;
+    }
+    memcpy(halConfig->spacings, config->spacings.data(),
+           sizeof(uint32_t) * halConfig->num_spacings);
+
+    if (config->type == Band::FM) {
+        halConfig->fm.deemphasis = static_cast<radio_deemphasis_t>(config->ext.fm.deemphasis);
+        halConfig->fm.stereo = config->ext.fm.stereo;
+        halConfig->fm.rds = static_cast<radio_rds_t>(config->ext.fm.rds);
+        halConfig->fm.ta = config->ext.fm.ta;
+        halConfig->fm.af = config->ext.fm.af;
+        halConfig->fm.ea = config->ext.fm.ea;
+    } else {
+        halConfig->am.stereo = config->ext.am.stereo;
+    }
+}
+
+
+//static
+void Utils::convertProgramInfoFromHal(ProgramInfo *info,
+                                      radio_program_info_t *halInfo,
+                                      bool withMetadata)
+{
+    info->channel = halInfo->channel;
+    info->subChannel = halInfo->sub_channel;
+    info->tuned = halInfo->tuned;
+    info->stereo = halInfo->stereo;
+    info->digital = halInfo->digital;
+    info->signalStrength = halInfo->signal_strength;
+    if (withMetadata && halInfo->metadata != NULL) {
+        convertMetaDataFromHal(info->metadata, halInfo->metadata);
+    }
+}
+
+//static
+int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
+                                   radio_metadata_t *halMetadata)
+{
+    if (halMetadata == NULL) {
+        return 0;
+    }
+
+    int count = radio_metadata_get_count(halMetadata);
+    if (count <= 0) {
+        return count;
+    }
+    MetaData *newMetadata =
+            new MetaData[count];
+    int outCount = 0;
+    for (int i = 0; i < count; i++) {
+        radio_metadata_key_t key;
+        radio_metadata_type_t type;
+        void *value;
+        size_t size;
+        if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 ||
+                size == 0) {
+            continue;
+        }
+        switch (type) {
+            case RADIO_METADATA_TYPE_INT: {
+                newMetadata[outCount].intValue = *(static_cast<int32_t *>(value));
+            } break;
+            case RADIO_METADATA_TYPE_TEXT: {
+                newMetadata[outCount].stringValue = static_cast<char *>(value);
+            } break;
+            case RADIO_METADATA_TYPE_RAW: {
+                newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size);
+                // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+                newMetadata[outCount].rawValue.resize(size);
+            } break;
+            case RADIO_METADATA_TYPE_CLOCK: {
+                  radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value);
+                  newMetadata[outCount].clockValue.utcSecondsSinceEpoch =
+                          clock->utc_seconds_since_epoch;
+                  newMetadata[outCount].clockValue.timezoneOffsetInMinutes =
+                          clock->timezone_offset_in_minutes;
+            } break;
+        }
+        newMetadata[outCount].type = static_cast<MetadataType>(type);
+        newMetadata[outCount].key = static_cast<MetadataKey>(key);
+        outCount++;
+    }
+    metadata.setToExternal(newMetadata, outCount);
+    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+    metadata.resize(outCount);
+    return outCount;
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.0/default/Utils.h b/broadcastradio/1.0/default/Utils.h
new file mode 100644 (file)
index 0000000..25eb6ee
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 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_BROADCASTRADIO_V1_0_UTILS_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H
+
+#include <android/hardware/broadcastradio/1.0/types.h>
+#include <hardware/radio.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+class Utils {
+public:
+    static const char * getClassString(Class ClassId);
+    static Result convertHalResult(int rc);
+    static void convertBandConfigFromHal(BandConfig *config,
+            const radio_hal_band_config_t *halConfig);
+    static void convertPropertiesFromHal(Properties *properties,
+            const radio_hal_properties_t *halProperties);
+    static void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
+            const BandConfig *config);
+    static void convertProgramInfoFromHal(ProgramInfo *info,
+                                          radio_program_info_t *halInfo,
+                                          bool withMetadata);
+    static int convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
+                                       radio_metadata_t *halMetadata);
+private:
+    static const char * sClassModuleNames[];
+
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H
index c5b4411..d04359c 100644 (file)
@@ -54,7 +54,7 @@ enum Band : uint32_t {
 enum Rds : uint32_t {
     NONE   = 0,
     WORLD  = (1<<0),
-    RDS_US = (1<<1),
+    US = (1<<1),
 };
 
 
@@ -111,7 +111,7 @@ struct BandConfig {
     union Ext {
         FmBandConfig fm;
         AmBandConfig am;
-    };
+    } ext;
 };
 
 /* Exposes properties of a given hardware radio module.