Allow arbitrary channels in Android.

Add a new image property allow_arbitrary_channels which is true on
Android and false on Chrome OS.

Bug: 72259103
Test: adb shell update_engine_client --channel=foo-channel
Change-Id: I70a0980fd877ee32d6152595f8d4462bf43254a2
diff --git a/image_properties.h b/image_properties.h
index f8fe095..49fe82f 100644
--- a/image_properties.h
+++ b/image_properties.h
@@ -58,6 +58,10 @@
   // The release channel this image was obtained from.
   std::string current_channel;
 
+  // Whether we allow arbitrary channels instead of just the ones listed in
+  // kChannelsByStability.
+  bool allow_arbitrary_channels = false;
+
   // The Omaha URL this image should get updates from.
   std::string omaha_url;
 };
diff --git a/image_properties_android.cc b/image_properties_android.cc
index 6e743f9..fa25683 100644
--- a/image_properties_android.cc
+++ b/image_properties_android.cc
@@ -201,6 +201,7 @@
       !system_state->prefs()->GetString(current_channel_key, &current_channel))
     current_channel = GetTargetChannel();
   result.current_channel = current_channel;
+  result.allow_arbitrary_channels = true;
 
   // Brillo only supports the official omaha URL.
   result.omaha_url = constants::kOmahaDefaultProductionURL;
diff --git a/image_properties_chromeos.cc b/image_properties_chromeos.cc
index 39ddeb3..87c32f0 100644
--- a/image_properties_chromeos.cc
+++ b/image_properties_chromeos.cc
@@ -118,6 +118,7 @@
                            constants::kOmahaDefaultProductionURL);
   // Build fingerprint not used in Chrome OS.
   result.build_fingerprint = "";
+  result.allow_arbitrary_channels = false;
 
   return result;
 }
diff --git a/omaha_request_params.cc b/omaha_request_params.cc
index 3ba7037..641032b 100644
--- a/omaha_request_params.cc
+++ b/omaha_request_params.cc
@@ -192,7 +192,7 @@
 }
 
 bool OmahaRequestParams::IsValidChannel(const string& channel) const {
-  return GetChannelIndex(channel) >= 0;
+  return image_props_.allow_arbitrary_channels || GetChannelIndex(channel) >= 0;
 }
 
 void OmahaRequestParams::set_root(const string& root) {
diff --git a/omaha_request_params.h b/omaha_request_params.h
index 73edd6f..9e41716 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -253,10 +253,11 @@
   }
 
  private:
-  FRIEND_TEST(OmahaRequestParamsTest, IsValidChannelTest);
   FRIEND_TEST(OmahaRequestParamsTest, ChannelIndexTest);
-  FRIEND_TEST(OmahaRequestParamsTest, ToMoreStableChannelFlagTest);
   FRIEND_TEST(OmahaRequestParamsTest, CollectECFWVersionsTest);
+  FRIEND_TEST(OmahaRequestParamsTest, IsValidChannelTest);
+  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;
diff --git a/omaha_request_params_unittest.cc b/omaha_request_params_unittest.cc
index 57ecf24..6705c71 100644
--- a/omaha_request_params_unittest.cc
+++ b/omaha_request_params_unittest.cc
@@ -145,6 +145,7 @@
     params.set_root(tempdir_.GetPath().value());
     SetLockDown(true);
     EXPECT_TRUE(params.Init("", "", false));
+    params.image_props_.allow_arbitrary_channels = false;
     string error_message;
     EXPECT_FALSE(
         params.SetTargetChannel("dogfood-channel", true, &error_message));
@@ -167,6 +168,8 @@
   EXPECT_FALSE(params_.IsValidChannel("dogfood-channel"));
   EXPECT_FALSE(params_.IsValidChannel("some-channel"));
   EXPECT_FALSE(params_.IsValidChannel(""));
+  params_.image_props_.allow_arbitrary_channels = true;
+  EXPECT_TRUE(params_.IsValidChannel("some-channel"));
 }
 
 TEST_F(OmahaRequestParamsTest, SetTargetChannelWorks) {