/**
 * Copyright 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.
 */

package android.hardware.broadcastradio@1.1;

import @1.0::types;

typedef @1.0::Result Result;

enum ProgramListResult : Result {
    NOT_READY,
    NOT_STARTED,
    UNAVAILABLE,
};

/**
 * Extra flags for program information.
 */
enum ProgramInfoFlags : uint32_t {
    /**
     * Set when the program is currently playing live stream.
     * This may result in a slightly altered reception parameters,
     * usually targetted at reduced latency.
     */
    LIVE = 1 << 0,

    /**
     * Radio stream is not playing, ie. due to bad reception conditions or
     * buffering. In this state volume knob MAY be disabled to prevent user
     * increasing volume too much.
     */
    MUTED = 1 << 1,

    /**
     * Station broadcasts traffic information regularly,
     * but not necessarily right now.
     */
    TRAFFIC_PROGRAM = 1 << 2,

    /**
     * Station is broadcasting traffic information at the very moment.
     */
    TRAFFIC_ANNOUNCEMENT = 1 << 3,
};

/**
 * A key-value pair for vendor-specific information to be passed as-is through
 * Android framework to the front-end application.
 */
struct VendorKeyValue {
    /**
     * Key must be prefixed with unique vendor Java-style namespace,
     * eg. 'com.somecompany.parameter1'.
     */
    string key;

    /**
     * Value must be passed through the framework without any changes.
     * Format of this string can vary across vendors.
     */
    string value;
};

struct Properties {
    @1.0::Properties base;

    /**
     * The hardware supports background scanning in general. At the given time
     * it may not be available though, see startBackgroundScan.
     */
    bool supportsBackgroundScanning;

    /**
     * A list of supported ProgramType values.
     *
     * If a program type is supported by radio module, it means it can tune
     * to ProgramSelector of a given type.
     *
     * Support for VENDOR program type does not guarantee compatibility, as
     * other module properties (implementor, product, version) must be checked.
     */
    vec<uint32_t> supportedProgramTypes;

    /**
     * A list of supported IdentifierType values.
     *
     * If an identifier is supported by radio module, it means it can use it for
     * tuning to ProgramSelector with either primary or secondary Identifier of
     * a given type.
     *
     * Support for VENDOR identifier type does not guarantee compatibility, as
     * other module properties (implementor, product, version) must be checked.
     */
    vec<uint32_t> supportedIdentifierTypes;

    /**
     * Vendor-specific information.
     *
     * It may be used for extra features, not supported by the platform,
     * for example: com.me.preset-slots=6; com.me.ultra-hd-capable=false.
     */
    vec<VendorKeyValue> vendorInfo;
};

/**
 * Type of modulation.
 *
 * Used as a value for DRMO_MODULATION IdentifierType.
 */
enum Modulation : uint32_t {
    AM = 1,
    FM,
};

/**
 * Type of a radio technology.
 *
 * VENDOR program types must be opaque to the framework.
 *
 * There are multiple VENDOR program types just to make vendor implementation
 * easier with multiple properitary radio technologies. They are treated the
 * same by the framework.
 *
 * All other values are reserved for future use.
 * Values not matching any enumerated constant must be ignored.
 */
enum ProgramType : uint32_t {
    AM = 1,  // analogue AM radio (with or without RDS)
    FM,      // analogue FM radio (with or without RDS)
    AM_HD,   // AM HD Radio
    FM_HD,   // FM HD Radio
    DAB,     // Digital audio broadcasting
    DRMO,    // Digital Radio Mondiale
    SXM,     // SiriusXM Satellite Radio

    // Vendor-specific, not synced across devices.
    VENDOR_START = 1000,
    VENDOR_END = 1999,
};

/**
 * Type of program identifier component.
 *
 * It MUST match the radio technology for primary ID but does not have to match
 * it for secondary IDs. For example, a satellite program may set AM/FM fallback
 * frequency, if a station broadcasts both via satellite and AM/FM.
 *
 * VENDOR identifier types must be opaque to the framework.
 *
 * The value format for each (but VENDOR_PRIMARY) identifier is strictly defined
 * to maintain interoperability between devices made by different vendors.
 *
 * All other values are reserved for future use.
 * Values not matching any enumerated constant must be ignored.
 */
enum IdentifierType : uint32_t {
    AMFM_FREQUENCY = 1,  // kHz
    RDS_PI,              // 16bit

    /**
     * 64bit compound primary identifier for HD Radio.
     *
     * Consists of (from the LSB):
     * - 32bit: Station ID number;
     * - 4bit: HD_SUBCHANNEL;
     * - 18bit: AMFM_FREQUENCY.
     * The remaining bits should be set to zeros when writing on the chip side
     * and ignored when read.
     */
    HD_STATION_ID_EXT,

    /**
     * HD Radio subchannel - a value of range 0-7.
     *
     * The subchannel index is 0-based (where 0 is MPS and 1..7 are SPS),
     * as opposed to HD Radio standard (where it's 1-based).
     */
    HD_SUBCHANNEL,

    /**
     * 24bit compound primary identifier for DAB.
     *
     * Consists of (from the LSB):
     * - 16bit: SId;
     * - 8bit: ECC code.
     * The remaining bits should be set to zeros when writing on the chip side
     * and ignored when read.
     */
    DAB_SIDECC,

    DAB_ENSEMBLE,     // 16bit
    DAB_SCID,         // 12bit
    DAB_FREQUENCY,    // kHz
    DRMO_SERVICE_ID,  // 24bit
    DRMO_FREQUENCY,   // kHz
    DRMO_MODULATION,  // Modulation enum
    SXM_SERVICE_ID,   // 32bit
    SXM_CHANNEL,      // 0-999 range

    /**
     * Primary identifier for vendor-specific radio technology.
     * The value format is determined by a vendor.
     *
     * It must not be used in any other programType than corresponding VENDOR
     * type between VENDOR_START and VENDOR_END (eg. identifier type 1015 must
     * not be used in any program type other than 1015).
     */
    VENDOR_PRIMARY_START = ProgramType:VENDOR_START,
    VENDOR_PRIMARY_END = ProgramType:VENDOR_END,
};

/**
 * A single program identifier component, eg. frequency or channel ID.
 *
 * The uint32_t type field maps to IdentifierType enum. It's not straight,
 * because the enum may be extended in future versions of the HAL. Values out of
 * the enum range must not be used when writing and ignored when reading.
 *
 * The uint64_t value field holds the value in format described in comments for
 * IdentifierType enum.
 */
struct ProgramIdentifier {
    uint32_t type;  // IdentifierType
    uint64_t value;
};

/**
 * A set of identifiers necessary to tune to a given station.
 *
 * This can hold various identifiers, like
 * - AM/FM frequency
 * - HD Radio subchannel
 * - DAB channel info
 *
 * The uint32_t programType field maps to ProgramType enum. It's not straight,
 * because the enum may be extended in future versions of the HAL. Values out of
 * the enum range must not be used when writing and ignored when reading.
 *
 * The primary ID uniquely identifies a station and can be used for equality
 * check. The secondary IDs are supplementary and can speed up tuning process,
 * but the primary ID is sufficient (ie. after a full band scan).
 *
 * Two selectors with different secondary IDs, but the same primary ID are
 * considered equal. In particular, secondary IDs vector may get updated for
 * an entry on the program list (ie. when a better frequency for a given
 * station is found).
 *
 * The primaryId of a given programType MUST be of a specific type:
 * - AM, FM: RDS_PI if the station broadcasts RDS, AMFM_FREQUENCY otherwise;
 * - AM_HD, FM_HD: HD_STATION_ID_EXT;
 * - DAB: DAB_SIDECC;
 * - DRMO: DRMO_SERVICE_ID;
 * - SXM: SXM_SERVICE_ID;
 * - VENDOR: VENDOR_PRIMARY.
 */
struct ProgramSelector {
    uint32_t programType;  // ProgramType
    ProgramIdentifier primaryId;  // uniquely identifies a station
    vec<ProgramIdentifier> secondaryIds;

    /**
     * Opaque vendor-specific identifiers, to be passed to front-end
     * without changes.
     *
     * The order is meaningful, ie. the first element may be defined as
     * frequency, second as the subchannel etc.
     *
     * The vector is not serialized (either locally or to the cloud),
     * unless it's a VENDOR program type.
     */
    vec<uint64_t> vendorIds;
};

/**
 * Radio program information. Returned by the HAL with event RADIO_EVENT_TUNED.
 * Contains information on currently tuned channel.
 */
struct ProgramInfo {
    @1.0::ProgramInfo base;

    ProgramSelector selector;

    bitfield<ProgramInfoFlags> flags;

    /**
     * Vendor-specific information.
     *
     * It may be used for extra features, not supported by the platform,
     * for example: paid-service=true; bitrate=320kbps.
     */
    vec<VendorKeyValue> vendorInfo;
};
