summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deymo <deymo@google.com>2016-04-18 19:57:58 -0700
committerAlex Deymo <deymo@google.com>2016-05-03 17:17:58 -0700
commitb3fa53bf760bd0a6fd1ef9df28cb425586d733f6 (patch)
tree457141d09742613dd2b3f64a92d6da4a83a0e390
parented9bd92e00099eddda86b32fd2bb4896cb44cd51 (diff)
downloadandroid_system_update_engine-b3fa53bf760bd0a6fd1ef9df28cb425586d733f6.tar.gz
android_system_update_engine-b3fa53bf760bd0a6fd1ef9df28cb425586d733f6.tar.bz2
android_system_update_engine-b3fa53bf760bd0a6fd1ef9df28cb425586d733f6.zip
Parse and expose end-of-life flag.
Omaha update or noupdate response can include _key=value pairs with arbitrary data. One of those key can be "_eol" with the one of the values "supported", "security-only" or "eol" which notifies the device the end-of-life status of the device with respect to updates. This information is now exposed via GetEolStatus() to the client so it can be properly displayed in the UI. Bug: 27924505 TEST=Added unittest. Run `update_engine_client --eol_status` on link. Change-Id: Icc15f25b4d0b19cc894f5afc52ac7c43c7818982
-rw-r--r--Android.mk5
-rw-r--r--UpdateEngine.conf3
-rw-r--r--binder_bindings/android/brillo/IUpdateEngine.aidl1
-rw-r--r--binder_service_brillo.cc9
-rw-r--r--binder_service_brillo.h1
-rw-r--r--client_library/client_binder.cc17
-rw-r--r--client_library/client_binder.h10
-rw-r--r--client_library/client_dbus.cc9
-rw-r--r--client_library/client_dbus.h2
-rw-r--r--client_library/include/update_engine/client.h3
-rw-r--r--common/constants.cc1
-rw-r--r--common/constants.h1
-rw-r--r--common_service.cc20
-rw-r--r--common_service.h4
-rw-r--r--common_service_unittest.cc17
-rw-r--r--dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml3
-rw-r--r--dbus_service.cc9
-rw-r--r--dbus_service.h4
-rw-r--r--omaha_request_action.cc24
-rw-r--r--omaha_request_action.h5
-rw-r--r--omaha_request_action_unittest.cc30
-rw-r--r--omaha_utils.cc57
-rw-r--r--omaha_utils.h40
-rw-r--r--omaha_utils_unittest.cc42
-rw-r--r--update_engine.gyp3
-rw-r--r--update_engine_client.cc13
26 files changed, 309 insertions, 24 deletions
diff --git a/Android.mk b/Android.mk
index 107a8449..93c6c871 100644
--- a/Android.mk
+++ b/Android.mk
@@ -315,6 +315,7 @@ LOCAL_SRC_FILES := \
omaha_request_action.cc \
omaha_request_params.cc \
omaha_response_handler_action.cc \
+ omaha_utils.cc \
p2p_manager.cc \
payload_state.cc \
proxy_resolver.cc \
@@ -524,7 +525,8 @@ LOCAL_SHARED_LIBRARIES += \
libupdate_engine_client
LOCAL_SRC_FILES := \
update_engine_client.cc \
- common/error_code_utils.cc
+ common/error_code_utils.cc \
+ omaha_utils.cc
else # !defined(BRILLO)
#TODO(deymo): Remove external/cros/system_api/dbus once the strings are moved
# out of the DBus interface.
@@ -904,6 +906,7 @@ LOCAL_SRC_FILES := \
omaha_request_action_unittest.cc \
omaha_request_params_unittest.cc \
omaha_response_handler_action_unittest.cc \
+ omaha_utils_unittest.cc \
p2p_manager_unittest.cc \
payload_consumer/bzip_extent_writer_unittest.cc \
payload_consumer/delta_performer_integration_test.cc \
diff --git a/UpdateEngine.conf b/UpdateEngine.conf
index 9cf60428..9238e3a6 100644
--- a/UpdateEngine.conf
+++ b/UpdateEngine.conf
@@ -57,6 +57,9 @@
<allow send_destination="org.chromium.UpdateEngine"
send_interface="org.chromium.UpdateEngineInterface"
send_member="GetLastAttemptError"/>
+ <allow send_destination="org.chromium.UpdateEngine"
+ send_interface="org.chromium.UpdateEngineInterface"
+ send_member="GetEolStatus"/>
<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 1c0a3e55..6a3295ab 100644
--- a/binder_bindings/android/brillo/IUpdateEngine.aidl
+++ b/binder_bindings/android/brillo/IUpdateEngine.aidl
@@ -37,4 +37,5 @@ interface IUpdateEngine {
String GetRollbackPartition();
void RegisterStatusCallback(in IUpdateEngineStatusCallback callback);
int GetLastAttemptError();
+ int GetEolStatus();
}
diff --git a/binder_service_brillo.cc b/binder_service_brillo.cc
index 6a6a16e1..3947ae1d 100644
--- a/binder_service_brillo.cc
+++ b/binder_service_brillo.cc
@@ -192,12 +192,15 @@ Status BinderUpdateEngineBrilloService::GetLastAttemptError(
out_last_attempt_error);
}
+Status BinderUpdateEngineBrilloService::GetEolStatus(int* out_eol_status) {
+ return CallCommonHandler(&UpdateEngineService::GetEolStatus, out_eol_status);
+}
+
void BinderUpdateEngineBrilloService::UnregisterStatusCallback(
IUpdateEngineStatusCallback* callback) {
auto it = callbacks_.begin();
-
- for (; it != callbacks_.end() && it->get() != callback; it++)
- ;
+ while (it != callbacks_.end() && it->get() != callback)
+ it++;
if (it == callbacks_.end()) {
LOG(ERROR) << "Got death notification for unknown callback.";
diff --git a/binder_service_brillo.h b/binder_service_brillo.h
index 497b1b06..b3bb81f1 100644
--- a/binder_service_brillo.h
+++ b/binder_service_brillo.h
@@ -86,6 +86,7 @@ class BinderUpdateEngineBrilloService : public android::brillo::BnUpdateEngine,
override;
android::binder::Status GetLastAttemptError(
int* out_last_attempt_error) override;
+ android::binder::Status GetEolStatus(int* out_eol_status) 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 321dfc40..6a617223 100644
--- a/client_library/client_binder.cc
+++ b/client_library/client_binder.cc
@@ -28,8 +28,8 @@
using android::OK;
using android::String16;
using android::String8;
-using android::brillo::ParcelableUpdateEngineStatus;
using android::binder::Status;
+using android::brillo::ParcelableUpdateEngineStatus;
using android::getService;
using chromeos_update_engine::StringToUpdateStatus;
using chromeos_update_engine::UpdateEngineService;
@@ -177,10 +177,7 @@ bool BinderUpdateEngineClient::RegisterStatusUpdateHandler(
bool BinderUpdateEngineClient::UnregisterStatusUpdateHandler(
StatusUpdateHandler* handler) {
- auto it = handlers_.begin();
-
- for (; *it != handler && it != handlers_.end(); it++);
-
+ auto it = std::find(handlers_.begin(), handlers_.end(), handler);
if (it != handlers_.end()) {
handlers_.erase(it);
return true;
@@ -226,5 +223,15 @@ bool BinderUpdateEngineClient::GetLastAttemptError(
return true;
}
+bool BinderUpdateEngineClient::GetEolStatus(int32_t* eol_status) const {
+ int out_as_int;
+
+ if (!service_->GetEolStatus(&out_as_int).isOk())
+ return false;
+
+ *eol_status = 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 72f80dd7..cd857e01 100644
--- a/client_library/client_binder.h
+++ b/client_library/client_binder.h
@@ -23,14 +23,13 @@
#include <vector>
#include <base/macros.h>
-#include <utils/StrongPointer.h>
#include <utils/String16.h>
+#include <utils/StrongPointer.h>
#include <brillo/binder_watcher.h>
-#include "android/brillo/IUpdateEngine.h"
#include "android/brillo/BnUpdateEngineStatusCallback.h"
-
+#include "android/brillo/IUpdateEngine.h"
#include "update_engine/client_library/include/update_engine/client.h"
@@ -82,11 +81,14 @@ class BinderUpdateEngineClient : public UpdateEngineClient {
bool GetLastAttemptError(int32_t* last_attempt_error) const override;
+ bool GetEolStatus(int32_t* eol_status) const override;
+
private:
class StatusUpdateCallback :
public android::brillo::BnUpdateEngineStatusCallback {
public:
- StatusUpdateCallback(BinderUpdateEngineClient* client) : client_(client) {}
+ explicit StatusUpdateCallback(BinderUpdateEngineClient* client)
+ : client_(client) {}
android::binder::Status HandleStatusUpdate(
int64_t last_checked_time,
diff --git a/client_library/client_dbus.cc b/client_library/client_dbus.cc
index 0d6b7833..5cb63a49 100644
--- a/client_library/client_dbus.cc
+++ b/client_library/client_dbus.cc
@@ -171,10 +171,7 @@ void DBusUpdateEngineClient::RunStatusUpdateHandlers(
bool DBusUpdateEngineClient::UnregisterStatusUpdateHandler(
StatusUpdateHandler* handler) {
- auto it = handlers_.begin();
-
- for (; *it != handler && it != handlers_.end(); it++);
-
+ auto it = std::find(handlers_.begin(), handlers_.end(), handler);
if (it != handlers_.end()) {
handlers_.erase(it);
return true;
@@ -230,5 +227,9 @@ bool DBusUpdateEngineClient::GetLastAttemptError(
return proxy_->GetLastAttemptError(last_attempt_error, nullptr);
}
+bool DBusUpdateEngineClient::GetEolStatus(int32_t* eol_status) const {
+ return proxy_->GetEolStatus(eol_status, nullptr);
+}
+
} // namespace internal
} // namespace update_engine
diff --git a/client_library/client_dbus.h b/client_library/client_dbus.h
index 02a7e84a..a2de5948 100644
--- a/client_library/client_dbus.h
+++ b/client_library/client_dbus.h
@@ -75,6 +75,8 @@ class DBusUpdateEngineClient : public UpdateEngineClient {
bool GetLastAttemptError(int32_t* last_attempt_error) const override;
+ bool GetEolStatus(int32_t* eol_status) 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 62ac5fb3..7956dbd2 100644
--- a/client_library/include/update_engine/client.h
+++ b/client_library/include/update_engine/client.h
@@ -115,6 +115,9 @@ class UpdateEngineClient {
// Get the last UpdateAttempt error code.
virtual bool GetLastAttemptError(int32_t* last_attempt_error) const = 0;
+ // Get the current end-of-life status code. See EolStatus enum for details.
+ virtual bool GetEolStatus(int32_t* eol_status) const = 0;
+
protected:
// Use CreateInstance().
UpdateEngineClient() = default;
diff --git a/common/constants.cc b/common/constants.cc
index f138ce3c..c0bb8742 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -57,6 +57,7 @@ const char kPrefsNumResponsesSeen[] = "num-responses-seen";
const char kPrefsOmahaCohort[] = "omaha-cohort";
const char kPrefsOmahaCohortHint[] = "omaha-cohort-hint";
const char kPrefsOmahaCohortName[] = "omaha-cohort-name";
+const char kPrefsOmahaEolStatus[] = "omaha-eol-status";
const char kPrefsP2PEnabled[] = "p2p-enabled";
const char kPrefsP2PFirstAttemptTimestamp[] = "p2p-first-attempt-timestamp";
const char kPrefsP2PNumAttempts[] = "p2p-num-attempts";
diff --git a/common/constants.h b/common/constants.h
index f0d589dc..660d9a96 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -61,6 +61,7 @@ extern const char kPrefsNumResponsesSeen[];
extern const char kPrefsOmahaCohort[];
extern const char kPrefsOmahaCohortHint[];
extern const char kPrefsOmahaCohortName[];
+extern const char kPrefsOmahaEolStatus[];
extern const char kPrefsP2PEnabled[];
extern const char kPrefsP2PFirstAttemptTimestamp[];
extern const char kPrefsP2PNumAttempts[];
diff --git a/common_service.cc b/common_service.cc
index f0b818ff..ade5349e 100644
--- a/common_service.cc
+++ b/common_service.cc
@@ -33,9 +33,10 @@
#include "update_engine/common/utils.h"
#include "update_engine/connection_manager_interface.h"
#include "update_engine/omaha_request_params.h"
+#include "update_engine/omaha_utils.h"
#include "update_engine/p2p_manager.h"
-#include "update_engine/update_attempter.h"
#include "update_engine/payload_state_interface.h"
+#include "update_engine/update_attempter.h"
using base::StringPrintf;
using brillo::ErrorPtr;
@@ -325,4 +326,21 @@ bool UpdateEngineService::GetLastAttemptError(ErrorPtr* /* error */,
*out_last_attempt_error = static_cast<int>(error_code);
return true;
}
+
+bool UpdateEngineService::GetEolStatus(ErrorPtr* error,
+ int32_t* out_eol_status) {
+ PrefsInterface* prefs = system_state_->prefs();
+
+ string str_eol_status;
+ if (prefs->Exists(kPrefsOmahaEolStatus) &&
+ !prefs->GetString(kPrefsOmahaEolStatus, &str_eol_status)) {
+ LogAndSetError(error, FROM_HERE, "Error getting the end-of-life status.");
+ return false;
+ }
+
+ // StringToEolStatus will return kSupported for invalid values.
+ *out_eol_status = static_cast<int32_t>(StringToEolStatus(str_eol_status));
+ return true;
+}
+
} // namespace chromeos_update_engine
diff --git a/common_service.h b/common_service.h
index 4ad8862d..1d380bc8 100644
--- a/common_service.h
+++ b/common_service.h
@@ -131,6 +131,10 @@ class UpdateEngineService {
bool GetLastAttemptError(brillo::ErrorPtr* error,
int32_t* out_last_attempt_error);
+ // Returns the current end-of-life status of the device. This value is updated
+ // on every update check and persisted on disk across reboots.
+ bool GetEolStatus(brillo::ErrorPtr* error, int32_t* out_eol_status);
+
private:
SystemState* system_state_;
};
diff --git a/common_service_unittest.cc b/common_service_unittest.cc
index 1c144d1b..0a7bfc34 100644
--- a/common_service_unittest.cc
+++ b/common_service_unittest.cc
@@ -23,7 +23,9 @@
#include <policy/libpolicy.h>
#include <policy/mock_device_policy.h>
+#include "update_engine/common/fake_prefs.h"
#include "update_engine/fake_system_state.h"
+#include "update_engine/omaha_utils.h"
using std::string;
using testing::Return;
@@ -131,4 +133,19 @@ TEST_F(UpdateEngineServiceTest, ResetStatusFails) {
UpdateEngineService::kErrorFailed));
}
+TEST_F(UpdateEngineServiceTest, GetEolStatusTest) {
+ FakePrefs fake_prefs;
+ fake_system_state_.set_prefs(&fake_prefs);
+ // The default value should be "supported".
+ int32_t eol_status = static_cast<int32_t>(EolStatus::kEol);
+ EXPECT_TRUE(common_service_.GetEolStatus(&error_, &eol_status));
+ EXPECT_EQ(nullptr, error_);
+ EXPECT_EQ(EolStatus::kSupported, static_cast<EolStatus>(eol_status));
+
+ fake_prefs.SetString(kPrefsOmahaEolStatus, "security-only");
+ EXPECT_TRUE(common_service_.GetEolStatus(&error_, &eol_status));
+ EXPECT_EQ(nullptr, error_);
+ EXPECT_EQ(EolStatus::kSecurityOnly, static_cast<EolStatus>(eol_status));
+}
+
} // namespace chromeos_update_engine
diff --git a/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml b/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
index 02287de7..aa995080 100644
--- a/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
+++ b/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
@@ -83,5 +83,8 @@
<method name="GetLastAttemptError">
<arg type="i" name="last_attempt_error" direction="out" />
</method>
+ <method name="GetEolStatus">
+ <arg type="i" name="eol_status" direction="out" />
+ </method>
</interface>
</node>
diff --git a/dbus_service.cc b/dbus_service.cc
index 392555fa..de1f9b56 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -133,8 +133,13 @@ bool DBusUpdateEngineService::GetRollbackPartition(
}
bool DBusUpdateEngineService::GetLastAttemptError(
- ErrorPtr* error, int32_t* out_last_attempt_error){
- return common_->GetLastAttemptError(error, out_last_attempt_error);
+ ErrorPtr* error, int32_t* out_last_attempt_error) {
+ return common_->GetLastAttemptError(error, out_last_attempt_error);
+}
+
+bool DBusUpdateEngineService::GetEolStatus(ErrorPtr* error,
+ int32_t* out_eol_status) {
+ return common_->GetEolStatus(error, out_eol_status);
}
UpdateEngineAdaptor::UpdateEngineAdaptor(SystemState* system_state,
diff --git a/dbus_service.h b/dbus_service.h
index 1486e3ca..12f8cf12 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -133,6 +133,10 @@ class DBusUpdateEngineService
// ErrorCode will be returned.
bool GetLastAttemptError(brillo::ErrorPtr* error,
int32_t* out_last_attempt_error) override;
+
+ // Returns the current end-of-life status of the device in |out_eol_status|.
+ bool GetEolStatus(brillo::ErrorPtr* error, int32_t* out_eol_status) override;
+
private:
std::unique_ptr<UpdateEngineService> common_;
};
diff --git a/omaha_request_action.cc b/omaha_request_action.cc
index 018f9aaa..16338a8c 100644
--- a/omaha_request_action.cc
+++ b/omaha_request_action.cc
@@ -77,6 +77,9 @@ static const char* kTagPublicKeyRsa = "PublicKeyRsa";
static const char* kOmahaUpdaterVersion = "0.1.0.0";
+// updatecheck attributes (without the underscore prefix).
+static const char* kEolAttr = "eol";
+
namespace {
// Returns an XML ping element attribute assignment with attribute
@@ -339,6 +342,7 @@ struct OmahaParserData {
bool app_cohortname_set = false;
string updatecheck_status;
string updatecheck_poll_interval;
+ map<string, string> updatecheck_attrs;
string daystart_elapsed_days;
string daystart_elapsed_seconds;
vector<string> url_codebase;
@@ -386,6 +390,12 @@ void ParserHandlerStart(void* user_data, const XML_Char* element,
// There is only supposed to be a single <updatecheck> element.
data->updatecheck_status = attrs["status"];
data->updatecheck_poll_interval = attrs["PollInterval"];
+ // Omaha sends arbitrary key-value pairs as extra attributes starting with
+ // an underscore.
+ for (const auto& attr : attrs) {
+ if (!attr.first.empty() && attr.first[0] == '_')
+ data->updatecheck_attrs[attr.first.substr(1)] = attr.second;
+ }
} else if (data->current_path == "/response/daystart") {
// Get the install-date.
data->daystart_elapsed_days = attrs["elapsed_days"];
@@ -748,6 +758,9 @@ bool OmahaRequestAction::ParseResponse(OmahaParserData* parser_data,
if (parser_data->app_cohortname_set)
PersistCohortData(kPrefsOmahaCohortName, parser_data->app_cohortname);
+ // Parse the updatecheck attributes.
+ PersistEolStatus(parser_data->updatecheck_attrs);
+
if (!ParseStatus(parser_data, output_object, completer))
return false;
@@ -1384,6 +1397,17 @@ bool OmahaRequestAction::PersistCohortData(
return true;
}
+bool OmahaRequestAction::PersistEolStatus(const map<string, string>& attrs) {
+ auto eol_attr = attrs.find(kEolAttr);
+ if (eol_attr != attrs.end()) {
+ return system_state_->prefs()->SetString(kPrefsOmahaEolStatus,
+ eol_attr->second);
+ } else if (system_state_->prefs()->Exists(kPrefsOmahaEolStatus)) {
+ return system_state_->prefs()->Delete(kPrefsOmahaEolStatus);
+ }
+ return true;
+}
+
void OmahaRequestAction::ActionCompleted(ErrorCode code) {
// We only want to report this on "update check".
if (ping_only_ || event_ != nullptr)
diff --git a/omaha_request_action.h b/omaha_request_action.h
index 1aeaf8a3..2915a6a8 100644
--- a/omaha_request_action.h
+++ b/omaha_request_action.h
@@ -21,6 +21,7 @@
#include <sys/stat.h>
#include <sys/types.h>
+#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -219,6 +220,10 @@ class OmahaRequestAction : public Action<OmahaRequestAction>,
bool PersistCohortData(const std::string& prefs_key,
const std::string& new_value);
+ // Parse and persist the end-of-life status flag sent back in the updatecheck
+ // tag attributes. The flag will be validated and stored in the Prefs.
+ bool PersistEolStatus(const std::map<std::string, std::string>& attrs);
+
// If this is an update check request, initializes
// |ping_active_days_| and |ping_roll_call_days_| to values that may
// be sent as pings to Omaha.
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index 496143e5..a7abdece 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -51,8 +51,6 @@
using base::Time;
using base::TimeDelta;
-using chromeos_update_engine::test_utils::System;
-using chromeos_update_engine::test_utils::WriteFileString;
using std::string;
using std::vector;
using testing::AllOf;
@@ -355,9 +353,7 @@ bool OmahaRequestActionTest::TestUpdateCheck(
? 0 : 1);
loop.PostTask(base::Bind([&processor] { processor.StartProcessing(); }));
- LOG(INFO) << "loop.PendingTasks() = " << loop.PendingTasks();
loop.Run();
- LOG(INFO) << "loop.PendingTasks() = " << loop.PendingTasks();
EXPECT_FALSE(loop.PendingTasks());
if (collector_action.has_input_object_ && out_response)
*out_response = collector_action.omaha_response_;
@@ -1676,6 +1672,32 @@ TEST_F(OmahaRequestActionTest, BadElapsedSecondsTest) {
nullptr));
}
+TEST_F(OmahaRequestActionTest, ParseUpdateCheckAttributesTest) {
+ // Test that the "eol" flags is only parsed from the "_eol" attribute and not
+ // the "eol" attribute.
+ ASSERT_TRUE(
+ TestUpdateCheck(nullptr, // request_params
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><response "
+ "protocol=\"3.0\"><app appid=\"foo\" status=\"ok\">"
+ "<ping status=\"ok\"/><updatecheck status=\"noupdate\" "
+ "_eol=\"security-only\" eol=\"eol\" _foo=\"bar\"/>"
+ "</app></response>",
+ -1,
+ false, // ping_only
+ ErrorCode::kSuccess,
+ metrics::CheckResult::kNoUpdateAvailable,
+ metrics::CheckReaction::kUnset,
+ metrics::DownloadErrorCode::kUnset,
+ nullptr,
+ nullptr));
+ string eol_pref;
+ EXPECT_TRUE(
+ fake_system_state_.prefs()->GetString(kPrefsOmahaEolStatus, &eol_pref));
+ // Note that the eol="eol" attribute should be ignored and the _eol should be
+ // used instead.
+ EXPECT_EQ("security-only", eol_pref);
+}
+
TEST_F(OmahaRequestActionTest, NoUniqueIDTest) {
brillo::Blob post_data;
ASSERT_FALSE(TestUpdateCheck(nullptr, // request_params
diff --git a/omaha_utils.cc b/omaha_utils.cc
new file mode 100644
index 00000000..6bd75250
--- /dev/null
+++ b/omaha_utils.cc
@@ -0,0 +1,57 @@
+//
+// Copyright (C) 2016 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.
+//
+
+#include "update_engine/omaha_utils.h"
+
+#include <base/logging.h>
+
+namespace chromeos_update_engine {
+
+namespace {
+
+// The possible string values for the end-of-life status.
+const char kEolStatusSupported[] = "supported";
+const char kEolStatusSecurityOnly[] = "security-only";
+const char kEolStatusEol[] = "eol";
+
+} // namespace
+
+const char* EolStatusToString(EolStatus eol_status) {
+ switch (eol_status) {
+ case EolStatus::kSupported:
+ return kEolStatusSupported;
+ case EolStatus::kSecurityOnly:
+ return kEolStatusSecurityOnly;
+ case EolStatus::kEol:
+ return kEolStatusEol;
+ }
+ // Only reached if an invalid number is casted to |EolStatus|.
+ LOG(WARNING) << "Invalid EolStatus value: " << static_cast<int>(eol_status);
+ return kEolStatusSupported;
+}
+
+EolStatus StringToEolStatus(const std::string& eol_status) {
+ if (eol_status == kEolStatusSupported || eol_status.empty())
+ return EolStatus::kSupported;
+ if (eol_status == kEolStatusSecurityOnly)
+ return EolStatus::kSecurityOnly;
+ if (eol_status == kEolStatusEol)
+ return EolStatus::kEol;
+ LOG(WARNING) << "Invalid end-of-life attribute: " << eol_status;
+ return EolStatus::kSupported;
+}
+
+} // namespace chromeos_update_engine
diff --git a/omaha_utils.h b/omaha_utils.h
new file mode 100644
index 00000000..86145403
--- /dev/null
+++ b/omaha_utils.h
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2016 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_OMAHA_UTILS_H_
+#define UPDATE_ENGINE_OMAHA_UTILS_H_
+
+#include <string>
+
+namespace chromeos_update_engine {
+
+// The end-of-life status of the device.
+enum class EolStatus {
+ kSupported = 0,
+ kSecurityOnly,
+ kEol,
+};
+
+// Returns the string representation of the |eol_status|.
+const char* EolStatusToString(EolStatus eol_status);
+
+// Converts the end-of-life status string to an EolStatus numeric value. In case
+// of an invalid string, the default "supported" value will be used instead.
+EolStatus StringToEolStatus(const std::string& eol_status);
+
+} // namespace chromeos_update_engine
+
+#endif // UPDATE_ENGINE_OMAHA_UTILS_H_
diff --git a/omaha_utils_unittest.cc b/omaha_utils_unittest.cc
new file mode 100644
index 00000000..8ceb76bf
--- /dev/null
+++ b/omaha_utils_unittest.cc
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2016 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.
+//
+
+#include "update_engine/omaha_utils.h"
+
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace chromeos_update_engine {
+
+class OmahaUtilsTest : public ::testing::Test {};
+
+TEST(OmahaUtilsTest, EolStatusTest) {
+ EXPECT_EQ(EolStatus::kEol, StringToEolStatus("eol"));
+
+ // Supported values are converted back and forth properly.
+ const std::vector<EolStatus> tests = {
+ EolStatus::kSupported, EolStatus::kSecurityOnly, EolStatus::kEol};
+ for (EolStatus eol_status : tests) {
+ EXPECT_EQ(eol_status, StringToEolStatus(EolStatusToString(eol_status)))
+ << "The StringToEolStatus() was " << EolStatusToString(eol_status);
+ }
+
+ // Invalid values are assumed as "supported".
+ EXPECT_EQ(EolStatus::kSupported, StringToEolStatus(""));
+ EXPECT_EQ(EolStatus::kSupported, StringToEolStatus("hello, world!"));
+}
+
+} // namespace chromeos_update_engine
diff --git a/update_engine.gyp b/update_engine.gyp
index 5f24a833..b8eccdc8 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -261,6 +261,7 @@
'omaha_request_action.cc',
'omaha_request_params.cc',
'omaha_response_handler_action.cc',
+ 'omaha_utils.cc',
'p2p_manager.cc',
'payload_state.cc',
'proxy_resolver.cc',
@@ -344,6 +345,7 @@
],
'sources': [
'common/error_code_utils.cc',
+ 'omaha_utils.cc',
'update_engine_client.cc',
],
},
@@ -511,6 +513,7 @@
'omaha_request_action_unittest.cc',
'omaha_request_params_unittest.cc',
'omaha_response_handler_action_unittest.cc',
+ 'omaha_utils_unittest.cc',
'p2p_manager_unittest.cc',
'payload_consumer/bzip_extent_writer_unittest.cc',
'payload_consumer/delta_performer_integration_test.cc',
diff --git a/update_engine_client.cc b/update_engine_client.cc
index 6ade12cf..55d7e649 100644
--- a/update_engine_client.cc
+++ b/update_engine_client.cc
@@ -32,10 +32,12 @@
#include "update_engine/client.h"
#include "update_engine/common/error_code.h"
#include "update_engine/common/error_code_utils.h"
+#include "update_engine/omaha_utils.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::EolStatus;
using chromeos_update_engine::ErrorCode;
using chromeos_update_engine::UpdateStatusToString;
using chromeos_update_engine::utils::ErrorCodeToString;
@@ -273,6 +275,7 @@ int UpdateEngineClient::ProcessFlags() {
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.");
+ DEFINE_bool(eol_status, false, "Show the current end-of-life status.");
// Boilerplate init commands.
base::CommandLine::Init(argc_, argv_);
@@ -534,6 +537,16 @@ int UpdateEngineClient::ProcessFlags() {
}
}
+ if (FLAGS_eol_status) {
+ int eol_status;
+ if (!client_->GetEolStatus(&eol_status)) {
+ LOG(ERROR) << "Error getting the end-of-life status.";
+ } else {
+ EolStatus eol_status_code = static_cast<EolStatus>(eol_status);
+ printf("EOL_STATUS=%s\n", EolStatusToString(eol_status_code));
+ }
+ }
+
return 0;
}