Add a feature to get the last UpdateAttempt ErrorCode from update_engine
For autotest, update_engine test failures are always hard to debug,
since the error message is not clear. Add a new flag 'last_attempt_error'
to get the last UpdateAttempt ErrorCode from update_engine.
Bug:25598547
Test:emerge-peppy update_engine
emerge-peppy update_engine_client
cros flash a test image to DUT.
(on the DUT):update_engine_client --last_attempt_error
Compare the results with the update_engine logs, matched.
Change-Id: Id12681097ed30b0826cad68809f17f934a07e5b2
diff --git a/Android.mk b/Android.mk
index 0b30720..07d8f64 100644
--- a/Android.mk
+++ b/Android.mk
@@ -465,7 +465,8 @@
LOCAL_SHARED_LIBRARIES += \
libupdate_engine_client
LOCAL_SRC_FILES := \
- update_engine_client.cc
+ update_engine_client.cc \
+ common/error_code_utils.cc
else # !defined(BRILLO)
#TODO(deymo): Remove external/cros/system_api/dbus once the strings are moved
# out of the DBus interface.
diff --git a/UpdateEngine.conf b/UpdateEngine.conf
index 8a91607..9cf6042 100644
--- a/UpdateEngine.conf
+++ b/UpdateEngine.conf
@@ -54,6 +54,9 @@
<allow send_destination="org.chromium.UpdateEngine"
send_interface="org.chromium.UpdateEngineInterface"
send_member="GetPrevVersion"/>
+ <allow send_destination="org.chromium.UpdateEngine"
+ send_interface="org.chromium.UpdateEngineInterface"
+ send_member="GetLastAttemptError"/>
<allow send_interface="org.chromium.UpdateEngineLibcrosProxyResolvedInterface" />
</policy>
<policy user="power">
diff --git a/binder_bindings/android/brillo/IUpdateEngine.aidl b/binder_bindings/android/brillo/IUpdateEngine.aidl
index 9399ce3..1c0a3e5 100644
--- a/binder_bindings/android/brillo/IUpdateEngine.aidl
+++ b/binder_bindings/android/brillo/IUpdateEngine.aidl
@@ -36,4 +36,5 @@
String GetPrevVersion();
String GetRollbackPartition();
void RegisterStatusCallback(in IUpdateEngineStatusCallback callback);
+ int GetLastAttemptError();
}
diff --git a/binder_service_brillo.cc b/binder_service_brillo.cc
index 45ac343..6a6a16e 100644
--- a/binder_service_brillo.cc
+++ b/binder_service_brillo.cc
@@ -186,6 +186,12 @@
return Status::ok();
}
+Status BinderUpdateEngineBrilloService::GetLastAttemptError(
+ int* out_last_attempt_error) {
+ return CallCommonHandler(&UpdateEngineService::GetLastAttemptError,
+ out_last_attempt_error);
+}
+
void BinderUpdateEngineBrilloService::UnregisterStatusCallback(
IUpdateEngineStatusCallback* callback) {
auto it = callbacks_.begin();
diff --git a/binder_service_brillo.h b/binder_service_brillo.h
index 178305b..497b1b0 100644
--- a/binder_service_brillo.h
+++ b/binder_service_brillo.h
@@ -84,6 +84,8 @@
android::binder::Status RegisterStatusCallback(
const android::sp<android::brillo::IUpdateEngineStatusCallback>& callback)
override;
+ android::binder::Status GetLastAttemptError(
+ int* out_last_attempt_error) override;
private:
// Generic function for dispatching to the common service.
diff --git a/client_library/client_binder.cc b/client_library/client_binder.cc
index 6f9b7b6..321dfc4 100644
--- a/client_library/client_binder.cc
+++ b/client_library/client_binder.cc
@@ -215,5 +215,16 @@
return true;
}
+bool BinderUpdateEngineClient::GetLastAttemptError(
+ int32_t* last_attempt_error) const {
+ int out_as_int;
+
+ if (!service_->GetLastAttemptError(&out_as_int).isOk())
+ return false;
+
+ *last_attempt_error = out_as_int;
+ return true;
+}
+
} // namespace internal
} // namespace update_engine
diff --git a/client_library/client_binder.h b/client_library/client_binder.h
index 562cee4..72f80dd 100644
--- a/client_library/client_binder.h
+++ b/client_library/client_binder.h
@@ -80,6 +80,8 @@
bool RegisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
bool UnregisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
+ bool GetLastAttemptError(int32_t* last_attempt_error) const override;
+
private:
class StatusUpdateCallback :
public android::brillo::BnUpdateEngineStatusCallback {
diff --git a/client_library/client_dbus.cc b/client_library/client_dbus.cc
index 270a987..0d6b783 100644
--- a/client_library/client_dbus.cc
+++ b/client_library/client_dbus.cc
@@ -225,5 +225,10 @@
nullptr);
}
+bool DBusUpdateEngineClient::GetLastAttemptError(
+ int32_t* last_attempt_error) const {
+ return proxy_->GetLastAttemptError(last_attempt_error, nullptr);
+}
+
} // namespace internal
} // namespace update_engine
diff --git a/client_library/client_dbus.h b/client_library/client_dbus.h
index 507fb5c..02a7e84 100644
--- a/client_library/client_dbus.h
+++ b/client_library/client_dbus.h
@@ -73,6 +73,8 @@
bool RegisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
bool UnregisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
+ bool GetLastAttemptError(int32_t* last_attempt_error) const override;
+
private:
void DBusStatusHandlersRegistered(const std::string& interface,
const std::string& signal_name,
diff --git a/client_library/include/update_engine/client.h b/client_library/include/update_engine/client.h
index dc0fb8c..62ac5fb 100644
--- a/client_library/include/update_engine/client.h
+++ b/client_library/include/update_engine/client.h
@@ -112,6 +112,9 @@
// Unregister a status update handler
virtual bool UnregisterStatusUpdateHandler(StatusUpdateHandler* handler) = 0;
+ // Get the last UpdateAttempt error code.
+ virtual bool GetLastAttemptError(int32_t* last_attempt_error) const = 0;
+
protected:
// Use CreateInstance().
UpdateEngineClient() = default;
diff --git a/common_service.cc b/common_service.cc
index 3c77c93..f0b818f 100644
--- a/common_service.cc
+++ b/common_service.cc
@@ -35,6 +35,7 @@
#include "update_engine/omaha_request_params.h"
#include "update_engine/p2p_manager.h"
#include "update_engine/update_attempter.h"
+#include "update_engine/payload_state_interface.h"
using base::StringPrintf;
using brillo::ErrorPtr;
@@ -318,4 +319,10 @@
return true;
}
+bool UpdateEngineService::GetLastAttemptError(ErrorPtr* /* error */,
+ int32_t* out_last_attempt_error) {
+ ErrorCode error_code = system_state_->payload_state()->GetAttemptErrorCode();
+ *out_last_attempt_error = static_cast<int>(error_code);
+ return true;
+}
} // namespace chromeos_update_engine
diff --git a/common_service.h b/common_service.h
index e08b4fd..4ad8862 100644
--- a/common_service.h
+++ b/common_service.h
@@ -127,6 +127,10 @@
bool GetRollbackPartition(brillo::ErrorPtr* error,
std::string* out_rollback_partition_name);
+ // Returns the last UpdateAttempt error.
+ bool GetLastAttemptError(brillo::ErrorPtr* error,
+ int32_t* out_last_attempt_error);
+
private:
SystemState* system_state_;
};
diff --git a/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml b/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
index bc4ec36..02287de 100644
--- a/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
+++ b/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
@@ -80,5 +80,8 @@
<method name="GetRollbackPartition">
<arg type="s" name="rollback_partition_name" direction="out" />
</method>
+ <method name="GetLastAttemptError">
+ <arg type="i" name="last_attempt_error" direction="out" />
+ </method>
</interface>
</node>
diff --git a/dbus_service.cc b/dbus_service.cc
index 0ab0ac0..392555f 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -132,6 +132,11 @@
return common_->GetRollbackPartition(error, out_rollback_partition_name);
}
+bool DBusUpdateEngineService::GetLastAttemptError(
+ ErrorPtr* error, int32_t* out_last_attempt_error){
+ return common_->GetLastAttemptError(error, out_last_attempt_error);
+}
+
UpdateEngineAdaptor::UpdateEngineAdaptor(SystemState* system_state,
const scoped_refptr<dbus::Bus>& bus)
: org::chromium::UpdateEngineInterfaceAdaptor(&dbus_service_),
diff --git a/dbus_service.h b/dbus_service.h
index b0c68e5..1486e3c 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -129,6 +129,10 @@
bool GetRollbackPartition(brillo::ErrorPtr* error,
std::string* out_rollback_partition_name) override;
+ // Returns the last UpdateAttempt error. If not updated yet, default success
+ // ErrorCode will be returned.
+ bool GetLastAttemptError(brillo::ErrorPtr* error,
+ int32_t* out_last_attempt_error) override;
private:
std::unique_ptr<UpdateEngineService> common_;
};
diff --git a/payload_state.cc b/payload_state.cc
index 4b5b5fd..04b6579 100644
--- a/payload_state.cc
+++ b/payload_state.cc
@@ -62,6 +62,7 @@
url_switch_count_(0),
attempt_num_bytes_downloaded_(0),
attempt_connection_type_(metrics::ConnectionType::kUnknown),
+ attempt_error_code_(ErrorCode::kSuccess),
attempt_type_(AttemptType::kUpdate) {
for (int i = 0; i <= kNumDownloadSources; i++)
total_bytes_downloaded_[i] = current_bytes_downloaded_[i] = 0;
@@ -232,6 +233,7 @@
metrics::RollbackResult::kSuccess);
break;
}
+ attempt_error_code_ = ErrorCode::kSuccess;
// Reset the number of responses seen since it counts from the last
// successful update, e.g. now.
@@ -265,6 +267,8 @@
break;
}
+ attempt_error_code_ = base_error;
+
switch (base_error) {
// Errors which are good indicators of a problem with a particular URL or
// the protocol used in the URL or entities in the communication channel
diff --git a/payload_state.h b/payload_state.h
index bec5823..46711b6 100644
--- a/payload_state.h
+++ b/payload_state.h
@@ -147,6 +147,10 @@
return p2p_url_;
}
+ inline ErrorCode GetAttemptErrorCode() const override {
+ return attempt_error_code_;
+ }
+
private:
enum class AttemptType {
kUpdate,
@@ -559,6 +563,9 @@
// The connection type when the attempt started.
metrics::ConnectionType attempt_connection_type_;
+ // The attempt error code when the attempt finished.
+ ErrorCode attempt_error_code_;
+
// Whether we're currently rolling back.
AttemptType attempt_type_;
diff --git a/payload_state_interface.h b/payload_state_interface.h
index 40a13dd..68798ee 100644
--- a/payload_state_interface.h
+++ b/payload_state_interface.h
@@ -192,6 +192,7 @@
// Sets/gets the P2P download URL, if one is to be used.
virtual void SetP2PUrl(const std::string& url) = 0;
virtual std::string GetP2PUrl() const = 0;
+ virtual ErrorCode GetAttemptErrorCode() const = 0;
};
} // namespace chromeos_update_engine
diff --git a/update_engine.gyp b/update_engine.gyp
index ab20243..7da34fb 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -334,7 +334,8 @@
],
'sources': [
'update_engine_client.cc',
- ],
+ 'common/error_code_utils.cc',
+ ],
},
# server-side code. This is used for delta_generator and unittests but not
# for any client code.
diff --git a/update_engine_client.cc b/update_engine_client.cc
index eabc546..22fe6a6 100644
--- a/update_engine_client.cc
+++ b/update_engine_client.cc
@@ -29,12 +29,15 @@
#include <brillo/daemons/daemon.h>
#include <brillo/flag_helper.h>
+#include "update_engine/common/error_code.h"
+#include "update_engine/common/error_code_utils.h"
#include "update_engine/client.h"
#include "update_engine/status_update_handler.h"
#include "update_engine/update_status.h"
#include "update_engine/update_status_utils.h"
using chromeos_update_engine::UpdateStatusToString;
+using chromeos_update_engine::ErrorCode;
using std::string;
using std::unique_ptr;
using std::vector;
@@ -262,6 +265,7 @@
"Listen for status updates and print them to the screen.");
DEFINE_bool(prev_version, false,
"Show the previous OS version used before the update reboot.");
+ DEFINE_bool(last_attempt_error, false, "Show the last attempt error.");
// Boilerplate init commands.
base::CommandLine::Init(argc_, argv_);
@@ -509,6 +513,19 @@
return kContinueRunning;
}
+ if (FLAGS_last_attempt_error) {
+ int last_attempt_error;
+ if (!client_->GetLastAttemptError(&last_attempt_error)) {
+ LOG(ERROR) << "Error getting last attempt error.";
+ } else {
+ ErrorCode code = static_cast<ErrorCode>(last_attempt_error);
+ string error_msg = chromeos_update_engine::utils::ErrorCodeToString(code);
+ printf("ERROR_CODE=%i\n"
+ "ERROR_MESSAGE=%s\n",
+ last_attempt_error, error_msg.c_str());
+ }
+ }
+
return 0;
}