Support writing FEC.

After hash tree is written, we re-read the partition to encode FEC,
this cannot be done incrementally for each Update() like the hash
tree, because the data needed to encode each rs block are spreaded
across entire partition, and we can not afford to use that much
memory.

For each round, we encode block_size number of rs blocks, which will
produce block_size * fec_roots bytes of FEC data, this will allow us
to read one block at a time instead of one byte.

Bug: 28171891
Test: update_engine_unittests
Test: brillo_update_payload generate
Test: brillo_update_payload verify

Change-Id: I35ba7e0647b9ee5a97b972dc480deef60d813676
diff --git a/payload_consumer/verity_writer_android.h b/payload_consumer/verity_writer_android.h
index c26663b..05a5856 100644
--- a/payload_consumer/verity_writer_android.h
+++ b/payload_consumer/verity_writer_android.h
@@ -18,6 +18,7 @@
 #define UPDATE_ENGINE_PAYLOAD_CONSUMER_VERITY_WRITER_ANDROID_H_
 
 #include <memory>
+#include <string>
 
 #include <verity/hash_tree_builder.h>
 
@@ -33,6 +34,21 @@
   bool Init(const InstallPlan::Partition& partition) override;
   bool Update(uint64_t offset, const uint8_t* buffer, size_t size) override;
 
+  // Read [data_offset : data_offset + data_size) from |path| and encode FEC
+  // data, if |verify_mode|, then compare the encoded FEC with the one in
+  // |path|, otherwise write the encoded FEC to |path|. We can't encode as we go
+  // in each Update() like hash tree, because for every rs block, its data are
+  // spreaded across entire |data_size|, unless we can cache all data in
+  // memory, we have to re-read them from disk.
+  static bool EncodeFEC(const std::string& path,
+                        uint64_t data_offset,
+                        uint64_t data_size,
+                        uint64_t fec_offset,
+                        uint64_t fec_size,
+                        uint32_t fec_roots,
+                        uint32_t block_size,
+                        bool verify_mode);
+
  private:
   const InstallPlan::Partition* partition_ = nullptr;