SampleTunerTIS HAL Process TS for SectionEvents

Currently, the HAL simply sends raw TS data when
SectionEvents are created from a TS file. This CL
will have the HAL process the TS packets and construct
sections to be sent to the SectionFilter. A slight-modified
TS protocol is used that mirrors the current implementation
for PES filters.

Bug: 237323181
Test: Manually using cuttlefish and the SampleTunerTvInput.
SectionEvents should be received without the 4-byte
TsHeader or any trailing data.

Change-Id: Ief6b9beb8f48bda1b83a0bffb83698ca431b7b12
diff --git a/tv/tuner/aidl/default/Filter.cpp b/tv/tuner/aidl/default/Filter.cpp
index 1d56303..82e11cf 100644
--- a/tv/tuner/aidl/default/Filter.cpp
+++ b/tv/tuner/aidl/default/Filter.cpp
@@ -961,24 +961,64 @@
     return ::ndk::ScopedAStatus::ok();
 }
 
+// Read PSI (Program Specific Information) Sections from TransportStreams
+// as defined in ISO/IEC 13818-1 Section 2.4.4
 bool Filter::writeSectionsAndCreateEvent(vector<int8_t>& data) {
     // TODO check how many sections has been read
     ALOGD("[Filter] section handler");
-    if (!writeDataToFilterMQ(data)) {
-        return false;
-    }
-    DemuxFilterSectionEvent secEvent;
-    secEvent = {
-            // temp dump meta data
-            .tableId = 0,
-            .version = 1,
-            .sectionNum = 1,
-            .dataLength = static_cast<int32_t>(data.size()),
-    };
 
-    {
-        std::lock_guard<std::mutex> lock(mFilterEventsLock);
-        mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::section>(secEvent));
+    // Transport Stream Packets are 188 bytes long, as defined in the
+    // Introduction of ISO/IEC 13818-1
+    for (int i = 0; i < data.size(); i += 188) {
+        if (mSectionSizeLeft == 0) {
+            // Location for sectionSize as defined by Section 2.4.4
+            // Note that the first 4 bytes skipped are the TsHeader
+            mSectionSizeLeft = ((data[i + 5] & 0x0f) << 8) | (data[i + 6] & 0xff);
+            mSectionSizeLeft += 3;
+            if (DEBUG_FILTER) {
+                ALOGD("[Filter] section data length %d", mSectionSizeLeft);
+            }
+        }
+
+        // 184 bytes per packet is derived by subtracting the 4 byte length of
+        // the TsHeader from its 188 byte packet size
+        uint32_t endPoint = min(184u, mSectionSizeLeft);
+        // append data and check size
+        vector<int8_t>::const_iterator first = data.begin() + i + 4;
+        vector<int8_t>::const_iterator last = data.begin() + i + 4 + endPoint;
+        mSectionOutput.insert(mSectionOutput.end(), first, last);
+        // size does not match then continue
+        mSectionSizeLeft -= endPoint;
+        if (DEBUG_FILTER) {
+            ALOGD("[Filter] section data left %d", mSectionSizeLeft);
+        }
+        if (mSectionSizeLeft > 0) {
+            continue;
+        }
+
+        if (!writeDataToFilterMQ(mSectionOutput)) {
+            mSectionOutput.clear();
+            return false;
+        }
+
+        DemuxFilterSectionEvent secEvent;
+        secEvent = {
+                // temp dump meta data
+                .tableId = 0,
+                .version = 1,
+                .sectionNum = 1,
+                .dataLength = static_cast<int32_t>(mSectionOutput.size()),
+        };
+        if (DEBUG_FILTER) {
+            ALOGD("[Filter] assembled section data length %lld", secEvent.dataLength);
+        }
+
+        {
+            std::lock_guard<std::mutex> lock(mFilterEventsLock);
+            mFilterEvents.push_back(
+                    DemuxFilterEvent::make<DemuxFilterEvent::Tag::section>(secEvent));
+        }
+        mSectionOutput.clear();
     }
 
     return true;
diff --git a/tv/tuner/aidl/default/Filter.h b/tv/tuner/aidl/default/Filter.h
index c559862..06c2c26 100644
--- a/tv/tuner/aidl/default/Filter.h
+++ b/tv/tuner/aidl/default/Filter.h
@@ -258,6 +258,10 @@
     std::mutex mFilterOutputLock;
     std::mutex mRecordFilterOutputLock;
 
+    // handle single Section filter
+    uint32_t mSectionSizeLeft = 0;
+    vector<int8_t> mSectionOutput;
+
     // temp handle single PES filter
     // TODO handle mulptiple Pes filters
     int mPesSizeLeft = 0;