arc: Add native_bridge_64bit_support_experiment

Add an experiment flag to enable 64-bit native bridge for ARC on
systems that have 64-bit native bridge support available but not
enabled.

Note that due to the nature of the timing of starting ARC mini-
container - which can be affected by the properties controlled by
this experiment - and user login, the experiment is treated as a one
way off->on transition for all users on a given device.

The experiment flag will have no effect on systems that do not have
64-bit native support available, nor will it affect systems that
have 64-bit native support enabled generally.

Bug: b:62095998
Change-Id: If2a5dc96ba36f8aba31405122a6de20764af30b9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2252956
Commit-Queue: Josh Horwich <[email protected]>
Reviewed-by: Yusuke Sato <[email protected]>
Cr-Commit-Position: refs/heads/master@{#786022}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 2b0459bf..cc6920f 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3226,6 +3226,11 @@
     {"arc-native-bridge-toggle", flag_descriptions::kArcNativeBridgeToggleName,
      flag_descriptions::kArcNativeBridgeToggleDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(arc::kNativeBridgeToggleFeature)},
+    {"arc-native-bridge-64bit-support-experiment",
+     flag_descriptions::kArcNativeBridge64BitSupportExperimentName,
+     flag_descriptions::kArcNativeBridge64BitSupportExperimentDescription,
+     kOsCrOS,
+     FEATURE_VALUE_TYPE(arc::kNativeBridge64BitSupportExperimentFeature)},
     {"arc-usb-host", flag_descriptions::kArcUsbHostName,
      flag_descriptions::kArcUsbHostDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(arc::kUsbHostFeature)},
diff --git a/chrome/browser/chromeos/arc/session/arc_session_manager.cc b/chrome/browser/chromeos/arc/session/arc_session_manager.cc
index 908926b..906f2bb 100644
--- a/chrome/browser/chromeos/arc/session/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/session/arc_session_manager.cc
@@ -22,6 +22,7 @@
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/arc/arc_migration_guide_notification.h"
 #include "chrome/browser/chromeos/arc/arc_optin_uma.h"
 #include "chrome/browser/chromeos/arc/arc_support_host.h"
@@ -214,8 +215,10 @@
 
 bool ExpandPropertyFilesInternal(const base::FilePath& source_path,
                                  const base::FilePath& dest_path,
-                                 bool single_file) {
-  if (!arc::ExpandPropertyFiles(source_path, dest_path, single_file))
+                                 bool single_file,
+                                 bool add_native_bridge_64bit_support) {
+  if (!arc::ExpandPropertyFiles(source_path, dest_path, single_file,
+                                add_native_bridge_64bit_support))
     return false;
   if (!arc::IsArcVmEnabled())
     return true;
@@ -1333,12 +1336,29 @@
   // For ARCVM, generate <dest_path>/{combined.prop,fstab}. For ARC, generate
   // <dest_path>/{default,build,vendor_build}.prop.
   const bool is_arcvm = arc::IsArcVmEnabled();
+  bool add_native_bridge_64bit_support = false;
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          chromeos::switches::kArcEnableNativeBridge64BitSupportExperiment)) {
+    PrefService* local_pref_service = g_browser_process->local_state();
+    if (base::FeatureList::IsEnabled(
+            arc::kNativeBridge64BitSupportExperimentFeature)) {
+      // Note that we treat this experiment as a one-way off->on switch, across
+      // all users of the device, as the lifetime of ARC mini-container and user
+      // sessions are different in different scenarios, and removing the
+      // experiment after it has been in effect for a user's ARC instance can
+      // lead to unexpected, and unsupported, results.
+      local_pref_service->SetBoolean(
+          prefs::kNativeBridge64BitSupportExperimentEnabled, true);
+    }
+    add_native_bridge_64bit_support = local_pref_service->GetBoolean(
+        prefs::kNativeBridge64BitSupportExperimentEnabled);
+  }
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&ExpandPropertyFilesInternal, property_files_source_dir_,
                      is_arcvm ? property_files_dest_dir_.Append("combined.prop")
                               : property_files_dest_dir_,
-                     /*single_file=*/is_arcvm),
+                     /*single_file=*/is_arcvm, add_native_bridge_64bit_support),
       base::BindOnce(&ArcSessionManager::OnExpandPropertyFiles,
                      weak_ptr_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 1cce9b4..ae371b7 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -184,6 +184,13 @@
     "expiry_milestone": 76
   },
   {
+    "name": "arc-native-bridge-64bit-support-experiment",
+    "owners": [ "jhorwich" ],
+    // Used on ChromeOS to experimentally enable 64-bit ARC native-bridge
+    // support before promoting it to enabled on a specific device class.
+    "expiry_milestone": 93
+  },
+  {
     "name": "arc-native-bridge-toggle",
     "owners": [ "[email protected]" ],
     // Used on ChromeOS to compare and debug different ARC native-bridge
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 262554a55..4eec203 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3325,6 +3325,11 @@
 const char kArcNativeBridgeToggleDescription[] =
     "Toggle between native bridge implementations for ARC.";
 
+const char kArcNativeBridge64BitSupportExperimentName[] =
+    "Enable experimental 64-bit native bridge support for ARC";
+const char kArcNativeBridge64BitSupportExperimentDescription[] =
+    "Enable experimental 64-bit native bridge support for ARC where available.";
+
 const char kArcUsbHostName[] = "Enable ARC USB host integration";
 const char kArcUsbHostDescription[] =
     "Allow Android apps to use USB host feature on ChromeOS devices.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index bfe4dff..6616f270 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1921,6 +1921,9 @@
 extern const char kArcNativeBridgeToggleName[];
 extern const char kArcNativeBridgeToggleDescription[];
 
+extern const char kArcNativeBridge64BitSupportExperimentName[];
+extern const char kArcNativeBridge64BitSupportExperimentDescription[];
+
 extern const char kArcUsbHostName[];
 extern const char kArcUsbHostDescription[];