Add UnownedCacheFileDescriptor

Since we switched to raw pointers in a subset of fs verfication
functions, EncodeFEC no longer have a shared ptr, and can no longer use
CacheFileDescriptor. Add a variant of CacheFileDescriptor that works
with raw pointer.

Test: th
Bug: 216391325
Change-Id: Id71880a4f8f97e4549dcc96d53e9af00ae45168c
diff --git a/payload_consumer/cached_file_descriptor.cc b/payload_consumer/cached_file_descriptor.cc
index 7f2515e..aa0dbcd 100644
--- a/payload_consumer/cached_file_descriptor.cc
+++ b/payload_consumer/cached_file_descriptor.cc
@@ -26,7 +26,7 @@
 
 namespace chromeos_update_engine {
 
-off64_t CachedFileDescriptor::Seek(off64_t offset, int whence) {
+off64_t CachedFileDescriptorBase::Seek(off64_t offset, int whence) {
   // Only support SEEK_SET and SEEK_CUR. I think these two would be enough. If
   // we want to support SEEK_END then we have to figure out the size of the
   // underlying file descriptor each time and it may not be a very good idea.
@@ -40,7 +40,7 @@
       return -1;
     }
     // Then we have to seek there.
-    if (fd_->Seek(next_offset, SEEK_SET) < 0) {
+    if (GetFd()->Seek(next_offset, SEEK_SET) < 0) {
       return -1;
     }
     offset_ = next_offset;
@@ -48,7 +48,7 @@
   return offset_;
 }
 
-ssize_t CachedFileDescriptor::Write(const void* buf, size_t count) {
+ssize_t CachedFileDescriptorBase::Write(const void* buf, size_t count) {
   auto bytes = static_cast<const uint8_t*>(buf);
   size_t total_bytes_wrote = 0;
   while (total_bytes_wrote < count) {
@@ -72,19 +72,20 @@
   return total_bytes_wrote;
 }
 
-bool CachedFileDescriptor::Flush() {
-  return FlushCache() && fd_->Flush();
+bool CachedFileDescriptorBase::Flush() {
+  return FlushCache() && GetFd()->Flush();
 }
 
-bool CachedFileDescriptor::Close() {
+bool CachedFileDescriptorBase::Close() {
   offset_ = 0;
-  return FlushCache() && fd_->Close();
+  return FlushCache() && GetFd()->Close();
 }
 
-bool CachedFileDescriptor::FlushCache() {
+bool CachedFileDescriptorBase::FlushCache() {
   size_t begin = 0;
   while (begin < bytes_cached_) {
-    auto bytes_wrote = fd_->Write(cache_.data() + begin, bytes_cached_ - begin);
+    auto bytes_wrote =
+        GetFd()->Write(cache_.data() + begin, bytes_cached_ - begin);
     if (bytes_wrote < 0) {
       PLOG(ERROR) << "Failed to flush cached data!";
       return false;
diff --git a/payload_consumer/cached_file_descriptor.h b/payload_consumer/cached_file_descriptor.h
index ada112b..1193455 100644
--- a/payload_consumer/cached_file_descriptor.h
+++ b/payload_consumer/cached_file_descriptor.h
@@ -29,45 +29,66 @@
 
 namespace chromeos_update_engine {
 
-class CachedFileDescriptor : public FileDescriptor {
+class CachedFileDescriptorBase : public FileDescriptor {
  public:
-  CachedFileDescriptor(FileDescriptorPtr fd, size_t cache_size)
-      : fd_(fd), cache_(cache_size) {}
-  ~CachedFileDescriptor() override = default;
+  CachedFileDescriptorBase(size_t cache_size) : cache_(cache_size) {}
+  ~CachedFileDescriptorBase() override = default;
 
   bool Open(const char* path, int flags, mode_t mode) override {
-    return fd_->Open(path, flags, mode);
+    return GetFd()->Open(path, flags, mode);
   }
   bool Open(const char* path, int flags) override {
-    return fd_->Open(path, flags);
+    return GetFd()->Open(path, flags);
   }
   ssize_t Read(void* buf, size_t count) override {
-    return fd_->Read(buf, count);
+    return GetFd()->Read(buf, count);
   }
   ssize_t Write(const void* buf, size_t count) override;
   off64_t Seek(off64_t offset, int whence) override;
-  uint64_t BlockDevSize() override { return fd_->BlockDevSize(); }
+  uint64_t BlockDevSize() override { return GetFd()->BlockDevSize(); }
   bool BlkIoctl(int request,
                 uint64_t start,
                 uint64_t length,
                 int* result) override {
-    return fd_->BlkIoctl(request, start, length, result);
+    return GetFd()->BlkIoctl(request, start, length, result);
   }
   bool Flush() override;
   bool Close() override;
-  bool IsSettingErrno() override { return fd_->IsSettingErrno(); }
-  bool IsOpen() override { return fd_->IsOpen(); }
+  bool IsSettingErrno() override { return GetFd()->IsSettingErrno(); }
+  bool IsOpen() override { return GetFd()->IsOpen(); }
+
+ protected:
+  virtual FileDescriptor* GetFd() = 0;
 
  private:
   // Internal flush without the need to call |fd_->Flush()|.
   bool FlushCache();
 
-  FileDescriptorPtr fd_;
   brillo::Blob cache_;
   size_t bytes_cached_{0};
   off64_t offset_{0};
 
-  DISALLOW_COPY_AND_ASSIGN(CachedFileDescriptor);
+  DISALLOW_COPY_AND_ASSIGN(CachedFileDescriptorBase);
+};
+
+class CachedFileDescriptor final : public CachedFileDescriptorBase {
+ public:
+  CachedFileDescriptor(FileDescriptorPtr fd, size_t cache_size)
+      : CachedFileDescriptorBase(cache_size), fd_(fd) {}
+
+ protected:
+  virtual FileDescriptor* GetFd() { return fd_.get(); }
+  FileDescriptorPtr fd_;
+};
+
+class UnownedCachedFileDescriptor final : public CachedFileDescriptorBase {
+ public:
+  UnownedCachedFileDescriptor(FileDescriptor* fd, size_t cache_size)
+      : CachedFileDescriptorBase(cache_size), fd_(fd) {}
+
+ protected:
+  virtual FileDescriptor* GetFd() { return fd_; }
+  FileDescriptor* fd_;
 };
 
 }  // namespace chromeos_update_engine
diff --git a/payload_consumer/partition_writer.cc b/payload_consumer/partition_writer.cc
index 4625a7a..b94f8c7 100644
--- a/payload_consumer/partition_writer.cc
+++ b/payload_consumer/partition_writer.cc
@@ -86,8 +86,6 @@
 
 }  // namespace
 
-using google::protobuf::RepeatedPtrField;
-
 // Opens path for read/write. On success returns an open FileDescriptor
 // and sets *err to 0. On failure, sets *err to errno and returns nullptr.
 FileDescriptorPtr OpenFile(const char* path,
diff --git a/payload_consumer/verity_writer_android.cc b/payload_consumer/verity_writer_android.cc
index b233b58..b669b4d 100644
--- a/payload_consumer/verity_writer_android.cc
+++ b/payload_consumer/verity_writer_android.cc
@@ -161,6 +161,11 @@
   std::unique_ptr<void, decltype(&free_rs_char)> rs_char(
       init_rs_char(FEC_PARAMS(fec_roots)), &free_rs_char);
   TEST_AND_RETURN_FALSE(rs_char != nullptr);
+  // Cache at most 1MB of fec data, in VABC, we need to re-open fd if we
+  // perform a read() operation after write(). So reduce the number of writes
+  // can save unnecessary re-opens.
+  UnownedCachedFileDescriptor cache_fd(write_fd, 1 * (1 << 20));
+  write_fd = &cache_fd;
 
   for (size_t i = 0; i < rounds; i++) {
     // Encodes |block_size| number of rs blocks each round so that we can read