Make sure channel ends with -channel.

Also changed to_more_stable_channel() to return true for arbitrary channels.

Bug: 72259103
Test: update_engine_unittests

Change-Id: Ifddbc5f28563c956241c69141523c5a73ba53151
diff --git a/image_properties_android.cc b/image_properties_android.cc
index fa25683..4dc2c02 100644
--- a/image_properties_android.cc
+++ b/image_properties_android.cc
@@ -22,6 +22,7 @@
 
 #include <android-base/properties.h>
 #include <base/logging.h>
+#include <base/strings/string_util.h>
 #include <bootloader.h>
 #include <brillo/osrelease_reader.h>
 #include <brillo/strings/string_utils.h>
@@ -122,6 +123,10 @@
     LOG(INFO) << "No channel set in misc.";
     return false;
   }
+  if (!base::EndsWith(channel, "-channel", base::CompareCase::SENSITIVE)) {
+    LOG(ERROR) << "Channel " << channel << " doesn't end with -channel.";
+    return false;
+  }
   out_channel->assign(channel);
   return true;
 }
diff --git a/omaha_request_params.cc b/omaha_request_params.cc
index 641032b..8301d7b 100644
--- a/omaha_request_params.cc
+++ b/omaha_request_params.cc
@@ -150,16 +150,7 @@
             << ", existing target channel = "
             << mutable_image_props_.target_channel
             << ", download channel = " << download_channel_;
-  if (!IsValidChannel(new_target_channel)) {
-    string valid_channels = brillo::string_utils::JoinRange(
-        ", ",
-        std::begin(kChannelsByStability),
-        std::end(kChannelsByStability));
-    if (error_message) {
-      *error_message = base::StringPrintf(
-          "Invalid channel name \"%s\", valid names are: %s",
-          new_target_channel.c_str(), valid_channels.c_str());
-    }
+  if (!IsValidChannel(new_target_channel, error_message)) {
     return false;
   }
 
@@ -191,8 +182,31 @@
   return ret;
 }
 
-bool OmahaRequestParams::IsValidChannel(const string& channel) const {
-  return image_props_.allow_arbitrary_channels || GetChannelIndex(channel) >= 0;
+bool OmahaRequestParams::IsValidChannel(const string& channel,
+                                        string* error_message) const {
+  if (image_props_.allow_arbitrary_channels) {
+    if (!base::EndsWith(channel, "-channel", base::CompareCase::SENSITIVE)) {
+      if (error_message) {
+        *error_message = base::StringPrintf(
+            "Invalid channel name \"%s\", must ends with -channel.",
+            channel.c_str());
+      }
+      return false;
+    }
+    return true;
+  }
+  if (GetChannelIndex(channel) < 0) {
+    string valid_channels = brillo::string_utils::JoinRange(
+        ", ", std::begin(kChannelsByStability), std::end(kChannelsByStability));
+    if (error_message) {
+      *error_message =
+          base::StringPrintf("Invalid channel name \"%s\", valid names are: %s",
+                             channel.c_str(),
+                             valid_channels.c_str());
+    }
+    return false;
+  }
+  return true;
 }
 
 void OmahaRequestParams::set_root(const string& root) {
@@ -212,6 +226,11 @@
   int current_channel_index = GetChannelIndex(image_props_.current_channel);
   int download_channel_index = GetChannelIndex(download_channel_);
 
+  // If any of the two channels are arbitrary channels, stability is unknown, so
+  // always powerwash if allowed.
+  if (current_channel_index < 0 || download_channel_index < 0)
+    return true;
+
   return download_channel_index > current_channel_index;
 }
 
diff --git a/omaha_request_params.h b/omaha_request_params.h
index 9e41716..6284ee1 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -259,8 +259,13 @@
   FRIEND_TEST(OmahaRequestParamsTest, SetTargetChannelInvalidTest);
   FRIEND_TEST(OmahaRequestParamsTest, ToMoreStableChannelFlagTest);
 
-  // Returns true if |channel| is a valid channel, false otherwise.
-  bool IsValidChannel(const std::string& channel) const;
+  // Returns true if |channel| is a valid channel, otherwise write error to
+  // |error_message| if passed and return false.
+  bool IsValidChannel(const std::string& channel,
+                      std::string* error_message) const;
+  bool IsValidChannel(const std::string& channel) const {
+    return IsValidChannel(channel, nullptr);
+  }
 
   // Returns the index of the given channel.
   int GetChannelIndex(const std::string& channel) const;
diff --git a/omaha_request_params_unittest.cc b/omaha_request_params_unittest.cc
index 6705c71..2de45de 100644
--- a/omaha_request_params_unittest.cc
+++ b/omaha_request_params_unittest.cc
@@ -170,6 +170,8 @@
   EXPECT_FALSE(params_.IsValidChannel(""));
   params_.image_props_.allow_arbitrary_channels = true;
   EXPECT_TRUE(params_.IsValidChannel("some-channel"));
+  EXPECT_FALSE(params_.IsValidChannel("wrong-suffix"));
+  EXPECT_FALSE(params_.IsValidChannel(""));
 }
 
 TEST_F(OmahaRequestParamsTest, SetTargetChannelWorks) {
@@ -231,6 +233,12 @@
   params_.image_props_.current_channel = "canary-channel";
   params_.download_channel_ = "stable-channel";
   EXPECT_TRUE(params_.to_more_stable_channel());
+  params_.image_props_.current_channel = "stable-channel";
+  EXPECT_FALSE(params_.to_more_stable_channel());
+  params_.download_channel_ = "beta-channel";
+  EXPECT_FALSE(params_.to_more_stable_channel());
+  params_.download_channel_ = "some-channel";
+  EXPECT_TRUE(params_.to_more_stable_channel());
 }
 
 TEST_F(OmahaRequestParamsTest, CollectECFWVersionsTest) {