Implement program list fetching.

Bug: 69860743
Test: VTS
Change-Id: I04eb43c1e0e1bb7bad86e123594a473454eed983
diff --git a/broadcastradio/common/tests/Android.bp b/broadcastradio/common/tests/Android.bp
index bbad527..512c02e 100644
--- a/broadcastradio/common/tests/Android.bp
+++ b/broadcastradio/common/tests/Android.bp
@@ -15,20 +15,6 @@
 //
 
 cc_test {
-    name: "android.hardware.broadcastradio@common-utils-tests",
-    vendor: true,
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
-    srcs: [
-        "WorkerThread_test.cpp",
-    ],
-    static_libs: ["android.hardware.broadcastradio@common-utils-lib"],
-}
-
-cc_test {
     name: "android.hardware.broadcastradio@common-utils-xx-tests",
     vendor: true,
     cflags: [
@@ -48,3 +34,36 @@
         "android.hardware.broadcastradio@2.0",
     ],
 }
+
+cc_test {
+    name: "android.hardware.broadcastradio@common-utils-2x-tests",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "IdentifierIterator_test.cpp",
+    ],
+    static_libs: [
+        "android.hardware.broadcastradio@common-utils-2x-lib",
+    ],
+    shared_libs: [
+        "android.hardware.broadcastradio@2.0",
+    ],
+}
+
+cc_test {
+    name: "android.hardware.broadcastradio@common-utils-tests",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "WorkerThread_test.cpp",
+    ],
+    static_libs: ["android.hardware.broadcastradio@common-utils-lib"],
+}
diff --git a/broadcastradio/common/tests/IdentifierIterator_test.cpp b/broadcastradio/common/tests/IdentifierIterator_test.cpp
new file mode 100644
index 0000000..5bf222b
--- /dev/null
+++ b/broadcastradio/common/tests/IdentifierIterator_test.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <broadcastradio-utils-2x/Utils.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+namespace V2_0 = android::hardware::broadcastradio::V2_0;
+namespace utils = android::hardware::broadcastradio::utils;
+
+using V2_0::IdentifierType;
+using V2_0::ProgramSelector;
+
+TEST(IdentifierIteratorTest, singleSecondary) {
+    // clang-format off
+    V2_0::ProgramSelector sel {
+        utils::make_identifier(IdentifierType::RDS_PI, 0xBEEF),
+        {utils::make_identifier(IdentifierType::AMFM_FREQUENCY, 100100)}
+    };
+    // clang-format on
+
+    auto it = utils::begin(sel);
+    auto end = utils::end(sel);
+
+    ASSERT_NE(end, it);
+    EXPECT_EQ(sel.primaryId, *it);
+    ASSERT_NE(end, ++it);
+    EXPECT_EQ(sel.secondaryIds[0], *it);
+    ASSERT_EQ(end, ++it);
+}
+
+TEST(IdentifierIteratorTest, empty) {
+    V2_0::ProgramSelector sel{};
+
+    auto it = utils::begin(sel);
+    auto end = utils::end(sel);
+
+    ASSERT_NE(end, it++);  // primary id is always present
+    ASSERT_EQ(end, it);
+}
+
+TEST(IdentifierIteratorTest, twoSelectors) {
+    V2_0::ProgramSelector sel1{};
+    V2_0::ProgramSelector sel2{};
+
+    auto it1 = utils::begin(sel1);
+    auto it2 = utils::begin(sel2);
+
+    EXPECT_NE(it1, it2);
+}
+
+TEST(IdentifierIteratorTest, increments) {
+    V2_0::ProgramSelector sel{{}, {{}, {}}};
+
+    auto it = utils::begin(sel);
+    auto end = utils::end(sel);
+    auto pre = it;
+    auto post = it;
+
+    EXPECT_NE(++pre, post++);
+    EXPECT_EQ(pre, post);
+    EXPECT_EQ(pre, it + 1);
+    ASSERT_NE(end, pre);
+}
+
+TEST(IdentifierIteratorTest, findType) {
+    using namespace std::placeholders;
+
+    uint64_t rds_pi1 = 0xDEAD;
+    uint64_t rds_pi2 = 0xBEEF;
+    uint64_t freq1 = 100100;
+    uint64_t freq2 = 107900;
+
+    // clang-format off
+    V2_0::ProgramSelector sel {
+        utils::make_identifier(IdentifierType::RDS_PI, rds_pi1),
+        {
+            utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq1),
+            utils::make_identifier(IdentifierType::RDS_PI, rds_pi2),
+            utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq2),
+        }
+    };
+    // clang-format on
+
+    auto typeEquals = [](const V2_0::ProgramIdentifier& id, V2_0::IdentifierType type) {
+        return utils::getType(id) == type;
+    };
+    auto isRdsPi = std::bind(typeEquals, _1, IdentifierType::RDS_PI);
+    auto isFreq = std::bind(typeEquals, _1, IdentifierType::AMFM_FREQUENCY);
+
+    auto end = utils::end(sel);
+    auto it = std::find_if(utils::begin(sel), end, isRdsPi);
+    ASSERT_NE(end, it);
+    EXPECT_EQ(rds_pi1, it->value);
+
+    it = std::find_if(it + 1, end, isRdsPi);
+    ASSERT_NE(end, it);
+    EXPECT_EQ(rds_pi2, it->value);
+
+    it = std::find_if(utils::begin(sel), end, isFreq);
+    ASSERT_NE(end, it);
+    EXPECT_EQ(freq1, it->value);
+
+    it = std::find_if(++it, end, isFreq);
+    ASSERT_NE(end, it);
+    EXPECT_EQ(freq2, it->value);
+}
+
+}  // anonymous namespace