Copy a version of download action for ChromeOS
DownloadAction contains many cros specific stuff, such as p2p, system
state. Many of these cros bits are used in a fragile way in aosp. It's
better if we maintain two independent download actions.
Test: treehugger
Bug: 175042161
Change-Id: Iaaed269b3886a068bfcb4bcac12aca99b9cf6970
diff --git a/cros/download_action_chromeos.h b/cros/download_action_chromeos.h
new file mode 100644
index 0000000..068946a
--- /dev/null
+++ b/cros/download_action_chromeos.h
@@ -0,0 +1,174 @@
+//
+// Copyright (C) 2020 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.
+//
+
+#ifndef UPDATE_ENGINE_COMMON_DOWNLOAD_ACTION_CHROMEOS_H_
+#define UPDATE_ENGINE_COMMON_DOWNLOAD_ACTION_CHROMEOS_H_
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <memory>
+#include <string>
+
+#include "update_engine/common/action.h"
+#include "update_engine/common/boot_control_interface.h"
+#include "update_engine/common/download_action.h"
+#include "update_engine/common/http_fetcher.h"
+#include "update_engine/common/multi_range_http_fetcher.h"
+#include "update_engine/payload_consumer/delta_performer.h"
+#include "update_engine/payload_consumer/install_plan.h"
+
+// The Download Action downloads a specified url to disk. The url should point
+// to an update in a delta payload format. The payload will be piped into a
+// DeltaPerformer that will apply the delta to the disk.
+
+namespace chromeos_update_engine {
+
+class PrefsInterface;
+
+class DownloadActionChromeos : public InstallPlanAction,
+ public HttpFetcherDelegate {
+ public:
+ static std::string StaticType() { return "DownloadActionChromeos"; }
+
+ // Takes ownership of the passed in HttpFetcher. Useful for testing.
+ // A good calling pattern is:
+ // DownloadActionChromeos(prefs, boot_contol, hardware, system_state,
+ // new WhateverHttpFetcher, false);
+ DownloadActionChromeos(PrefsInterface* prefs,
+ BootControlInterface* boot_control,
+ HardwareInterface* hardware,
+ HttpFetcher* http_fetcher,
+ bool interactive);
+ ~DownloadActionChromeos() override;
+
+ // InstallPlanAction overrides.
+ void PerformAction() override;
+ void SuspendAction() override;
+ void ResumeAction() override;
+ void TerminateProcessing() override;
+ std::string Type() const override { return StaticType(); }
+
+ // Testing
+ void SetTestFileWriter(FileWriter* writer) { writer_ = writer; }
+
+ int GetHTTPResponseCode() { return http_fetcher_->http_response_code(); }
+
+ // HttpFetcherDelegate methods (see http_fetcher.h)
+ bool ReceivedBytes(HttpFetcher* fetcher,
+ const void* bytes,
+ size_t length) override;
+ void SeekToOffset(off_t offset) override;
+ void TransferComplete(HttpFetcher* fetcher, bool successful) override;
+ void TransferTerminated(HttpFetcher* fetcher) override;
+
+ DownloadActionDelegate* delegate() const { return delegate_; }
+ void set_delegate(DownloadActionDelegate* delegate) { delegate_ = delegate; }
+
+ void set_base_offset(int64_t base_offset) { base_offset_ = base_offset; }
+
+ HttpFetcher* http_fetcher() { return http_fetcher_.get(); }
+
+ // Returns the p2p file id for the file being written or the empty
+ // string if we're not writing to a p2p file.
+ std::string p2p_file_id() { return p2p_file_id_; }
+
+ private:
+ // Closes the file descriptor for the p2p file being written and
+ // clears |p2p_file_id_| to indicate that we're no longer sharing
+ // the file. If |delete_p2p_file| is True, also deletes the file.
+ // If there is no p2p file descriptor, this method does nothing.
+ void CloseP2PSharingFd(bool delete_p2p_file);
+
+ // Starts sharing the p2p file. Must be called before
+ // WriteToP2PFile(). Returns True if this worked.
+ bool SetupP2PSharingFd();
+
+ // Writes |length| bytes of payload from |data| into |file_offset|
+ // of the p2p file. Also does validation checks; for example ensures we
+ // don't end up with a file with holes in it.
+ //
+ // This method does nothing if SetupP2PSharingFd() hasn't been
+ // called or if CloseP2PSharingFd() has been called.
+ void WriteToP2PFile(const void* data, size_t length, off_t file_offset);
+
+ // Attempt to load cached manifest data from prefs
+ // return true on success, false otherwise.
+ bool LoadCachedManifest(int64_t manifest_size);
+
+ // Start downloading the current payload using delta_performer.
+ void StartDownloading();
+
+ // Pointer to the current payload in install_plan_.payloads.
+ InstallPlan::Payload* payload_{nullptr};
+
+ PrefsInterface* prefs_;
+ BootControlInterface* boot_control_;
+ HardwareInterface* hardware_;
+
+ // Pointer to the MultiRangeHttpFetcher that does the http work.
+ std::unique_ptr<MultiRangeHttpFetcher> http_fetcher_;
+
+ // If |true|, the update is user initiated (vs. periodic update checks). Hence
+ // the |delta_performer_| can decide not to use O_DSYNC flag for faster
+ // update.
+ bool interactive_;
+
+ // The FileWriter that downloaded data should be written to. It will
+ // either point to *decompressing_file_writer_ or *delta_performer_.
+ FileWriter* writer_;
+
+ std::unique_ptr<DeltaPerformer> delta_performer_;
+
+ // Used by TransferTerminated to figure if this action terminated itself or
+ // was terminated by the action processor.
+ ErrorCode code_;
+
+ // For reporting status to outsiders
+ DownloadActionDelegate* delegate_;
+ uint64_t bytes_received_{0}; // per file/range
+ uint64_t bytes_received_previous_payloads_{0};
+ uint64_t bytes_total_{0};
+ bool download_active_{false};
+
+ // The file-id for the file we're sharing or the empty string
+ // if we're not using p2p to share.
+ std::string p2p_file_id_;
+
+ // The file descriptor for the p2p file used for caching the payload or -1
+ // if we're not using p2p to share.
+ int p2p_sharing_fd_;
+
+ // Set to |false| if p2p file is not visible.
+ bool p2p_visible_;
+
+ // Loaded from prefs before downloading any payload.
+ size_t resume_payload_index_{0};
+
+ // Offset of the payload in the download URL, used by UpdateAttempterAndroid.
+ int64_t base_offset_{0};
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadActionChromeos);
+};
+
+// We want to be sure that we're compiled with large file support on linux,
+// just in case we find ourselves downloading large images.
+static_assert(8 == sizeof(off_t), "off_t not 64 bit");
+
+} // namespace chromeos_update_engine
+
+#endif // UPDATE_ENGINE_COMMON_DOWNLOAD_ACTION_CHROMEOS_H_