update_engine: Added ability to retrieve old version via DBus
Now it is possible to retrieve an old OS version that was in use
before the last reboot, provided that we are now booted into
an updated version. This is to be used by crash reporter in case
the reboot was caused by a crash in kernel while reboot was pending
for an update. In such a scenario, the crash would be attributed
to the current (updated) version, which is wrong.
Also added additional parameter, --old_version, to
update_engine_client to retrieve the old version number, if any,
from the update engine.
BUG=chrome-os-partner:26518
TEST=cros deploy and tested via update_engine_client
Change-Id: I84e2322c5698b44b4c77f25c8f4211cdb367e5dc
Reviewed-on: https://chromium-review.googlesource.com/190149
Reviewed-by: Chris Sosa <[email protected]>
Tested-by: Alex Vakulenko <[email protected]>
Commit-Queue: Alex Vakulenko <[email protected]>
diff --git a/UpdateEngine.conf b/UpdateEngine.conf
index ac40e9d..bdfd3c8 100644
--- a/UpdateEngine.conf
+++ b/UpdateEngine.conf
@@ -48,6 +48,9 @@
<allow send_destination="org.chromium.UpdateEngine"
send_interface="org.chromium.UpdateEngineInterface"
send_member="GetDurationSinceUpdate"/>
+ <allow send_destination="org.chromium.UpdateEngine"
+ send_interface="org.chromium.UpdateEngineInterface"
+ send_member="GetOldVersion"/>
<allow send_interface="org.chromium.UpdateEngineLibcrosProxyResolvedInterface" />
</policy>
<policy user="power">
diff --git a/dbus_service.cc b/dbus_service.cc
index a9455fe..7235be1 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -481,3 +481,12 @@
new_size);
return TRUE;
}
+
+gboolean update_engine_service_get_prev_version(
+ UpdateEngineService* self,
+ gchar** prev_version,
+ GError **error) {
+ std::string ver = self->system_state_->update_attempter()->GetPrevVersion();
+ *prev_version = g_strdup(ver.c_str());
+ return TRUE;
+}
diff --git a/dbus_service.h b/dbus_service.h
index cb8c0e2..3449f1f 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -151,6 +151,14 @@
const gchar* new_version,
gint64 new_size);
+// Returns the version string of OS that was used before the last reboot
+// into an updated version. This is avalable only when rebooting into an
+// update from previous version, otherwise an empty string is returned.
+gboolean update_engine_service_get_prev_version(
+ UpdateEngineService* self,
+ gchar** prev_version,
+ GError **error);
+
G_END_DECLS
#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_SERVICE_H_
diff --git a/update_attempter.cc b/update_attempter.cc
index 9cb7a25..5ab8e1a 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -1456,6 +1456,20 @@
void UpdateAttempter::UpdateEngineStarted() {
+ // If we just booted into a new update, keep the previous OS version
+ // in case we rebooted because of a crash of the old version, so we
+ // can do a proper crash report with correcy information.
+ // This must be done before calling
+ // system_state_->payload_state()->UpdateEngineStarted() since it will
+ // delete SystemUpdated marker file.
+ if (system_state_->system_rebooted() &&
+ prefs_->Exists(kPrefsSystemUpdatedMarker)) {
+ if (!prefs_->GetString(kPrefsPreviousVersion, &prev_version_)) {
+ // If we fail to get the version string, make sure it stays empty.
+ prev_version_.clear();
+ }
+ }
+
system_state_->payload_state()->UpdateEngineStarted();
StartP2PAtStartup();
}
diff --git a/update_attempter.h b/update_attempter.h
index 216d3c1..425d8ed 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -187,6 +187,11 @@
// successful update. Returns false if the device has not updated.
bool GetBootTimeAtUpdate(base::Time *out_boot_time);
+ // Returns a version OS version that was being used before the last reboot,
+ // and if that reboot happended to be into an update (current version).
+ // This will return an empty string otherwise.
+ std::string const& GetPrevVersion() const { return prev_version_; }
+
private:
// Update server URL for automated lab test.
static const char* const kTestUpdateUrl;
@@ -395,6 +400,7 @@
UpdateStatus status_;
double download_progress_;
int64_t last_checked_time_;
+ std::string prev_version_;
std::string new_version_;
int64_t new_payload_size_;
diff --git a/update_engine.xml b/update_engine.xml
index 964ea62..3891374 100644
--- a/update_engine.xml
+++ b/update_engine.xml
@@ -78,5 +78,8 @@
<arg type="s" name="new_version" />
<arg type="x" name="new_size" />
</signal>
+ <method name="GetPrevVersion">
+ <arg type="s" name="prev_version" direction="out" />
+ </method>
</interface>
</node>
diff --git a/update_engine_client.cc b/update_engine_client.cc
index 6bd3d9f..d27f027 100644
--- a/update_engine_client.cc
+++ b/update_engine_client.cc
@@ -57,6 +57,8 @@
"cellular networks.");
DEFINE_bool(watch_for_updates, false,
"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.");
namespace {
@@ -373,6 +375,26 @@
g_main_loop_unref(loop);
}
+void ShowPrevVersion() {
+ DBusGProxy* proxy;
+ GError* error = nullptr;
+
+ CHECK(GetProxy(&proxy));
+
+ char* prev_version = nullptr;
+
+ gboolean rc = update_engine_client_get_prev_version(proxy,
+ &prev_version,
+ &error);
+ if (!rc) {
+ LOG(ERROR) << "Error getting previous version: "
+ << GetAndFreeGError(&error);
+ } else {
+ LOG(INFO) << "Previous version = " << prev_version;
+ g_free(prev_version);
+ }
+}
+
} // namespace {}
int main(int argc, char** argv) {
@@ -521,6 +543,10 @@
return 0;
}
+ if (FLAGS_prev_version) {
+ ShowPrevVersion();
+ }
+
LOG(INFO) << "Done.";
return 0;
}