[CrOS MultiDevice] Add metrics for feature states.

MultiDevice.BetterTogetherSuite.MultiDeviceFeatureState
AndroidSms.MultiDeviceFeatureState
SmartLock.MultiDeviceFeatureState
InstantTethering.MultiDeviceFeatureState

Multiple enumerated histograms with the same 9 buckets:
1) “Prohibited by policy”,
2) “Disabled by user”,
3) “Enabled by user”,
4) “Not supported by Chromebook”,
5) “Not supported by phone”,
6) “Unavailable, no verified host”,
7) “Unavailable, insufficient security”,
8) “Unavailable, suite disabled”, and
9) “Further setup required”.

Bug: 870138
Change-Id: Ic96b673a10b4ecd52b9f44b0f29abc52d29858b3
Reviewed-on: https://chromium-review.googlesource.com/c/1315938
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: Ryan Hansberry <hansberry@chromium.org>
Reviewed-by: Steven Holte <holte@chromium.org>
Commit-Queue: Regan Hsu <hsuregan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607804}
diff --git a/chromeos/services/multidevice_setup/feature_state_manager_impl.cc b/chromeos/services/multidevice_setup/feature_state_manager_impl.cc
index dee8d27..e38cbd3 100644
--- a/chromeos/services/multidevice_setup/feature_state_manager_impl.cc
+++ b/chromeos/services/multidevice_setup/feature_state_manager_impl.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
@@ -92,6 +93,50 @@
   }
 }
 
+bool HasFeatureStateChanged(
+    const base::Optional<FeatureStateManager::FeatureStatesMap>&
+        previous_states,
+    const FeatureStateManager::FeatureStatesMap& new_states,
+    mojom::Feature feature) {
+  if (!previous_states)
+    return true;
+  return previous_states->find(feature)->second !=
+         new_states.find(feature)->second;
+}
+
+void LogFeatureStates(
+    const base::Optional<FeatureStateManager::FeatureStatesMap>&
+        previous_states,
+    const FeatureStateManager::FeatureStatesMap& new_states) {
+  if (HasFeatureStateChanged(previous_states, new_states,
+                             mojom::Feature::kBetterTogetherSuite)) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "MultiDevice.BetterTogetherSuite.MultiDeviceFeatureState",
+        new_states.find(mojom::Feature::kBetterTogetherSuite)->second);
+  }
+
+  if (HasFeatureStateChanged(previous_states, new_states,
+                             mojom::Feature::kInstantTethering)) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "InstantTethering.MultiDeviceFeatureState",
+        new_states.find(mojom::Feature::kInstantTethering)->second);
+  }
+
+  if (HasFeatureStateChanged(previous_states, new_states,
+                             mojom::Feature::kMessages)) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "AndroidSms.MultiDeviceFeatureState",
+        new_states.find(mojom::Feature::kMessages)->second);
+  }
+
+  if (HasFeatureStateChanged(previous_states, new_states,
+                             mojom::Feature::kSmartLock)) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "SmartLock.MultiDeviceFeatureState",
+        new_states.find(mojom::Feature::kSmartLock)->second);
+  }
+}
+
 }  // namespace
 
 // static
@@ -167,6 +212,9 @@
   // represent a true change of feature state values, so observers should not be
   // notified.
   UpdateFeatureStateCache(false /* notify_observers_of_changes */);
+
+  LogFeatureStates(base::nullopt /* previous_states */,
+                   cached_feature_state_map_ /* new_states */);
 }
 
 FeatureStateManagerImpl::~FeatureStateManagerImpl() {
@@ -228,6 +276,8 @@
   PA_LOG(VERBOSE) << "Feature states map changed. Old map: "
                   << previous_cached_feature_state_map
                   << ", new map: " << cached_feature_state_map_;
+  LogFeatureStates(previous_cached_feature_state_map /* previous_states */,
+                   cached_feature_state_map_ /* new_states */);
   NotifyFeatureStatesChange(cached_feature_state_map_);
 }
 
diff --git a/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom b/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom
index 94e32b2..dcc9520 100644
--- a/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom
+++ b/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom
@@ -50,39 +50,42 @@
   kSmartLock
 };
 
+// This enum is tied directly to a UMA enum defined in
+// //tools/metrics/histograms/enums.xml, and should always reflect it (do not
+// change one without changing the other).
 enum FeatureState {
   // Feature was prohibited by a device policy (e.g., EDU or Enterprise).
-  kProhibitedByPolicy,
+  kProhibitedByPolicy = 0,
 
   // Feature was disabled by the user (i.e., via settings).
-  kDisabledByUser,
+  kDisabledByUser = 1,
 
   // Feature was enabled by the user (i.e., via settings).
-  kEnabledByUser,
+  kEnabledByUser = 2,
 
   // Feature is not supported by this Chromebook.
-  kNotSupportedByChromebook,
+  kNotSupportedByChromebook = 3,
 
   // Feature is not supported by the current host phone device.
-  kNotSupportedByPhone,
+  kNotSupportedByPhone = 4,
 
   // The feature is unavailable because there is no verified multi-device host.
   // To set a host, use SetHostDevice(); to verify a host, use
   // RetrySetHostNow().
-  kUnavailableNoVerifiedHost,
+  kUnavailableNoVerifiedHost = 5,
 
   // The feature is unavailable because there are insufficient security
   // mechanisms in place (e.g., Smart Lock returns this value when the host
   // phone device does not have a lock screen set).
-  kUnavailableInsufficientSecurity,
+  kUnavailableInsufficientSecurity = 6,
 
   // The feature has been enabled by the user, but it is still unavailable
   // because the entire Better Together suite has been disabled by the user.
-  kUnavailableSuiteDisabled,
+  kUnavailableSuiteDisabled = 7,
 
   // The feature still requires further setup to be ready for use (e.g., Android
   // Messages requires a separate pairing flow after unified setup).
-  kFurtherSetupRequired,
+  kFurtherSetupRequired = 8,
 };
 
 interface AccountStatusChangeDelegate {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 0f93278..3ffdc898 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -33993,6 +33993,18 @@
   <int value="1" label="Service not ready"/>
 </enum>
 
+<enum name="MultiDevice_FeatureState">
+  <int value="0" label="Prohibited by policy"/>
+  <int value="1" label="Disabled by user"/>
+  <int value="2" label="Enabled by user"/>
+  <int value="3" label="Not support by Chromebook"/>
+  <int value="4" label="Not supported by phone"/>
+  <int value="5" label="Unable, no verified host"/>
+  <int value="6" label="Unavailable, insufficient security"/>
+  <int value="7" label="Unavailable, suite disabled"/>
+  <int value="8" label="Further setup required"/>
+</enum>
+
 <enum name="MultiDevice_PostOOBESetupFlow_Page">
   <int value="0" label="Unknown page"/>
   <int value="1" label="Start page"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c46461f..1af38ed 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -2800,6 +2800,16 @@
   </summary>
 </histogram>
 
+<histogram name="AndroidSms.MultiDeviceFeatureState"
+    enum="MultiDevice_FeatureState">
+  <owner>jlklein@chromium.org</owner>
+  <summary>
+    Indicates the feature state of the Messages feature. This metric is emitted
+    to at the creation of the user session (when the user logs in), and when
+    feature state updates occur.
+  </summary>
+</histogram>
+
 <histogram name="AndroidSms.PWAInstallationResult"
     enum="WebAppInstallResultCode">
   <owner>azeemarshad@chromium.org</owner>
@@ -40431,6 +40441,16 @@
   </summary>
 </histogram>
 
+<histogram name="InstantTethering.MultiDeviceFeatureState"
+    enum="MultiDevice_FeatureState">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Indicates the feature state of the Instant Tethering feature. This metric is
+    emitted to at the creation of the user session (when the user logs in), and
+    when feature state updates occur.
+  </summary>
+</histogram>
+
 <histogram name="InstantTethering.NotificationInteractionType"
     enum="InstantTethering_NotificationInteractionType">
   <owner>hansberry@chromium.org</owner>
@@ -51635,6 +51655,16 @@
   </summary>
 </histogram>
 
+<histogram name="MultiDevice.BetterTogetherSuite.MultiDeviceFeatureState"
+    enum="MultiDevice_FeatureState">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Indicates the feature state of the Better Together Suite feature. This
+    metric is emitted to at the creation of the user session (when the user logs
+    in), and when feature state updates occur.
+  </summary>
+</histogram>
+
 <histogram name="MultiDevice.DeviceSyncService.FindEligibleDevices.Result"
     enum="BooleanSuccess">
   <owner>hansberry@chromium.org</owner>
@@ -104377,6 +104407,16 @@
   </summary>
 </histogram>
 
+<histogram name="SmartLock.MultiDeviceFeatureState"
+    enum="MultiDevice_FeatureState">
+  <owner>hansberry@chromium.org</owner>
+  <summary>
+    Indicates the feature state of the SmartLock feature. This metric is emitted
+    to at the creation of the user session (when the user logs in), and when
+    feature state updates occur.
+  </summary>
+</histogram>
+
 <histogram name="SmartLock.ToggleFeature" enum="BooleanEnabled">
   <owner>jhawkins@chromium.org</owner>
   <summary>