blob: dca431d68a51fd4d3bda72535475162e39943d32 [file] [log] [blame]
Weilin Xub2a6ca62022-05-08 23:47:04 +00001/*
2 * Copyright (C) 2022 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
17#include "VirtualProgram.h"
18
19#include <broadcastradio-utils-aidl/Utils.h>
20#include "resources.h"
21
22#include <android-base/logging.h>
23
24namespace aidl::android::hardware::broadcastradio {
25
26using ::std::vector;
27
28VirtualProgram::operator ProgramInfo() const {
29 ProgramInfo info = {};
30
31 info.selector = selector;
32
33 IdentifierType programType = selector.primaryId.type;
34 bool isDigital = (programType != IdentifierType::AMFM_FREQUENCY_KHZ &&
35 programType != IdentifierType::RDS_PI);
36
37 auto selectId = [&info](const IdentifierType& type) {
38 return utils::makeIdentifier(type, utils::getId(info.selector, type));
39 };
40
41 switch (programType) {
42 case IdentifierType::AMFM_FREQUENCY_KHZ:
43 info.logicallyTunedTo = info.physicallyTunedTo =
44 selectId(IdentifierType::AMFM_FREQUENCY_KHZ);
45 break;
46 case IdentifierType::RDS_PI:
47 info.logicallyTunedTo = selectId(IdentifierType::RDS_PI);
48 info.physicallyTunedTo = selectId(IdentifierType::AMFM_FREQUENCY_KHZ);
49 break;
50 case IdentifierType::HD_STATION_ID_EXT:
51 info.logicallyTunedTo = selectId(IdentifierType::HD_STATION_ID_EXT);
Weilin Xu39dd0f82023-09-07 17:00:57 -070052 if (utils::hasId(info.selector, IdentifierType::AMFM_FREQUENCY_KHZ)) {
53 info.physicallyTunedTo = selectId(IdentifierType::AMFM_FREQUENCY_KHZ);
54 } else {
55 info.physicallyTunedTo = utils::makeIdentifier(
56 IdentifierType::AMFM_FREQUENCY_KHZ, utils::getHdFrequency(info.selector));
57 }
Weilin Xub2a6ca62022-05-08 23:47:04 +000058 break;
59 case IdentifierType::DAB_SID_EXT:
60 info.logicallyTunedTo = selectId(IdentifierType::DAB_SID_EXT);
Weilin Xu0d4207d2022-12-09 00:37:44 +000061 info.physicallyTunedTo = selectId(IdentifierType::DAB_FREQUENCY_KHZ);
Weilin Xub2a6ca62022-05-08 23:47:04 +000062 break;
63 case IdentifierType::DRMO_SERVICE_ID:
64 info.logicallyTunedTo = selectId(IdentifierType::DRMO_SERVICE_ID);
65 info.physicallyTunedTo = selectId(IdentifierType::DRMO_FREQUENCY_KHZ);
66 break;
67 case IdentifierType::SXM_SERVICE_ID:
68 info.logicallyTunedTo = selectId(IdentifierType::SXM_SERVICE_ID);
69 info.physicallyTunedTo = selectId(IdentifierType::SXM_CHANNEL);
70 break;
71 default:
72 LOG(FATAL) << "unsupported program type: " << toString(programType);
73 return {};
74 }
75
76 info.infoFlags |= (ProgramInfo::FLAG_TUNABLE | ProgramInfo::FLAG_STEREO);
77 info.signalQuality = isDigital ? kSignalQualityDigital : kSignalQualityNonDigital;
78
79 info.metadata = vector<Metadata>({
80 Metadata::make<Metadata::rdsPs>(programName),
81 Metadata::make<Metadata::songTitle>(songTitle),
82 Metadata::make<Metadata::songArtist>(songArtist),
83 Metadata::make<Metadata::stationIcon>(resources::kDemoPngId),
84 Metadata::make<Metadata::albumArt>(resources::kDemoPngId),
85 });
86
87 info.vendorInfo = vector<VendorKeyValue>({
88 {"com.android.sample", "sample"},
89 {"com.android.sample.VirtualProgram", "VirtualProgram"},
90 });
91
92 return info;
93}
94
95bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) {
96 auto& l = lhs.selector;
97 auto& r = rhs.selector;
98
Weilin Xu39dd0f82023-09-07 17:00:57 -070099 if ((utils::hasId(l, IdentifierType::AMFM_FREQUENCY_KHZ) ||
100 l.primaryId.type == IdentifierType::HD_STATION_ID_EXT) &&
101 (utils::hasId(r, IdentifierType::AMFM_FREQUENCY_KHZ) ||
102 r.primaryId.type == IdentifierType::HD_STATION_ID_EXT)) {
103 uint32_t freq1 = utils::getAmFmFrequency(l);
104 int subChannel1 = l.primaryId.type == IdentifierType::HD_STATION_ID_EXT
105 ? utils::getHdSubchannel(l)
106 : 0;
107 uint32_t freq2 = utils::getAmFmFrequency(r);
108 int subChannel2 = r.primaryId.type == IdentifierType::HD_STATION_ID_EXT
109 ? utils::getHdSubchannel(r)
110 : 0;
111 return freq1 < freq2 || (freq1 == freq2 && (l.primaryId.type < r.primaryId.type ||
112 subChannel1 < subChannel2));
113 } else if (l.primaryId.type == IdentifierType::DAB_SID_EXT &&
Weilin Xu90e39f52023-11-07 20:07:23 -0800114 r.primaryId.type == IdentifierType::DAB_SID_EXT) {
Weilin Xu39dd0f82023-09-07 17:00:57 -0700115 uint64_t dabFreq1 = utils::getId(l, IdentifierType::DAB_FREQUENCY_KHZ);
116 uint64_t dabFreq2 = utils::getId(r, IdentifierType::DAB_FREQUENCY_KHZ);
117 if (dabFreq1 != dabFreq2) {
118 return dabFreq1 < dabFreq2;
119 }
Weilin Xu90e39f52023-11-07 20:07:23 -0800120 uint32_t ecc1 = utils::getDabEccCode(l);
121 uint32_t ecc2 = utils::getDabEccCode(r);
122 if (ecc1 != ecc2) {
123 return ecc1 < ecc2;
124 }
125 uint64_t dabEnsemble1 = utils::getId(l, IdentifierType::DAB_ENSEMBLE);
126 uint64_t dabEnsemble2 = utils::getId(r, IdentifierType::DAB_ENSEMBLE);
127 if (dabEnsemble1 != dabEnsemble2) {
128 return dabEnsemble1 < dabEnsemble2;
129 }
130 uint32_t sId1 = utils::getDabSId(l);
131 uint32_t sId2 = utils::getDabSId(r);
132 return sId1 < sId2 || (sId1 == sId2 && utils::getDabSCIdS(l) < utils::getDabSCIdS(r));
Weilin Xu39dd0f82023-09-07 17:00:57 -0700133 }
Weilin Xub2a6ca62022-05-08 23:47:04 +0000134
Weilin Xu39dd0f82023-09-07 17:00:57 -0700135 if (l.primaryId.type != r.primaryId.type) {
136 return l.primaryId.type < r.primaryId.type;
137 }
Weilin Xub2a6ca62022-05-08 23:47:04 +0000138 return l.primaryId.value < r.primaryId.value;
139}
140
141} // namespace aidl::android::hardware::broadcastradio