Implement currently tuned ID / channel indication.

Bug: 70939328
Test: it builds
Change-Id: I62011b70b3786b0d5e5ac24eb480a3c52a35f104
diff --git a/broadcastradio/2.0/default/TunerSession.cpp b/broadcastradio/2.0/default/TunerSession.cpp
index 36a22c5..244544a 100644
--- a/broadcastradio/2.0/default/TunerSession.cpp
+++ b/broadcastradio/2.0/default/TunerSession.cpp
@@ -56,6 +56,9 @@
 static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
     ProgramInfo info = {};
     info.selector = selector;
+    info.logicallyTunedTo = utils::make_identifier(
+        IdentifierType::AMFM_FREQUENCY, utils::getId(selector, IdentifierType::AMFM_FREQUENCY));
+    info.physicallyTunedTo = info.logicallyTunedTo;
     return info;
 }
 
diff --git a/broadcastradio/2.0/default/VirtualProgram.cpp b/broadcastradio/2.0/default/VirtualProgram.cpp
index 1acd4d3..acde704 100644
--- a/broadcastradio/2.0/default/VirtualProgram.cpp
+++ b/broadcastradio/2.0/default/VirtualProgram.cpp
@@ -13,11 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "BcRadioDef.VirtualProgram"
+
 #include "VirtualProgram.h"
 
 #include "resources.h"
 
+#include <android-base/logging.h>
 #include <broadcastradio-utils-2x/Utils.h>
+#include <log/log.h>
 
 namespace android {
 namespace hardware {
@@ -38,6 +42,39 @@
     auto pType = getType(selector.primaryId);
     auto isDigital = (pType != IdentifierType::AMFM_FREQUENCY && pType != IdentifierType::RDS_PI);
 
+    auto selectId = [&info](IdentifierType type) {
+        return utils::make_identifier(type, utils::getId(info.selector, type));
+    };
+
+    switch (pType) {
+        case IdentifierType::AMFM_FREQUENCY:
+            info.logicallyTunedTo = info.physicallyTunedTo =
+                selectId(IdentifierType::AMFM_FREQUENCY);
+            break;
+        case IdentifierType::RDS_PI:
+            info.logicallyTunedTo = selectId(IdentifierType::RDS_PI);
+            info.physicallyTunedTo = selectId(IdentifierType::AMFM_FREQUENCY);
+            break;
+        case IdentifierType::HD_STATION_ID_EXT:
+            info.logicallyTunedTo = selectId(IdentifierType::HD_STATION_ID_EXT);
+            info.physicallyTunedTo = selectId(IdentifierType::AMFM_FREQUENCY);
+            break;
+        case IdentifierType::DAB_SID_EXT:
+            info.logicallyTunedTo = selectId(IdentifierType::DAB_SID_EXT);
+            info.physicallyTunedTo = selectId(IdentifierType::DAB_ENSEMBLE);
+            break;
+        case IdentifierType::DRMO_SERVICE_ID:
+            info.logicallyTunedTo = selectId(IdentifierType::DRMO_SERVICE_ID);
+            info.physicallyTunedTo = selectId(IdentifierType::DRMO_FREQUENCY);
+            break;
+        case IdentifierType::SXM_SERVICE_ID:
+            info.logicallyTunedTo = selectId(IdentifierType::SXM_SERVICE_ID);
+            info.physicallyTunedTo = selectId(IdentifierType::SXM_CHANNEL);
+            break;
+        default:
+            LOG(FATAL) << "Unsupported program type: " << toString(pType);
+    }
+
     info.infoFlags |= ProgramInfoFlags::TUNED;
     info.infoFlags |= ProgramInfoFlags::STEREO;
     info.signalQuality = isDigital ? 100 : 80;
diff --git a/broadcastradio/2.0/types.hal b/broadcastradio/2.0/types.hal
index 42eab6a..b5264f4 100644
--- a/broadcastradio/2.0/types.hal
+++ b/broadcastradio/2.0/types.hal
@@ -185,6 +185,69 @@
      */
     ProgramSelector selector;
 
+    /**
+     * Identifier currently used for program selection.
+     *
+     * It allows to determine which technology is currently used for reception.
+     *
+     * Some program selectors contain tuning information for different radio
+     * technologies (i.e. FM RDS and DAB). For example, user may tune using
+     * a ProgramSelector with RDS_PI primary identifier, but the tuner hardware
+     * may choose to use DAB technology to make actual tuning. This identifier
+     * must reflect that.
+     *
+     * This field is optional, but must be set for currently tuned program.
+     * If it's not set, its value must be initialized to all-zeros.
+     *
+     * Only primary identifiers for a given radio technology are valid:
+     *  - AMFM_FREQUENCY for analog AM/FM;
+     *  - RDS_PI for FM RDS;
+     *  - HD_STATION_ID_EXT;
+     *  - DAB_SID_EXT;
+     *  - DRMO_SERVICE_ID;
+     *  - SXM_SERVICE_ID;
+     *  - VENDOR_*;
+     *  - more might come in next minor versions of this HAL.
+     */
+    ProgramIdentifier logicallyTunedTo;
+
+    /**
+     * Identifier currently used by hardware to physically tune to a channel.
+     *
+     * Some radio technologies broadcast the same program on multiple channels,
+     * i.e. with RDS AF the same program may be broadcasted on multiple
+     * alternative frequencies; the same DAB program may be broadcast on
+     * multiple ensembles. This identifier points to the channel to which the
+     * radio hardware is physically tuned to.
+     *
+     * This field is optional, but must be set for currently tuned program.
+     * If it's not set, its type field must be initialized to
+     * IdentifierType::INVALID.
+     *
+     * Only physical identifiers are valid:
+     *  - AMFM_FREQUENCY;
+     *  - DAB_ENSEMBLE;
+     *  - DRMO_FREQUENCY;
+     *  - SXM_CHANNEL;
+     *  - VENDOR_*;
+     *  - more might come in next minor versions of this HAL.
+     */
+    ProgramIdentifier physicallyTunedTo;
+
+    /**
+     * Primary identifiers of related contents.
+     *
+     * Some radio technologies provide pointers to other programs that carry
+     * related content (i.e. DAB soft-links). This field is a list of pointers
+     * to other programs on the program list.
+     *
+     * Please note, that these identifiers does not have to exist on the program
+     * list - i.e. DAB tuner may provide information on FM RDS alternatives
+     * despite not supporting FM RDS. If the system has multiple tuners, another
+     * one may have it on its list.
+     */
+    vec<ProgramIdentifier> relatedContent;
+
     bitfield<ProgramInfoFlags> infoFlags;
 
     /**
@@ -275,6 +338,8 @@
     /** See VENDOR_START */
     VENDOR_END = 1999,
 
+    INVALID = 0,
+
     /**
      * Primary identifier for analogue (without RDS) AM/FM stations:
      * frequency in kHz.
@@ -285,7 +350,7 @@
      *  - 1.71MHz - 30MHz: AM SW;
      *  - >60MHz: FM.
      */
-    AMFM_FREQUENCY = 1,
+    AMFM_FREQUENCY,
 
     /**
      * 16bit primary identifier for FM RDS station.
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 4ab6cbe..cbe6288 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -520,6 +520,9 @@
     EXPECT_TRUE(stopResult.isOk());
 }
 
+// TODO(b/70939328): test ProgramInfo's currentlyTunedId and
+// currentlyTunedChannel once the program list is implemented.
+
 }  // namespace vts
 }  // namespace V2_0
 }  // namespace broadcastradio
diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp
index 10a155b..e0337b4 100644
--- a/broadcastradio/common/utils2x/Utils.cpp
+++ b/broadcastradio/common/utils2x/Utils.cpp
@@ -206,6 +206,9 @@
     };
 
     switch (getType(id)) {
+        case IdentifierType::INVALID:
+            expect(false, "IdentifierType::INVALID");
+            break;
         case IdentifierType::AMFM_FREQUENCY:
         case IdentifierType::DAB_FREQUENCY:
         case IdentifierType::DRMO_FREQUENCY: