从上一篇我们已经知道具体的升级写入校验流程都是由InstallPlanAction,DownloadAction,FilesystemVerifierAction,PostinstallRunnerAction,这四个Action完成的,本篇主要讲解这四个的具体流程,我准备这些文件依然按照.h 和.cc进行分析
一、InstallPlanAction
二、DownloadAction
三、FilesystemVerifierAction
四、PostinstallRunnerAction
一、InstallPlanAction
1system/update_engine/payload_consumer/install_plan.h
2
3// Basic action that only receives and sends Install Plans.
4// Can be used to construct an Install Plan to send to any other Action that
5// accept an InstallPlan.
6// 基础的action,接收和发送install plans ,通过查询代码可以发现,installplanAcion没有单独的代码
7// 实现,是其他action的父类,只用于发送和接收install_plan_
8class InstallPlanAction : public Action<InstallPlanAction> {
9 public:
10 InstallPlanAction() {}
11 explicit InstallPlanAction(const InstallPlan& install_plan):
12 install_plan_(install_plan) {}
13 //这算是具体执行Acion的方法,将install_plan_设置为install_plan_
14 void PerformAction() override {
15 if (HasOutputPipe()) {
16 SetOutputObject(install_plan_);
17 }
18 //调用processor执行action完成的处理
19 processor_->ActionComplete(this, ErrorCode::kSuccess);
20 }
21 //定义方法可以获取install_plan_
22 InstallPlan* install_plan() { return &install_plan_; }
23 //定义方法可以获取当前的Acion类型
24 static std::string StaticType() { return "InstallPlanAction"; }
25 std::string Type() const override { return StaticType(); }
26 //定义了管道机制中的输出和输入
27 typedef ActionTraits<InstallPlanAction>::InputObjectType InputObjectType;
28 typedef ActionTraits<InstallPlanAction>::OutputObjectType OutputObjectType;
29
30 private:
31 InstallPlan install_plan_;
32
33 DISALLOW_COPY_AND_ASSIGN(InstallPlanAction);
34};
我觉得这个installplanAcion相当于我们运了一车猪做火腿肠,生产线已经整好了,但是总的有个地方放这个生产线,所以整了个厂房放进去,切也好 剁也好,都放着里边,具体的代码也比较简单 只是把install_plan_作为SetOutputObject,也就是downloadAcion的输入,install_plan_就相当于那一车猪
二、DownloadAction
我们先分析下system/update_engine/payload_consumer/download_action.h ,确认下大概的方法和定义参数
2.1 download_action.h
1// The Download Action downloads a specified url to disk. The url should point
2// to an update in a delta payload format. The payload will be piped into a
3// DeltaPerformer that will apply the delta to the disk.
4// downloadAcion会下载一个特殊的url到磁盘,这个url会指向到一个delta payload格式的升级
5// 将payload使用管道传输给DeltaPerformer,通过DeltaPerformer将delta写入到磁盘
6// 所以downloadAcion其实是具体写入到分区升级的业务
7namespace chromeos_update_engine {
8
9//这三个方法是Delegate委托 最后调用的是updateAttempterAndroid中的对应方法
10class DownloadActionDelegate {
11 public:
12 virtual ~DownloadActionDelegate() = default;
13
14 // Called periodically after bytes are received. This method will be invoked
15 // only if the DownloadAction is running. |bytes_progressed| is the number of
16 // bytes downloaded since the last call of this method, |bytes_received|
17 // the number of bytes downloaded thus far and |total| is the number of bytes
18 // expected.
19 virtual void BytesReceived(uint64_t bytes_progressed,
20 uint64_t bytes_received,
21 uint64_t total) = 0;
22
23 // Returns whether the download should be canceled, in which case the
24 // |cancel_reason| error should be set to the reason why the download was
25 // canceled.
26 virtual bool ShouldCancel(ErrorCode* cancel_reason) = 0;
27
28 // Called once the complete payload has been downloaded. Note that any errors
29 // while applying or downloading the partial payload will result in this
30 // method not being called.
31 virtual void DownloadComplete() = 0;
32};
33
34class PrefsInterface;
35
36class DownloadAction : public InstallPlanAction,
37 public HttpFetcherDelegate {
38 public:
39 // Debugging/logging 打印当前的Action
40 static std::string StaticType() { return "DownloadAction"; }
41
42 // Takes ownership of the passed in HttpFetcher. Useful for testing.
43 // A good calling pattern is:
44 // DownloadAction(prefs, boot_contol, hardware, system_state,
45 // new WhateverHttpFetcher, false);
46 DownloadAction(PrefsInterface* prefs,
47 BootControlInterface* boot_control,
48 HardwareInterface* hardware,
49 SystemState* system_state, //传入的值为空
50 HttpFetcher* http_fetcher,
51 bool is_interactive);//传入的值为true
52 ~DownloadAction() override;
53
54 // InstallPlanAction overrides.
55 void PerformAction() override; //具体处理action
56 void SuspendAction() override; //暂停
57 void ResumeAction() override; //恢复
58 void TerminateProcessing() override; //停止
59 std::string Type() const override { return StaticType(); }
60
61 // Testing
62 void SetTestFileWriter(FileWriter* writer) {
63 writer_ = writer;
64 }
65 //获取HTTP相应的code
66 int GetHTTPResponseCode() { return http_fetcher_->http_response_code(); }
67
68 // HttpFetcherDelegate methods (see http_fetcher.h) 重写HttpFetcherDelegate的方法
69 void ReceivedBytes(HttpFetcher* fetcher,
70 const void* bytes, size_t length) override;
71 void SeekToOffset(off_t offset) override;
72 void TransferComplete(HttpFetcher* fetcher, bool successful) override;
73 void TransferTerminated(HttpFetcher* fetcher) override;
74 //获取委托代理
75 DownloadActionDelegate* delegate() const { return delegate_; }
76 void set_delegate(DownloadActionDelegate* delegate) {
77 delegate_ = delegate;
78 }
79
80 void set_base_offset(int64_t base_offset) { base_offset_ = base_offset; }
81 // 获取http_fetcher
82 HttpFetcher* http_fetcher() { return http_fetcher_.get(); }
83
84 // Returns the p2p file id for the file being written or the empty
85 // string if we're not writing to a p2p file.
86 std::string p2p_file_id() { return p2p_file_id_; }
87
88 private:
89 // Closes the file descriptor for the p2p file being written and
90 // clears |p2p_file_id_| to indicate that we're no longer sharing
91 // the file. If |delete_p2p_file| is True, also deletes the file.
92 // If there is no p2p file descriptor, this method does nothing.
93 void CloseP2PSharingFd(bool delete_p2p_file);
94
95 // Starts sharing the p2p file. Must be called before
96 // WriteToP2PFile(). Returns True if this worked.
97 bool SetupP2PSharingFd();
98
99 // Writes |length| bytes of payload from |data| into |file_offset|
100 // of the p2p file. Also does sanity checks; for example ensures we
101 // don't end up with a file with holes in it.
102 //
103 // This method does nothing if SetupP2PSharingFd() hasn't been
104 // called or if CloseP2PSharingFd() has been called.
105 void WriteToP2PFile(const void* data, size_t length, off_t file_offset);
106
107 // Start downloading the current payload using delta_performer.
108 // 使用delta_performer开始下载当前的payload
109 void StartDownloading();
110
111 // The InstallPlan passed in
112 InstallPlan install_plan_;
113
114 // Pointer to the current payload in install_plan_.payloads.
115 InstallPlan::Payload* payload_{nullptr};
116
117 // SystemState required pointers.
118 PrefsInterface* prefs_;
119 BootControlInterface* boot_control_;
120 HardwareInterface* hardware_;
121
122 // Global context for the system.
123 SystemState* system_state_;
124
125 // Pointer to the MultiRangeHttpFetcher that does the http work.
126 // 具体做这个Http业务是MultiRangeHttpFetcher
127 std::unique_ptr<MultiRangeHttpFetcher> http_fetcher_;
128
129 // If |true|, the update is user initiated (vs. periodic update checks). Hence
130 // the |delta_performer_| can decide not to use O_DSYNC flag for faster
131 // update.
132 bool is_interactive_;
133
134 // The FileWriter that downloaded data should be written to. It will
135 // either point to *decompressing_file_writer_ or *delta_performer_.
136 // 具体执行写入分区操作,指向decompressing_file_writer_或者delta_performer_
137 FileWriter* writer_;
138
139 std::unique_ptr<DeltaPerformer> delta_performer_;
140
141 // Used by TransferTerminated to figure if this action terminated itself or
142 // was terminated by the action processor.
143 ErrorCode code_;
144
145 // For reporting status to outsiders
146 // 委托代理,用于向外部发送状态
147 DownloadActionDelegate* delegate_;
148 uint64_t bytes_received_{0}; // per file/range
149 uint64_t bytes_received_previous_payloads_{0};
150 uint64_t bytes_total_{0};
151 bool download_active_{false};
152
153 // The file-id for the file we're sharing or the empty string
154 // if we're not using p2p to share.
155 std::string p2p_file_id_;
156
157 // The file descriptor for the p2p file used for caching the payload or -1
158 // if we're not using p2p to share.
159 int p2p_sharing_fd_;
160
161 // Set to |false| if p2p file is not visible.
162 bool p2p_visible_;
163
164 // Loaded from prefs before downloading any payload.
165 size_t resume_payload_index_{0};
166
167 // Offset of the payload in the download URL, used by UpdateAttempterAndroid.
168 int64_t base_offset_{0};
169
170 DISALLOW_COPY_AND_ASSIGN(DownloadAction);
171};
172
173// We want to be sure that we're compiled with large file support on linux,
174// just in case we find ourselves downloading large images.
175static_assert(8 == sizeof(off_t), "off_t not 64 bit");
176
177} // namespace chromeos_update_engine
2.2 download_action.cc
2.2.1 PerformAction
1//具体执行Action的方法,老生常谈
2void DownloadAction::PerformAction() {
3 //将downloadAcion作为http_fetcher的委托对象
4 http_fetcher_->set_delegate(this);
5
6 // Get the InstallPlan and read it
7 //获取管道installplanAcion的输入,拿到install_plan
8 CHECK(HasInputObject());
9 install_plan_ = GetInputObject();
10 install_plan_.Dump();
11 //定义接收的字节数
12 bytes_received_ = 0;
13 //定义接收到之前的payloads的字节数
14 bytes_received_previous_payloads_ = 0;
15 //定义接收到的字节总数
16 bytes_total_ = 0;
17 //获取payload的字节总数
18 for (const auto& payload : install_plan_.payloads)
19 bytes_total_ += payload.size;
20 //根据判断条件是否有未完成的升级
21 if (install_plan_.is_resume) {
22 int64_t payload_index = 0;
23 if (prefs_->GetInt64(kPrefsUpdateStatePayloadIndex, &payload_index) &&
24 static_cast<size_t>(payload_index) < install_plan_.payloads.size()) {
25 // Save the index for the resume payload before downloading any previous
26 // payload, otherwise it will be overwritten.
27 // 在下载以前的payload之前 先保存当前需要恢复payload的标签,否则将会被重写
28 resume_payload_index_ = payload_index;
29 for (int i = 0; i < payload_index; i++)
30 install_plan_.payloads[i].already_applied = true;
31 }
32 }
33 // TODO(senj): check that install plan has at least one payload.
34 // 如果payload不存在,则指定payloads中其中0位置的的成员
35 if (!payload_)
36 payload_ = &install_plan_.payloads[0];
37 //编译target 分区为不可启动
38 LOG(INFO) << "Marking new slot as unbootable";
39 if (!boot_control_->MarkSlotUnbootable(install_plan_.target_slot)) {
40 LOG(WARNING) << "Unable to mark new slot "
41 << BootControlInterface::SlotName(install_plan_.target_slot)
42 << ". Proceeding with the update anyway.";
43 }
44 //开始执行download
45 StartDownloading();
46}
2.2.2 StartDownloading
1void DownloadAction::StartDownloading() {
2 //设定download_active_ 标志位为true
3 download_active_ = true;
4 //执行http_fetcher_的清空区间
5 http_fetcher_->ClearRanges();
6 //判断是否是执行恢复升级,而且payload_是resume_payload_index_
7 if (install_plan_.is_resume &&
8 payload_ == &install_plan_.payloads[resume_payload_index_]) {
9 // Resuming an update so fetch the update manifest metadata first.
10 int64_t

本文详细解析了固件升级过程中的四个关键行动:InstallPlanAction、DownloadAction、FilesystemVerifierAction和PostinstallRunnerAction。从数据下载、写入、分区验证到最终的脚本执行,逐一介绍了各阶段的功能及实现流程。

5375

被折叠的 条评论
为什么被折叠?



