1 /*
2 * Copyright (C) 2020 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 <gtest/gtest.h>
18 #include <stddef.h>
19
20 #include <string.h>
21
22 #include "chpp/common/wwan_types.h"
23 #include "chpp/memory.h"
24
25 namespace {
26
27 // clang-format off
28 const chreWwanCellInfo kChreCells[] = {
29 {
30 .timeStamp = 1234,
31 .cellInfoType = CHRE_WWAN_CELL_INFO_TYPE_LTE,
32 .timeStampType = CHRE_WWAN_CELL_TIMESTAMP_TYPE_MODEM,
33 .registered = 1,
34 .reserved = 111, // ignored
35 .CellInfo = {
36 .lte = {
37 .cellIdentityLte = {
38 .mcc = 777,
39 .mnc = 888,
40 .ci = 4321,
41 .pci = 333,
42 .tac = 9876,
43 .earfcn = 5432,
44 },
45 .signalStrengthLte = {
46 .signalStrength = 27,
47 .rsrp = 96,
48 .rsrq = 18,
49 .rssnr = 157,
50 .cqi = 13,
51 .timingAdvance = INT32_MAX,
52 }
53 }
54 }
55 },
56 {
57 .timeStamp = 1235,
58 .cellInfoType = CHRE_WWAN_CELL_INFO_TYPE_WCDMA,
59 .timeStampType = CHRE_WWAN_CELL_TIMESTAMP_TYPE_ANTENNA,
60 .registered = 0,
61 .CellInfo = {
62 .wcdma = {
63 .cellIdentityWcdma = {
64 .mcc = 123,
65 .mnc = 456,
66 .lac = 789,
67 .cid = 012,
68 .psc = 345,
69 .uarfcn = 678,
70 },
71 .signalStrengthWcdma = {
72 .signalStrength = 99,
73 .bitErrorRate = INT32_MAX,
74 }
75 }
76 }
77 },
78 };
79 const chreWwanCellInfoResult kChreResultOneCell = {
80 .errorCode = 0,
81 .cellInfoCount = 1,
82 .cells = kChreCells,
83 };
84 const chreWwanCellInfoResult kChreResultTwoCell = {
85 .errorCode = 0,
86 .cellInfoCount = 2,
87 .cells = kChreCells,
88 };
89 // clang-format on
90
compareCellInfo(const chreWwanCellInfo * chre,const ChppWwanCellInfo * chppIn)91 void compareCellInfo(const chreWwanCellInfo *chre,
92 const ChppWwanCellInfo *chppIn) {
93 // Local variable needed to avoid unaligned memory access.
94 ChppWwanCellInfo chppLocal;
95 memcpy(&chppLocal, chppIn, sizeof(ChppWwanCellInfo));
96 const ChppWwanCellInfo *chpp = &chppLocal;
97
98 EXPECT_EQ(chpp->timeStamp, chre->timeStamp);
99 EXPECT_EQ(chpp->cellInfoType, chre->cellInfoType);
100 EXPECT_EQ(chpp->timeStampType, chre->timeStampType);
101 EXPECT_EQ(chpp->registered, chre->registered);
102
103 switch (chpp->cellInfoType) {
104 case CHRE_WWAN_CELL_INFO_TYPE_LTE:
105 EXPECT_EQ(chpp->CellInfo.lte.cellIdentityLte.mcc,
106 chre->CellInfo.lte.cellIdentityLte.mcc);
107 EXPECT_EQ(chpp->CellInfo.lte.cellIdentityLte.mnc,
108 chre->CellInfo.lte.cellIdentityLte.mnc);
109 EXPECT_EQ(chpp->CellInfo.lte.cellIdentityLte.ci,
110 chre->CellInfo.lte.cellIdentityLte.ci);
111 EXPECT_EQ(chpp->CellInfo.lte.cellIdentityLte.pci,
112 chre->CellInfo.lte.cellIdentityLte.pci);
113 EXPECT_EQ(chpp->CellInfo.lte.cellIdentityLte.tac,
114 chre->CellInfo.lte.cellIdentityLte.tac);
115 EXPECT_EQ(chpp->CellInfo.lte.cellIdentityLte.earfcn,
116 chre->CellInfo.lte.cellIdentityLte.earfcn);
117
118 EXPECT_EQ(chpp->CellInfo.lte.signalStrengthLte.signalStrength,
119 chre->CellInfo.lte.signalStrengthLte.signalStrength);
120 EXPECT_EQ(chpp->CellInfo.lte.signalStrengthLte.rsrp,
121 chre->CellInfo.lte.signalStrengthLte.rsrp);
122 EXPECT_EQ(chpp->CellInfo.lte.signalStrengthLte.rsrq,
123 chre->CellInfo.lte.signalStrengthLte.rsrq);
124 EXPECT_EQ(chpp->CellInfo.lte.signalStrengthLte.rssnr,
125 chre->CellInfo.lte.signalStrengthLte.rssnr);
126 EXPECT_EQ(chpp->CellInfo.lte.signalStrengthLte.cqi,
127 chre->CellInfo.lte.signalStrengthLte.cqi);
128 EXPECT_EQ(chpp->CellInfo.lte.signalStrengthLte.timingAdvance,
129 chre->CellInfo.lte.signalStrengthLte.timingAdvance);
130 break;
131
132 case CHRE_WWAN_CELL_INFO_TYPE_WCDMA:
133 EXPECT_EQ(chpp->CellInfo.wcdma.cellIdentityWcdma.mcc,
134 chre->CellInfo.wcdma.cellIdentityWcdma.mcc);
135 EXPECT_EQ(chpp->CellInfo.wcdma.cellIdentityWcdma.mnc,
136 chre->CellInfo.wcdma.cellIdentityWcdma.mnc);
137 EXPECT_EQ(chpp->CellInfo.wcdma.cellIdentityWcdma.lac,
138 chre->CellInfo.wcdma.cellIdentityWcdma.lac);
139 EXPECT_EQ(chpp->CellInfo.wcdma.cellIdentityWcdma.cid,
140 chre->CellInfo.wcdma.cellIdentityWcdma.cid);
141 EXPECT_EQ(chpp->CellInfo.wcdma.cellIdentityWcdma.psc,
142 chre->CellInfo.wcdma.cellIdentityWcdma.psc);
143 EXPECT_EQ(chpp->CellInfo.wcdma.cellIdentityWcdma.uarfcn,
144 chre->CellInfo.wcdma.cellIdentityWcdma.uarfcn);
145
146 EXPECT_EQ(chpp->CellInfo.wcdma.signalStrengthWcdma.signalStrength,
147 chre->CellInfo.wcdma.signalStrengthWcdma.signalStrength);
148 EXPECT_EQ(chpp->CellInfo.wcdma.signalStrengthWcdma.bitErrorRate,
149 chre->CellInfo.wcdma.signalStrengthWcdma.bitErrorRate);
150 break;
151
152 default:
153 // Other types not supported yet
154 ASSERT_TRUE(false);
155 }
156 }
157
158 //! Test for correct handling of a malformed ChppWwanCellInfoResult (e.g. short
159 //! payload, invalid offset/length)
testMalformedCellInfoResultDecoding(struct ChppWwanCellInfoResult * chpp,size_t inputSize)160 void testMalformedCellInfoResultDecoding(struct ChppWwanCellInfoResult *chpp,
161 size_t inputSize) {
162 chreWwanCellInfoResult *chreMalformed;
163
164 inputSize--;
165 chreMalformed = chppWwanCellInfoResultToChre(chpp, inputSize);
166 EXPECT_EQ(chreMalformed, nullptr);
167 inputSize++;
168
169 chpp->cells.offset++;
170 chreMalformed = chppWwanCellInfoResultToChre(chpp, inputSize);
171 EXPECT_EQ(chreMalformed, nullptr);
172 chpp->cells.offset--;
173
174 chpp->cells.length++;
175 chreMalformed = chppWwanCellInfoResultToChre(chpp, inputSize);
176 EXPECT_EQ(chreMalformed, nullptr);
177 chpp->cells.length--;
178
179 chpp->cellInfoCount++;
180 chreMalformed = chppWwanCellInfoResultToChre(chpp, inputSize);
181 EXPECT_EQ(chreMalformed, nullptr);
182 chpp->cellInfoCount--;
183
184 chpp->cellInfoCount--;
185 chreMalformed = chppWwanCellInfoResultToChre(chpp, inputSize);
186 EXPECT_EQ(chreMalformed, nullptr);
187 chpp->cellInfoCount++;
188 }
189
TEST(WwanConvert,EncodeErrorCode)190 TEST(WwanConvert, EncodeErrorCode) {
191 const chreWwanCellInfoResult chreResult = {
192 .version = 200, // ignored
193 .errorCode = 2,
194 .cellInfoCount = 0,
195 .reserved = 3, // ignored
196 .cookie = (void *)-1, // ignored
197 .cells = nullptr,
198 };
199
200 ChppWwanCellInfoResultWithHeader *chppWithHeader = nullptr;
201 size_t outputSize = 999;
202 bool result =
203 chppWwanCellInfoResultFromChre(&chreResult, &chppWithHeader, &outputSize);
204 ASSERT_TRUE(result);
205 ASSERT_NE(chppWithHeader, nullptr);
206 EXPECT_EQ(outputSize, sizeof(ChppWwanCellInfoResultWithHeader));
207
208 ChppWwanCellInfoResult *chpp = &chppWithHeader->payload;
209 EXPECT_EQ(chpp->version, CHRE_WWAN_CELL_INFO_RESULT_VERSION);
210 EXPECT_EQ(chpp->errorCode, chreResult.errorCode);
211 EXPECT_EQ(chpp->cellInfoCount, chreResult.cellInfoCount);
212 EXPECT_EQ(chpp->reserved, 0);
213 EXPECT_EQ(chpp->cookie, 0u);
214 EXPECT_EQ(chpp->cells.offset, 0);
215 EXPECT_EQ(chpp->cells.length, 0);
216
217 chppFree(chppWithHeader);
218 }
219
TEST(WwanConvert,DecodeErrorCode)220 TEST(WwanConvert, DecodeErrorCode) {
221 const ChppWwanCellInfoResult chpp = {
222 .version = 200, // ignored
223 .errorCode = 2,
224 .cellInfoCount = 0,
225 .reserved = 3, // ignored
226 .cookie = 100, // ignored
227 .cells.offset = 0,
228 .cells.length = 0,
229 };
230
231 size_t outputSize = sizeof(struct ChppWwanCellInfoResult);
232 chreWwanCellInfoResult *chre =
233 chppWwanCellInfoResultToChre(&chpp, outputSize);
234 ASSERT_NE(chre, nullptr);
235
236 EXPECT_EQ(chre->version, CHRE_WWAN_CELL_INFO_RESULT_VERSION);
237 EXPECT_EQ(chre->errorCode, chpp.errorCode);
238 EXPECT_EQ(chre->cellInfoCount, chpp.cellInfoCount);
239 EXPECT_EQ(chre->reserved, 0);
240 EXPECT_EQ(chre->cookie, (void *)0);
241
242 // Handling of short payload
243 chreWwanCellInfoResult *chreShort =
244 chppWwanCellInfoResultToChre(&chpp, outputSize - 1);
245 ASSERT_EQ(chreShort, nullptr);
246
247 chppFree(chre);
248 }
249
TEST(WwanConvert,EncodeOneCell)250 TEST(WwanConvert, EncodeOneCell) {
251 ChppWwanCellInfoResultWithHeader *chppWithHeader = nullptr;
252 size_t outputSize = 999;
253 bool result = chppWwanCellInfoResultFromChre(&kChreResultOneCell,
254 &chppWithHeader, &outputSize);
255 ASSERT_TRUE(result);
256 ASSERT_NE(chppWithHeader, nullptr);
257 EXPECT_EQ(outputSize, sizeof(ChppWwanCellInfoResultWithHeader) +
258 sizeof(ChppWwanCellInfo));
259
260 ChppWwanCellInfoResult *chpp = &chppWithHeader->payload;
261 EXPECT_EQ(chpp->errorCode, kChreResultOneCell.errorCode);
262 EXPECT_EQ(chpp->cellInfoCount, kChreResultOneCell.cellInfoCount);
263 EXPECT_EQ(chpp->cells.offset, sizeof(ChppWwanCellInfoResult));
264 EXPECT_EQ(chpp->cells.length, sizeof(ChppWwanCellInfo));
265
266 ChppWwanCellInfo *chppCell =
267 (ChppWwanCellInfo *)((uint8_t *)chpp + chpp->cells.offset);
268 EXPECT_EQ(chppCell->reserved, 0);
269 compareCellInfo(&kChreCells[0], chppCell);
270
271 chppFree(chppWithHeader);
272 }
273
TEST(WwanConvert,EncodeDecodeOneCell)274 TEST(WwanConvert, EncodeDecodeOneCell) {
275 ChppWwanCellInfoResultWithHeader *chppWithHeader;
276 size_t outputSize;
277 bool result = chppWwanCellInfoResultFromChre(&kChreResultOneCell,
278 &chppWithHeader, &outputSize);
279 ASSERT_TRUE(result);
280 ASSERT_NE(chppWithHeader, nullptr);
281
282 ChppWwanCellInfoResult *chpp = &chppWithHeader->payload;
283 ChppWwanCellInfo *chppCell =
284 (ChppWwanCellInfo *)((uint8_t *)chpp + chpp->cells.offset);
285
286 chpp->version = 100; // ignored
287 chpp->reserved = 10; // ignored
288 chpp->cookie = -10; // ignored
289
290 size_t inputSize = outputSize - sizeof(struct ChppAppHeader);
291
292 chreWwanCellInfoResult *chre = chppWwanCellInfoResultToChre(chpp, inputSize);
293 ASSERT_NE(chre, nullptr);
294
295 EXPECT_EQ(chre->version, CHRE_WWAN_CELL_INFO_RESULT_VERSION);
296 EXPECT_EQ(chre->reserved, 0);
297 EXPECT_EQ(chre->cookie, (void *)0);
298
299 EXPECT_EQ(chre->errorCode, chpp->errorCode);
300 EXPECT_EQ(chre->errorCode, kChreResultOneCell.errorCode);
301 EXPECT_EQ(chre->cellInfoCount, chpp->cellInfoCount);
302 EXPECT_EQ(chre->cellInfoCount, kChreResultOneCell.cellInfoCount);
303
304 EXPECT_EQ(chre->cells[0].reserved, 0);
305 compareCellInfo(&kChreCells[0], chppCell);
306 compareCellInfo(&chre->cells[0], chppCell);
307
308 testMalformedCellInfoResultDecoding(chpp, inputSize);
309
310 chppFree(chppWithHeader);
311 chppFree(chre);
312 }
313
TEST(WwanConvert,EncodeTwoCells)314 TEST(WwanConvert, EncodeTwoCells) {
315 ChppWwanCellInfoResultWithHeader *chppWithHeader = nullptr;
316 size_t outputSize = 999;
317 bool result = chppWwanCellInfoResultFromChre(&kChreResultTwoCell,
318 &chppWithHeader, &outputSize);
319 ASSERT_TRUE(result);
320 ASSERT_NE(chppWithHeader, nullptr);
321 EXPECT_EQ(outputSize, sizeof(ChppWwanCellInfoResultWithHeader) +
322 2 * sizeof(ChppWwanCellInfo));
323
324 ChppWwanCellInfoResult *chpp = &chppWithHeader->payload;
325 EXPECT_EQ(chpp->errorCode, kChreResultTwoCell.errorCode);
326 EXPECT_EQ(chpp->cellInfoCount, kChreResultTwoCell.cellInfoCount);
327 EXPECT_EQ(chpp->cells.offset, sizeof(ChppWwanCellInfoResult));
328 EXPECT_EQ(chpp->cells.length, 2 * sizeof(ChppWwanCellInfo));
329
330 ChppWwanCellInfo *chppCells =
331 (ChppWwanCellInfo *)((uint8_t *)chpp + chpp->cells.offset);
332 EXPECT_EQ(chppCells[0].reserved, 0);
333 EXPECT_EQ(chppCells[1].reserved, 0);
334 compareCellInfo(&kChreCells[0], &chppCells[0]);
335 compareCellInfo(&kChreCells[1], &chppCells[1]);
336
337 // Ensure unused bytes in the union are zeroed out
338 uint8_t *pastEnd =
339 (uint8_t *)&chppCells[1].CellInfo.wcdma.signalStrengthWcdma.bitErrorRate +
340 sizeof(chppCells[1].CellInfo.wcdma.signalStrengthWcdma.bitErrorRate);
341 size_t sizePastEnd = sizeof(chreWwanCellInfo::chreWwanCellInfoPerRat) -
342 sizeof(chreWwanCellInfoWcdma);
343 uint8_t zeros[sizePastEnd];
344 memset(zeros, 0, sizePastEnd);
345 EXPECT_EQ(memcmp(pastEnd, zeros, sizeof(zeros)), 0);
346
347 chppFree(chppWithHeader);
348 }
349
TEST(WwanConvert,EncodeDecodeTwoCells)350 TEST(WwanConvert, EncodeDecodeTwoCells) {
351 ChppWwanCellInfoResultWithHeader *chppWithHeader;
352 size_t outputSize;
353 bool result = chppWwanCellInfoResultFromChre(&kChreResultTwoCell,
354 &chppWithHeader, &outputSize);
355 ASSERT_TRUE(result);
356 ASSERT_NE(chppWithHeader, nullptr);
357
358 ChppWwanCellInfoResult *chpp = &chppWithHeader->payload;
359 ChppWwanCellInfo *chppCells =
360 (ChppWwanCellInfo *)((uint8_t *)chpp + chpp->cells.offset);
361
362 chpp->version = 100; // ignored
363 chpp->reserved = 10; // ignored
364 chpp->cookie = -10; // ignored
365
366 size_t inputSize = outputSize - sizeof(struct ChppAppHeader);
367
368 chreWwanCellInfoResult *chre = chppWwanCellInfoResultToChre(chpp, inputSize);
369 ASSERT_NE(chre, nullptr);
370
371 EXPECT_EQ(chre->version, CHRE_WWAN_CELL_INFO_RESULT_VERSION);
372 EXPECT_EQ(chre->reserved, 0);
373 EXPECT_EQ(chre->cookie, (void *)0);
374
375 EXPECT_EQ(chre->errorCode, chpp->errorCode);
376 EXPECT_EQ(chpp->errorCode, kChreResultTwoCell.errorCode);
377 EXPECT_EQ(chre->cellInfoCount, chpp->cellInfoCount);
378 EXPECT_EQ(chpp->cellInfoCount, kChreResultTwoCell.cellInfoCount);
379
380 EXPECT_EQ(chre->cells[0].reserved, 0);
381 compareCellInfo(&kChreCells[0], &chppCells[0]);
382 compareCellInfo(&chre->cells[0], &chppCells[0]);
383
384 EXPECT_EQ(chre->cells[1].reserved, 0);
385 compareCellInfo(&kChreCells[1], &chppCells[1]);
386 compareCellInfo(&chre->cells[1], &chppCells[1]);
387
388 testMalformedCellInfoResultDecoding(chpp, inputSize);
389
390 chppFree(chppWithHeader);
391 chppFree(chre);
392 }
393
394 } // namespace
395