1a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk/*
2a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * Copyright (C) 2017 The Android Open Source Project
3a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk *
4a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * Licensed under the Apache License, Version 2.0 (the "License");
5a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * you may not use this file except in compliance with the License.
6a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * You may obtain a copy of the License at
7a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk *
8a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk *      http://www.apache.org/licenses/LICENSE-2.0
9a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk *
10a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * Unless required by applicable law or agreed to in writing, software
11a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * distributed under the License is distributed on an "AS IS" BASIS,
12a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * See the License for the specific language governing permissions and
14a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk * limitations under the License.
15a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk */
16a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk#define LOG_TAG "BroadcastRadioDefault.utils"
17a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk//#define LOG_NDEBUG 0
18a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
1906100b39db99dd5b7860a6e981ba9f8d511793faTomasz Wasilczyk#include <broadcastradio-utils-1x/Utils.h>
20a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
21a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk#include <log/log.h>
22a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
23a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyknamespace android {
24a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyknamespace hardware {
25a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyknamespace broadcastradio {
26a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyknamespace utils {
27a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
28a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykusing V1_0::Band;
298c34c8179d4b745338e6200b337488ef9ad4b7edTomasz Wasilczykusing V1_1::IdentifierType;
30f679e8b6ece550ea84348c70b8e414d92fc4a5c6Tomasz Wasilczykusing V1_1::ProgramIdentifier;
31f679e8b6ece550ea84348c70b8e414d92fc4a5c6Tomasz Wasilczykusing V1_1::ProgramSelector;
32f679e8b6ece550ea84348c70b8e414d92fc4a5c6Tomasz Wasilczykusing V1_1::ProgramType;
33a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
34a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykstatic bool isCompatibleProgramType(const uint32_t ia, const uint32_t ib) {
35a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    auto a = static_cast<ProgramType>(ia);
36a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    auto b = static_cast<ProgramType>(ib);
37a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
38a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (a == b) return true;
39a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (a == ProgramType::AM && b == ProgramType::AM_HD) return true;
40a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (a == ProgramType::AM_HD && b == ProgramType::AM) return true;
41a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (a == ProgramType::FM && b == ProgramType::FM_HD) return true;
42a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (a == ProgramType::FM_HD && b == ProgramType::FM) return true;
43a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    return false;
44a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
45a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
46a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykstatic bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
47a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk                       const IdentifierType type) {
48a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    return hasId(a, type) && hasId(b, type);
49a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
50a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
51a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykstatic bool anyHaveId(const ProgramSelector& a, const ProgramSelector& b,
52a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk                      const IdentifierType type) {
53a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    return hasId(a, type) || hasId(b, type);
54a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
55a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
56a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykstatic bool haveEqualIds(const ProgramSelector& a, const ProgramSelector& b,
57a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk                         const IdentifierType type) {
58a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (!bothHaveId(a, b, type)) return false;
59753c1d1ef27a7f0519c954ffa462fae0cfb18976Tomasz Wasilczyk    /* We should check all Ids of a given type (ie. other AF),
60753c1d1ef27a7f0519c954ffa462fae0cfb18976Tomasz Wasilczyk     * but it doesn't matter for default implementation.
61753c1d1ef27a7f0519c954ffa462fae0cfb18976Tomasz Wasilczyk     */
6206100b39db99dd5b7860a6e981ba9f8d511793faTomasz Wasilczyk    return getId(a, type) == getId(b, type);
63a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
64a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
65a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykbool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
66a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (!isCompatibleProgramType(a.programType, b.programType)) return false;
67a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
68a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    auto type = getType(a);
69a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
70a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    switch (type) {
71a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::AM:
72a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::AM_HD:
73a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::FM:
74a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::FM_HD:
75a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
76a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
77a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            // if HD Radio subchannel is specified, it must match
78a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            if (anyHaveId(a, b, IdentifierType::HD_SUBCHANNEL)) {
79a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk                // missing subchannel (analog) is an equivalent of first subchannel (MPS)
80a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk                auto aCh = getId(a, IdentifierType::HD_SUBCHANNEL, 0);
81a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk                auto bCh = getId(b, IdentifierType::HD_SUBCHANNEL, 0);
82a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk                if (aCh != bCh) return false;
83a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            }
84a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
85a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
86a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
87a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            return haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
88a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::DAB:
898c34c8179d4b745338e6200b337488ef9ad4b7edTomasz Wasilczyk            return haveEqualIds(a, b, IdentifierType::DAB_SIDECC);
90a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::DRMO:
91a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
92a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::SXM:
93a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            if (anyHaveId(a, b, IdentifierType::SXM_SERVICE_ID)) {
94a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk                return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
95a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            }
96a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            return haveEqualIds(a, b, IdentifierType::SXM_CHANNEL);
97da97a6dd42c1fdacc5110c8b04e95d67321697d5Tomasz Wasilczyk        default:  // includes all vendor types
98a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            ALOGW("Unsupported program type: %s", toString(type).c_str());
99a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            return false;
100a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    }
101a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
102a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
103a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz WasilczykProgramType getType(const ProgramSelector& sel) {
104a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    return static_cast<ProgramType>(sel.programType);
105a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
106a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
107a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykbool isAmFm(const ProgramType type) {
108a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    switch (type) {
109a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::AM:
110a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::FM:
111a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::AM_HD:
112a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::FM_HD:
113a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            return true;
114a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        default:
115a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            return false;
116a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    }
117a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
118a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
119701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczykbool isAm(const Band band) {
120701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk    return band == Band::AM || band == Band::AM_HD;
121701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk}
122701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk
123701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczykbool isFm(const Band band) {
124701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk    return band == Band::FM || band == Band::FM_HD;
125701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk}
126701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk
127002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczykstatic bool maybeGetId(const ProgramSelector& sel, const IdentifierType type, uint64_t* val) {
128a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    auto itype = static_cast<uint32_t>(type);
129002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk
1308c34c8179d4b745338e6200b337488ef9ad4b7edTomasz Wasilczyk    if (sel.primaryId.type == itype) {
131002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk        if (val) *val = sel.primaryId.value;
132002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk        return true;
133002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk    }
134002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk
135a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    // not optimal, but we don't care in default impl
136a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    for (auto&& id : sel.secondaryIds) {
137002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk        if (id.type == itype) {
138002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk            if (val) *val = id.value;
139002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk            return true;
140002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk        }
141a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    }
142002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk
1438c34c8179d4b745338e6200b337488ef9ad4b7edTomasz Wasilczyk    return false;
144002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk}
145002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk
146002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczykbool hasId(const ProgramSelector& sel, const IdentifierType type) {
147002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk    return maybeGetId(sel, type, nullptr);
148a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
149a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
150a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykuint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
151002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk    uint64_t val;
152002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk
153002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk    if (maybeGetId(sel, type, &val)) {
154002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk        return val;
155a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    }
156002151ce255f171a3bfdd3bbf2f2ed5d63f77541Tomasz Wasilczyk
157a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    ALOGW("Identifier %s not found", toString(type).c_str());
158a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    return 0;
159a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
160a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
161a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykuint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval) {
162a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (!hasId(sel, type)) return defval;
163a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    return getId(sel, type);
164a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
165a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
166a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz WasilczykProgramSelector make_selector(Band band, uint32_t channel, uint32_t subChannel) {
167a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    ProgramSelector sel = {};
168a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
169a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    ALOGW_IF((subChannel > 0) && (band == Band::AM || band == Band::FM),
170a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk             "got subChannel for non-HD AM/FM");
171a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
172a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    // we can't use ProgramType::AM_HD or FM_HD, because we don't know HD station ID
173a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    ProgramType type;
174701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk    if (isAm(band)) {
175701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk        type = ProgramType::AM;
176701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk    } else if (isFm(band)) {
177701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk        type = ProgramType::FM;
178701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk    } else {
179701a5bdda51a8b2feddbb5e82a3ac3bbc6ce3fddTomasz Wasilczyk        LOG_ALWAYS_FATAL("Unsupported band: %s", toString(band).c_str());
180a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    }
181a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
182a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    sel.programType = static_cast<uint32_t>(type);
183a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    sel.primaryId.type = static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY);
184a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    sel.primaryId.value = channel;
185a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (subChannel > 0) {
1862834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk        /* stating sub channel for AM/FM channel does not give any guarantees,
1872834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk         * but we can't do much more without HD station ID
1882834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk         *
1892834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk         * The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
1902834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk         */
191a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        sel.secondaryIds = hidl_vec<ProgramIdentifier>{
1922834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk            {static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL), subChannel - 1},
193a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        };
194a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    }
195a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
196a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    return sel;
197a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
198a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
1992834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczykbool getLegacyChannel(const ProgramSelector& sel, uint32_t* channelOut, uint32_t* subChannelOut) {
2002834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk    if (channelOut) *channelOut = 0;
2012834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk    if (subChannelOut) *subChannelOut = 0;
202a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    if (isAmFm(getType(sel))) {
2032834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk        if (channelOut) *channelOut = getId(sel, IdentifierType::AMFM_FREQUENCY);
2042834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk        if (subChannelOut && hasId(sel, IdentifierType::HD_SUBCHANNEL)) {
2052834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk            // The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
2062834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk            *subChannelOut = getId(sel, IdentifierType::HD_SUBCHANNEL) + 1;
2072834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk        }
208a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        return true;
209a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    }
2102834b95b12edb0b234594b21bcb4b44cc797fc90Tomasz Wasilczyk    return false;
211a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
212a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
213a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczykbool isDigital(const ProgramSelector& sel) {
214a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    switch (getType(sel)) {
215a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::AM:
216a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        case ProgramType::FM:
217a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            return false;
218a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk        default:
219a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            // VENDOR might not be digital, but it doesn't matter for default impl.
220a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk            return true;
221a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk    }
222a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}
223a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk
224a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}  // namespace utils
225c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk
226c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyknamespace V1_0 {
227c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk
228c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczykbool operator==(const BandConfig& l, const BandConfig& r) {
22906100b39db99dd5b7860a6e981ba9f8d511793faTomasz Wasilczyk    using namespace utils;
23006100b39db99dd5b7860a6e981ba9f8d511793faTomasz Wasilczyk
231c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk    if (l.type != r.type) return false;
232c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk    if (l.antennaConnected != r.antennaConnected) return false;
233c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk    if (l.lowerLimit != r.lowerLimit) return false;
234c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk    if (l.upperLimit != r.upperLimit) return false;
235c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk    if (l.spacings != r.spacings) return false;
23606100b39db99dd5b7860a6e981ba9f8d511793faTomasz Wasilczyk    if (isAm(l.type)) {
237c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk        return l.ext.am == r.ext.am;
23806100b39db99dd5b7860a6e981ba9f8d511793faTomasz Wasilczyk    } else if (isFm(l.type)) {
239c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk        return l.ext.fm == r.ext.fm;
240c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk    } else {
241c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk        ALOGW("Unsupported band config type: %s", toString(l.type).c_str());
242c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk        return false;
243c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk    }
244c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk}
245c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk
246c1763a679659cdb1a50f7b4640b6c3f659f1d666Tomasz Wasilczyk}  // namespace V1_0
247a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}  // namespace broadcastradio
248a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}  // namespace hardware
249a02b6ef23c6dd0405ceb1337ba05bf4e0087890cTomasz Wasilczyk}  // namespace android
250