OSDN Git Service

release-request-bd6aa7dd-7b02-4794-942c-14599bf61208-for-git_oc-mr1-release-4193791...
[android-x86/hardware-interfaces.git] / broadcastradio / 1.1 / utils / Utils.cpp
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #define LOG_TAG "BroadcastRadioDefault.utils"
17 //#define LOG_NDEBUG 0
18
19 #include "Utils.h"
20
21 #include <log/log.h>
22
23 namespace android {
24 namespace hardware {
25 namespace broadcastradio {
26 namespace V1_1 {
27 namespace utils {
28
29 using V1_0::Band;
30
31 static bool isCompatibleProgramType(const uint32_t ia, const uint32_t ib) {
32     auto a = static_cast<ProgramType>(ia);
33     auto b = static_cast<ProgramType>(ib);
34
35     if (a == b) return true;
36     if (a == ProgramType::AM && b == ProgramType::AM_HD) return true;
37     if (a == ProgramType::AM_HD && b == ProgramType::AM) return true;
38     if (a == ProgramType::FM && b == ProgramType::FM_HD) return true;
39     if (a == ProgramType::FM_HD && b == ProgramType::FM) return true;
40     return false;
41 }
42
43 static bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
44                        const IdentifierType type) {
45     return hasId(a, type) && hasId(b, type);
46 }
47
48 static bool anyHaveId(const ProgramSelector& a, const ProgramSelector& b,
49                       const IdentifierType type) {
50     return hasId(a, type) || hasId(b, type);
51 }
52
53 static bool haveEqualIds(const ProgramSelector& a, const ProgramSelector& b,
54                          const IdentifierType type) {
55     if (!bothHaveId(a, b, type)) return false;
56     // TODO(b/36864090): we should check all Ids of a given type (ie. other AF), not just one
57     auto aId = getId(a, type);
58     auto bId = getId(b, type);
59     return aId == bId;
60 }
61
62 bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
63     if (!isCompatibleProgramType(a.programType, b.programType)) return false;
64
65     auto type = getType(a);
66
67     switch (type) {
68         case ProgramType::AM:
69         case ProgramType::AM_HD:
70         case ProgramType::FM:
71         case ProgramType::FM_HD:
72             if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
73
74             // if HD Radio subchannel is specified, it must match
75             if (anyHaveId(a, b, IdentifierType::HD_SUBCHANNEL)) {
76                 // missing subchannel (analog) is an equivalent of first subchannel (MPS)
77                 auto aCh = getId(a, IdentifierType::HD_SUBCHANNEL, 0);
78                 auto bCh = getId(b, IdentifierType::HD_SUBCHANNEL, 0);
79                 if (aCh != bCh) return false;
80             }
81
82             if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
83
84             return haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
85         case ProgramType::DAB:
86             return haveEqualIds(a, b, IdentifierType::DAB_SIDECC);
87         case ProgramType::DRMO:
88             return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
89         case ProgramType::SXM:
90             if (anyHaveId(a, b, IdentifierType::SXM_SERVICE_ID)) {
91                 return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
92             }
93             return haveEqualIds(a, b, IdentifierType::SXM_CHANNEL);
94         case ProgramType::VENDOR1:
95         case ProgramType::VENDOR2:
96         case ProgramType::VENDOR3:
97         case ProgramType::VENDOR4:
98         default:
99             ALOGW("Unsupported program type: %s", toString(type).c_str());
100             return false;
101     }
102 }
103
104 ProgramType getType(const ProgramSelector& sel) {
105     return static_cast<ProgramType>(sel.programType);
106 }
107
108 bool isAmFm(const ProgramType type) {
109     switch (type) {
110         case ProgramType::AM:
111         case ProgramType::FM:
112         case ProgramType::AM_HD:
113         case ProgramType::FM_HD:
114             return true;
115         default:
116             return false;
117     }
118 }
119
120 bool hasId(const ProgramSelector& sel, const IdentifierType type) {
121     auto itype = static_cast<uint32_t>(type);
122     if (sel.primaryId.type == itype) return true;
123     // not optimal, but we don't care in default impl
124     for (auto&& id : sel.secondaryIds) {
125         if (id.type == itype) return true;
126     }
127     return false;
128 }
129
130 uint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
131     auto itype = static_cast<uint32_t>(type);
132     if (sel.primaryId.type == itype) return sel.primaryId.value;
133     // not optimal, but we don't care in default impl
134     for (auto&& id : sel.secondaryIds) {
135         if (id.type == itype) return id.value;
136     }
137     ALOGW("Identifier %s not found", toString(type).c_str());
138     return 0;
139 }
140
141 uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval) {
142     if (!hasId(sel, type)) return defval;
143     return getId(sel, type);
144 }
145
146 ProgramSelector make_selector(Band band, uint32_t channel, uint32_t subChannel) {
147     ProgramSelector sel = {};
148
149     ALOGW_IF((subChannel > 0) && (band == Band::AM || band == Band::FM),
150              "got subChannel for non-HD AM/FM");
151
152     // we can't use ProgramType::AM_HD or FM_HD, because we don't know HD station ID
153     ProgramType type;
154     switch (band) {
155         case Band::AM:
156         case Band::AM_HD:
157             type = ProgramType::AM;
158             break;
159         case Band::FM:
160         case Band::FM_HD:
161             type = ProgramType::FM;
162             break;
163         default:
164             LOG_ALWAYS_FATAL("Unsupported band: %s", toString(band).c_str());
165     }
166
167     sel.programType = static_cast<uint32_t>(type);
168     sel.primaryId.type = static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY);
169     sel.primaryId.value = channel;
170     if (subChannel > 0) {
171         /* stating sub channel for AM/FM channel does not give any guarantees,
172          * but we can't do much more without HD station ID
173          *
174          * The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
175          */
176         sel.secondaryIds = hidl_vec<ProgramIdentifier>{
177             {static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL), subChannel - 1},
178         };
179     }
180
181     return sel;
182 }
183
184 bool getLegacyChannel(const ProgramSelector& sel, uint32_t* channelOut, uint32_t* subChannelOut) {
185     if (channelOut) *channelOut = 0;
186     if (subChannelOut) *subChannelOut = 0;
187     if (isAmFm(getType(sel))) {
188         if (channelOut) *channelOut = getId(sel, IdentifierType::AMFM_FREQUENCY);
189         if (subChannelOut && hasId(sel, IdentifierType::HD_SUBCHANNEL)) {
190             // The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
191             *subChannelOut = getId(sel, IdentifierType::HD_SUBCHANNEL) + 1;
192         }
193         return true;
194     }
195     return false;
196 }
197
198 bool isDigital(const ProgramSelector& sel) {
199     switch (getType(sel)) {
200         case ProgramType::AM:
201         case ProgramType::FM:
202             return false;
203         default:
204             // VENDOR might not be digital, but it doesn't matter for default impl.
205             return true;
206     }
207 }
208
209 }  // namespace utils
210 }  // namespace V1_1
211 }  // namespace broadcastradio
212 }  // namespace hardware
213 }  // namespace android