Add query count UMA metric for Assistant.

This metric should be the number of queries fired per each entry point,
e.g. keyboard, OKG, launcher button, longpress applist. This includes
the first query fired immediately after each entry point and follow up
queries before window close.

Test: local compile and manually test.
Bug: b:117517666
Change-Id: I77c906ab95598a1e819f261462c50372c3aa07ea
Reviewed-on: https://chromium-review.googlesource.com/c/1278149
Commit-Queue: Meilin Wang <meilinw@chromium.org>
Reviewed-by: Ilya Sherman <isherman@chromium.org>
Reviewed-by: Xiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600122}
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index a29e52d..477f37c 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -240,6 +240,8 @@
     "assistant/util/assistant_util.h",
     "assistant/util/deep_link_util.cc",
     "assistant/util/deep_link_util.h",
+    "assistant/util/histogram_util.cc",
+    "assistant/util/histogram_util.h",
     "assistant/util/views_util.cc",
     "assistant/util/views_util.h",
     "autoclick/autoclick_controller.cc",
diff --git a/ash/assistant/assistant_interaction_controller.cc b/ash/assistant/assistant_interaction_controller.cc
index 01a8917..1466cb31 100644
--- a/ash/assistant/assistant_interaction_controller.cc
+++ b/ash/assistant/assistant_interaction_controller.cc
@@ -4,7 +4,6 @@
 
 #include "ash/assistant/assistant_interaction_controller.h"
 
-#include <map>
 #include <utility>
 
 #include "ash/assistant/assistant_controller.h"
@@ -16,6 +15,7 @@
 #include "ash/assistant/model/assistant_ui_element.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
 #include "ash/assistant/util/deep_link_util.h"
+#include "ash/assistant/util/histogram_util.h"
 #include "ash/public/interfaces/voice_interaction_controller.mojom.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -226,6 +226,12 @@
   StopActiveInteraction(false);
 }
 
+void AssistantInteractionController::OnResponseChanged(
+    const std::shared_ptr<AssistantResponse>& response) {
+  assistant::util::IncrementAssistantQueryCountForEntryPoint(
+      assistant_controller_->ui_controller()->model()->entry_point());
+}
+
 void AssistantInteractionController::OnResponseDestroying(
     AssistantResponse& response) {
   response.RemoveObserver(this);
@@ -247,6 +253,13 @@
 
 void AssistantInteractionController::OnInteractionStarted(
     bool is_voice_interaction) {
+  if (is_voice_interaction) {
+    // If the Assistant UI is not visible yet, and |is_voice_interaction| is
+    // true, then it will be sure that Assistant is fired via OKG. ShowUi will
+    // not update the Assistant entry point if the UI is already visible.
+    assistant_controller_->ui_controller()->ShowUi(AssistantSource::kHotword);
+  }
+
   model_.SetInteractionState(InteractionState::kActive);
 
   // In the case of a voice interaction, we assume that the mic is open and
diff --git a/ash/assistant/assistant_interaction_controller.h b/ash/assistant/assistant_interaction_controller.h
index 4fc28a3..7756ca4 100644
--- a/ash/assistant/assistant_interaction_controller.h
+++ b/ash/assistant/assistant_interaction_controller.h
@@ -5,6 +5,7 @@
 #ifndef ASH_ASSISTANT_ASSISTANT_INTERACTION_CONTROLLER_H_
 #define ASH_ASSISTANT_ASSISTANT_INTERACTION_CONTROLLER_H_
 
+#include <map>
 #include <memory>
 #include <string>
 #include <vector>
@@ -67,6 +68,8 @@
   // AssistantInteractionModelObserver:
   void OnInteractionStateChanged(InteractionState interaction_state) override;
   void OnInputModalityChanged(InputModality input_modality) override;
+  void OnResponseChanged(
+      const std::shared_ptr<AssistantResponse>& response) override;
 
   // AssistantResponseObserver:
   void OnResponseDestroying(AssistantResponse& response) override;
diff --git a/ash/assistant/assistant_ui_controller.cc b/ash/assistant/assistant_ui_controller.cc
index 2fd1a2b..eed37365 100644
--- a/ash/assistant/assistant_ui_controller.cc
+++ b/ash/assistant/assistant_ui_controller.cc
@@ -104,7 +104,7 @@
 
   // If there is an active interaction, we need to show Assistant UI if it is
   // not already showing. We don't have enough information here to know what
-  // the interaction source is, but at the moment we have no need to know.
+  // the interaction source is.
   ShowUi(AssistantSource::kUnspecified);
 }
 
diff --git a/ash/assistant/model/assistant_ui_model.cc b/ash/assistant/model/assistant_ui_model.cc
index 6374ffe..c46d0d4a 100644
--- a/ash/assistant/model/assistant_ui_model.cc
+++ b/ash/assistant/model/assistant_ui_model.cc
@@ -36,6 +36,10 @@
   const AssistantVisibility old_visibility = visibility_;
   visibility_ = visibility;
 
+  // Cache the Assistant entry point used for query count UMA metric.
+  if (visibility == AssistantVisibility::kVisible)
+    entry_point_ = source;
+
   NotifyUiVisibilityChanged(old_visibility, source);
 }
 
diff --git a/ash/assistant/model/assistant_ui_model.h b/ash/assistant/model/assistant_ui_model.h
index efed31b..93ecfc7 100644
--- a/ash/assistant/model/assistant_ui_model.h
+++ b/ash/assistant/model/assistant_ui_model.h
@@ -13,16 +13,21 @@
 
 class AssistantUiModelObserver;
 
-// Enumeration of Assistant entry/exit points.
+// Enumeration of Assistant entry/exit points, also recorded in histograms.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused. Only append to this enum is allowed
+// if the possible source grows.
 enum class AssistantSource {
-  kUnspecified,
-  kDeepLink,
-  kHotkey,
-  kHotword,
-  kLauncherSearchBox,
-  kLongPressLauncher,
-  kSetup,
-  kStylus,
+  kUnspecified = 0,
+  kDeepLink = 1,
+  kHotkey = 2,
+  kHotword = 3,
+  kLauncherSearchBox = 4,
+  kLongPressLauncher = 5,
+  kSetup = 6,
+  kStylus = 7,
+  // Special enumerator value used by histogram macros.
+  kMaxValue = kStylus
 };
 
 // Enumeration of Assistant UI modes.
@@ -66,6 +71,9 @@
   // Returns the current usable work area.
   const gfx::Rect& usable_work_area() const { return usable_work_area_; }
 
+  // Returns the UI entry point. Only valid while UI is visible.
+  AssistantSource entry_point() const { return entry_point_; }
+
  private:
   void NotifyUiModeChanged();
   void NotifyUiVisibilityChanged(AssistantVisibility old_visibility,
@@ -76,6 +84,8 @@
 
   AssistantVisibility visibility_ = AssistantVisibility::kClosed;
 
+  AssistantSource entry_point_ = AssistantSource::kUnspecified;
+
   base::ObserverList<AssistantUiModelObserver>::Unchecked observers_;
 
   // Usable work area for Assistant. Value is only meaningful when Assistant
diff --git a/ash/assistant/util/histogram_util.cc b/ash/assistant/util/histogram_util.cc
new file mode 100644
index 0000000..6830c48
--- /dev/null
+++ b/ash/assistant/util/histogram_util.cc
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/assistant/util/histogram_util.h"
+
+#include "ash/assistant/model/assistant_ui_model.h"
+#include "base/metrics/histogram_macros.h"
+
+namespace ash {
+namespace assistant {
+namespace util {
+
+void IncrementAssistantQueryCountForEntryPoint(AssistantSource entry_point) {
+  UMA_HISTOGRAM_ENUMERATION("Assistant.QueryCountPerEntryPoint", entry_point);
+}
+
+}  // namespace util
+}  // namespace assistant
+}  // namespace ash
diff --git a/ash/assistant/util/histogram_util.h b/ash/assistant/util/histogram_util.h
new file mode 100644
index 0000000..8381284
--- /dev/null
+++ b/ash/assistant/util/histogram_util.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_ASSISTANT_UTIL_HISTOGRAM_UTIL_H_
+#define ASH_ASSISTANT_UTIL_HISTOGRAM_UTIL_H_
+
+namespace ash {
+
+enum class AssistantSource;
+
+namespace assistant {
+namespace util {
+
+// Increment number of queries fired for each entry point.
+void IncrementAssistantQueryCountForEntryPoint(AssistantSource entry_point);
+
+}  // namespace util
+}  // namespace assistant
+}  // namespace ash
+
+#endif  // ASH_ASSISTANT_UTIL_HISTOGRAM_UTIL_H_
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index e0e2069..de8d6e5 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -1900,6 +1900,17 @@
   <int value="11" label="READY_SCREEN_CONTINUED"/>
 </enum>
 
+<enum name="AssistantSource">
+  <int value="0" label="kUnspecified"/>
+  <int value="1" label="kDeepLink"/>
+  <int value="2" label="kHotkey"/>
+  <int value="3" label="kHotword"/>
+  <int value="4" label="kLauncherSearchBox"/>
+  <int value="5" label="kLongPressLauncher"/>
+  <int value="6" label="kSetup"/>
+  <int value="7" label="kStylus"/>
+</enum>
+
 <enum name="AsyncDNSConfigParsePosix">
   <int value="0" label="OK"/>
   <int value="1" label="RES_INIT_FAILED"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 58334912e..cd446364 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -5324,6 +5324,13 @@
   <summary>Record the status of the Assistant opt-in flow.</summary>
 </histogram>
 
+<histogram name="Assistant.QueryCountPerEntryPoint" enum="AssistantSource"
+    expires_after="2019-10-15">
+  <owner>xiaohuic@chromium.org</owner>
+  <owner>meilinw@chromium.org</owner>
+  <summary>Number of queries fired for each entry point.</summary>
+</histogram>
+
 <histogram name="Assistant.ServiceStartTime" units="ms">
   <owner>updowndota@chromium.org</owner>
   <summary>Amount of time spent in starting Assistant service.</summary>