六、A/B 升级update_engine分析-Action流程

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

   从上一篇我们已经知道具体的升级写入校验流程都是由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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值