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

Commit a6f15235 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

Implement region guessing.

Bug: b/64115131
Test: instrumentation
Change-Id: I80a03b4e8614de18cebd9c4bd1f5f9922b8da59b
parent 708d1184
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -131,7 +131,9 @@ public class RadioTunerTest {

        // find FM band and build its config
        mModule = mModules.get(0);

        for (RadioManager.BandDescriptor band : mModule.getBands()) {
            Log.d(TAG, "Band: " + band);
            int bandType = band.getType();
            if (bandType == RadioManager.BAND_AM || bandType == RadioManager.BAND_AM_HD) {
                mAmBandDescriptor = (RadioManager.AmBandDescriptor)band;
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ LOCAL_SRC_FILES += \
    $(LOCAL_REL_DIR)/BroadcastRadio/Tuner.cpp \
    $(LOCAL_REL_DIR)/BroadcastRadio/TunerCallback.cpp \
    $(LOCAL_REL_DIR)/BroadcastRadio/convert.cpp \
    $(LOCAL_REL_DIR)/BroadcastRadio/regions.cpp \
    $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
    $(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.cpp \
    $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
+39 −38
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@

#include "convert.h"

#include "regions.h"

#include <broadcastradio-utils/Utils.h>
#include <core_jni_helpers.h>
#include <nativehelper/JNIHelp.h>
@@ -29,8 +31,11 @@ namespace server {
namespace BroadcastRadio {
namespace convert {

namespace utils = V1_1::utils;

using hardware::Return;
using hardware::hidl_vec;
using regions::RegionalBandConfig;

using V1_0::Band;
using V1_0::Deemphasis;
@@ -43,6 +48,7 @@ using V1_1::ProgramListResult;
using V1_1::ProgramSelector;
using V1_1::VendorKeyValue;

static JavaRef<jobject> BandDescriptorFromHal(JNIEnv *env, const RegionalBandConfig &config);
static JavaRef<jobject> BandDescriptorFromHal(JNIEnv *env, const V1_0::BandConfig &config, Region region);

static struct {
@@ -334,9 +340,10 @@ static JavaRef<jobject> ModulePropertiesFromHal(JNIEnv *env, const V1_0::Propert
    auto jSerial = make_javastr(env, prop10.serial);
    bool isBgScanSupported = prop11 ? prop11->supportsBackgroundScanning : false;
    auto jVendorInfo = prop11 ? VendorInfoFromHal(env, prop11->vendorInfo) : nullptr;
    // ITU_1 is the default region just because its index is 0.
    auto jBands = ArrayFromHal<V1_0::BandConfig>(env, prop10.bands, gjni.BandDescriptor.clazz,
        std::bind(BandDescriptorFromHal, _1, _2, Region::ITU_1));

    auto regionalBands = regions::mapRegions(prop10.bands);
    auto jBands = ArrayFromHal<RegionalBandConfig>(env, regionalBands,
            gjni.BandDescriptor.clazz, BandDescriptorFromHal);
    auto jSupportedProgramTypes =
            prop11 ? ArrayFromHal(env, prop11->supportedProgramTypes) : nullptr;
    auto jSupportedIdentifierTypes =
@@ -359,30 +366,29 @@ JavaRef<jobject> ModulePropertiesFromHal(JNIEnv *env, const V1_1::Properties &pr
    return ModulePropertiesFromHal(env, properties.base, &properties, moduleId, serviceName);
}

static JavaRef<jobject> BandDescriptorFromHal(JNIEnv *env, const RegionalBandConfig &config) {
    return BandDescriptorFromHal(env, config.bandConfig, config.region);
}

static JavaRef<jobject> BandDescriptorFromHal(JNIEnv *env, const V1_0::BandConfig &config, Region region) {
    ALOGV("%s", __func__);

    jint spacing = config.spacings.size() > 0 ? config.spacings[0] : 0;
    ALOGW_IF(config.spacings.size() > 1, "Multiple spacings - not a regional config");
    ALOGW_IF(config.spacings.size() == 0, "No channel spacing specified");

    switch (config.type) {
        case Band::FM:
        case Band::FM_HD: {
    if (utils::isFm(config.type)) {
        auto& fm = config.ext.fm;
        return make_javaref(env, env->NewObject(
                gjni.FmBandDescriptor.clazz, gjni.FmBandDescriptor.cstor,
                region, config.type, config.lowerLimit, config.upperLimit, spacing,
                fm.stereo, fm.rds != Rds::NONE, fm.ta, fm.af, fm.ea));
        }
        case Band::AM:
        case Band::AM_HD: {
    } else if (utils::isAm(config.type)) {
        auto& am = config.ext.am;
        return make_javaref(env, env->NewObject(
                gjni.AmBandDescriptor.clazz, gjni.AmBandDescriptor.cstor,
                    region, config.type, config.lowerLimit, config.upperLimit, spacing,
                    am.stereo));
        }
        default:
                region, config.type, config.lowerLimit, config.upperLimit, spacing, am.stereo));
    } else {
        ALOGE("Unsupported band type: %d", config.type);
        return nullptr;
    }
@@ -394,18 +400,13 @@ JavaRef<jobject> BandConfigFromHal(JNIEnv *env, const V1_0::BandConfig &config,
    auto descriptor = BandDescriptorFromHal(env, config, region);
    if (descriptor == nullptr) return nullptr;

    switch (config.type) {
        case Band::FM:
        case Band::FM_HD: {
    if (utils::isFm(config.type)) {
        return make_javaref(env, env->NewObject(
                gjni.FmBandConfig.clazz, gjni.FmBandConfig.cstor, descriptor.get()));
        }
        case Band::AM:
        case Band::AM_HD: {
    } else if (utils::isAm(config.type)) {
        return make_javaref(env, env->NewObject(
                gjni.AmBandConfig.clazz, gjni.AmBandConfig.cstor, descriptor.get()));
        }
        default:
    } else {
        ALOGE("Unsupported band type: %d", config.type);
        return nullptr;
    }
@@ -583,7 +584,7 @@ static JavaRef<jobject> ProgramInfoFromHal(JNIEnv *env, const V1_0::ProgramInfo
}

JavaRef<jobject> ProgramInfoFromHal(JNIEnv *env, const V1_0::ProgramInfo &info, V1_0::Band band) {
    auto selector = V1_1::utils::make_selector(band, info.channel, info.subChannel);
    auto selector = utils::make_selector(band, info.channel, info.subChannel);
    return ProgramInfoFromHal(env, info, nullptr, selector);
}

+196 −0
Original line number Diff line number Diff line
/**
 * Copyright (C) 2017 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 "BroadcastRadioService.regions.jni"
#define LOG_NDEBUG 0

#include "regions.h"

#include <broadcastradio-utils/Utils.h>
#include <utils/Log.h>

namespace android {
namespace server {
namespace BroadcastRadio {
namespace regions {

namespace utils = hardware::broadcastradio::V1_1::utils;

using hardware::hidl_vec;

using V1_0::Band;
using V1_0::BandConfig;
using V1_0::Deemphasis;
using V1_0::Rds;

class RegionalBandDefinition {
public:
    std::vector<Region> mRegions;
    std::vector<Band> mTypes;
    uint32_t mLowerLimit;
    uint32_t mUpperLimit;
    uint32_t mSpacing;

    Deemphasis mFmDeemphasis = {};
    Rds mFmRds = Rds::NONE;

    bool fitsInsideBand(const BandConfig &bandConfig) const;
    std::vector<RegionalBandConfig> withConfig(BandConfig bandConfig) const;
};

static const RegionalBandDefinition kKnownRegionConfigs[] = {
    {
        { Region::ITU_1 },
        { Band::FM },
        87500,
        108000,
        100,
        Deemphasis::D50,
        Rds::WORLD,
    },
    {
        { Region::ITU_2 },
        { Band::FM, Band::FM_HD },
        87900,
        107900,
        200,
        Deemphasis::D75,
        Rds::US,
    },
    {
        { Region::OIRT },
        { Band::FM },
        65800,
        74000,
        10,
        Deemphasis::D50,
        Rds::WORLD,
    },
    {
        { Region::JAPAN },
        { Band::FM },
        76000,
        90000,
        100,
        Deemphasis::D50,
        Rds::WORLD,
    },
    {
        { Region::KOREA },
        { Band::FM },
        87500,
        108000,
        100,
        Deemphasis::D75,
        Rds::WORLD,
    },
    {  // AM LW
        { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA },
        { Band::AM },
        153,
        279,
        9,
    },
    {  // AM MW
        { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA },
        { Band::AM },
        531,
        1611,
        9,
    },
    {  // AM SW
        { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA },
        { Band::AM },
        2300,
        26100,
        5,
    },
    {  // AM LW ITU2
        { Region::ITU_2 },
        { Band::AM, Band::AM_HD },
        153,
        279,
        9,
    },
    {  // AM MW ITU2
        { Region::ITU_2 },
        { Band::AM, Band::AM_HD },
        540,
        1610,
        10,
    },
    {  // AM SW ITU2
        { Region::ITU_2 },
        { Band::AM, Band::AM_HD },
        2300,
        26100,
        5,
    },
};

bool RegionalBandDefinition::fitsInsideBand(const BandConfig &bandConfig) const {
    if (std::find(mTypes.begin(), mTypes.end(), bandConfig.type) == mTypes.end()) return false;
    if (mLowerLimit < bandConfig.lowerLimit) return false;
    if (mUpperLimit > bandConfig.upperLimit) return false;
    auto&& spacings = bandConfig.spacings;
    if (std::find(spacings.begin(), spacings.end(), mSpacing) == spacings.end()) return false;
    if (utils::isFm(bandConfig.type)) {
        if (0 == (mFmDeemphasis & bandConfig.ext.fm.deemphasis)) return false;
    }

    return true;
}

std::vector<RegionalBandConfig> RegionalBandDefinition::withConfig(BandConfig config) const {
    config.lowerLimit = mLowerLimit;
    config.upperLimit = mUpperLimit;
    config.spacings = hidl_vec<uint32_t>({ mSpacing });
    if (utils::isFm(config.type)) {
        auto&& fm = config.ext.fm;
        fm.deemphasis = mFmDeemphasis;
        fm.rds = static_cast<Rds>(mFmRds & fm.rds);
    }

    std::vector<RegionalBandConfig> configs;
    for (auto region : mRegions) {
        configs.push_back({region, config});
    }

    return configs;
}

std::vector<RegionalBandConfig> mapRegions(const hidl_vec<BandConfig>& bands) {
    ALOGV("%s", __func__);

    std::vector<RegionalBandConfig> out;

    for (auto&& regionalBand : kKnownRegionConfigs) {
        for (auto&& tunerBand : bands) {
            if (regionalBand.fitsInsideBand(tunerBand)) {
                auto mapped = regionalBand.withConfig(tunerBand);
                out.insert(out.end(), mapped.begin(), mapped.end());
            }
        }
    }

    ALOGI("Mapped %zu tuner bands to %zu regional bands", bands.size(), out.size());
    return out;
}

} // namespace regions
} // namespace BroadcastRadio
} // namespace server
} // namespace android
+44 −0
Original line number Diff line number Diff line
/**
 * Copyright (C) 2017 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_SERVER_BROADCASTRADIO_REGIONS_H
#define _ANDROID_SERVER_BROADCASTRADIO_REGIONS_H

#include "types.h"

#include <android/hardware/broadcastradio/1.1/types.h>

namespace android {
namespace server {
namespace BroadcastRadio {
namespace regions {

namespace V1_0 = hardware::broadcastradio::V1_0;

struct RegionalBandConfig {
    Region region;
    V1_0::BandConfig bandConfig;
};

std::vector<RegionalBandConfig>
mapRegions(const hardware::hidl_vec<V1_0::BandConfig>& bands);

} // namespace regions
} // namespace BroadcastRadio
} // namespace server
} // namespace android

#endif // _ANDROID_SERVER_BROADCASTRADIO_REGIONS_H