Add new telecom metrics for emergency dialer

These includes,
1. The source where user initiated the call.
2. The duration between START_CONNECTION and REQUEST_DISCONNECT.

Bug: 111818008
Test: manual and check the result of
'adb shell dumpsys telecom' for metrics data
Change-Id: I7d57ac29ad4bb6c8506b7a37b2f1bc63253fa9cb
diff --git a/proto/telecom.proto b/proto/telecom.proto
index 9fd64db..5539f7f 100644
--- a/proto/telecom.proto
+++ b/proto/telecom.proto
@@ -145,6 +145,7 @@
     BLOCK_CHECK_FINISHED_TIMING = 9;
     FILTERING_COMPLETED_TIMING = 10;
     FILTERING_TIMED_OUT_TIMING = 11;
+    START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING = 12;
   }
 
   // The name of the event timing.
@@ -230,6 +231,18 @@
     CONNECTION_MANAGER_NOT_SUPPORTED = 10;
   }
 
+  // The source where user initiated this call.
+  enum CallSource {
+    // Call source is not specified.
+    CALL_SOURCE_UNSPECIFIED = 0;
+
+    // Dialpad at emergency dialer.
+    CALL_SOURCE_EMERGENCY_DIALPAD = 1;
+
+    // Shortcut button at emergency dialer.
+    CALL_SOURCE_EMERGENCY_SHORTCUT = 2;
+  }
+
   // Start time of the connection.
   // Rounded to the nearest 5 minute interval.
   optional int64 start_time_5min = 1;
@@ -283,4 +296,7 @@
   // A bitmask of the properties that were set at any point during the call.
   // Bits are defined by android.telecom.Connection.PROPERTY_* constants.
   optional int32 connection_properties = 17;
+
+  // Call source.
+  optional CallSource call_source = 18;
 }
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index c7b8afd..d524c10 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -141,6 +141,9 @@
                         ParcelableCallAnalytics.EventTiming.FILTERING_COMPLETED_TIMING);
                 put(LogUtils.Events.Timings.FILTERING_TIMED_OUT_TIMING,
                         ParcelableCallAnalytics.EventTiming.FILTERING_TIMED_OUT_TIMING);
+                put(LogUtils.Events.Timings.START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING,
+                        ParcelableCallAnalytics.EventTiming.
+                                START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING);
             }};
 
     public static final Map<Integer, String> sSessionIdToLogSession = new HashMap<>();
@@ -192,6 +195,9 @@
 
         public void addCallProperties(int properties) {
         }
+
+        public void setCallSource(int callSource) {
+        }
     }
 
     /**
@@ -225,6 +231,7 @@
         public List<TelecomLogClass.VideoEvent> videoEvents;
         public List<TelecomLogClass.InCallServiceInfo> inCallServiceInfos;
         public int callProperties = 0;
+        public int callSource = CALL_SOURCE_UNSPECIFIED;
 
         private long mTimeOfLastVideoEvent = -1;
 
@@ -254,6 +261,7 @@
             this.isVideo = other.isVideo;
             this.videoEvents = other.videoEvents;
             this.callProperties = other.callProperties;
+            this.callSource = other.callSource;
 
             if (other.callTerminationReason != null) {
                 this.callTerminationReason = new DisconnectCause(
@@ -363,6 +371,11 @@
         }
 
         @Override
+        public void setCallSource(int callSource) {
+            this.callSource = callSource;
+        }
+
+        @Override
         public String toString() {
             return "{\n"
                     + "    startTime: " + startTime + '\n'
@@ -378,6 +391,7 @@
                     + "    inCallServices: " + getInCallServicesString() + '\n'
                     + "    callProperties: " + Connection.propertiesToStringShort(callProperties)
                     + '\n'
+                    + "    callSource: " + getCallSourceString() + '\n'
                     + "}\n";
         }
 
@@ -420,6 +434,8 @@
                             videoEventProto.getVideoState())
                     ).collect(Collectors.toList()));
 
+            result.setCallSource(analyticsProto.getCallSource());
+
             return result;
         }
 
@@ -446,7 +462,8 @@
                     .setIsCreatedFromExistingConnection(createdFromExistingConnection)
                     .setIsEmergencyCall(isEmergency)
                     .setIsVideoCall(isVideo)
-                    .setConnectionProperties(callProperties);
+                    .setConnectionProperties(callProperties)
+                    .setCallSource(callSource);
 
             result.connectionService = new String[] {connectionService};
             if (callEvents != null) {
@@ -510,6 +527,19 @@
             s.append("]");
             return s.toString();
         }
+
+        private String getCallSourceString() {
+            switch (callSource) {
+                case CALL_SOURCE_UNSPECIFIED:
+                    return "UNSPECIFIED";
+                case CALL_SOURCE_EMERGENCY_DIALPAD:
+                    return "EMERGENCY_DIALPAD";
+                case CALL_SOURCE_EMERGENCY_SHORTCUT:
+                    return "EMERGENCY_SHORTCUT";
+                default:
+                    return "UNSPECIFIED";
+            }
+        }
     }
     public static final String TAG = "TelecomAnalytics";
 
@@ -525,6 +555,14 @@
     public static final int SIP_PHONE = ParcelableCallAnalytics.SIP_PHONE;
     public static final int THIRD_PARTY_PHONE = ParcelableCallAnalytics.THIRD_PARTY_PHONE;
 
+    // Constants for call source
+    public static final int CALL_SOURCE_UNSPECIFIED =
+            ParcelableCallAnalytics.CALL_SOURCE_UNSPECIFIED;
+    public static final int CALL_SOURCE_EMERGENCY_DIALPAD =
+            ParcelableCallAnalytics.CALL_SOURCE_EMERGENCY_DIALPAD;
+    public static final int CALL_SOURCE_EMERGENCY_SHORTCUT =
+            ParcelableCallAnalytics.CALL_SOURCE_EMERGENCY_SHORTCUT;
+
     // Constants for video events
     public static final int SEND_LOCAL_SESSION_MODIFY_REQUEST =
             ParcelableCallAnalytics.VideoEvent.SEND_LOCAL_SESSION_MODIFY_REQUEST;
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 941259b..e078dee 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -1287,6 +1287,7 @@
             }
         }
         setIntentExtrasAndStartTime(call, extras);
+        setCallSourceToAnalytics(call, originalIntent);
 
         if ((isPotentialMMICode(handle) || isPotentialInCallMMICode) && !needsAccountSelection) {
             // Do not add the call if it is a potential MMI code.
@@ -3469,6 +3470,18 @@
         call.setIntentExtras(extras);
     }
 
+    private void setCallSourceToAnalytics(Call call, Intent originalIntent) {
+        if (originalIntent == null) {
+            return;
+        }
+
+        int callSource = originalIntent.getIntExtra(TelecomManager.EXTRA_CALL_SOURCE,
+                Analytics.CALL_SOURCE_UNSPECIFIED);
+
+        // Call source is only used by metrics, so we simply set it to Analytics directly.
+        call.getAnalytics().setCallSource(callSource);
+    }
+
     /**
      * Notifies the {@link android.telecom.ConnectionService} associated with a
      * {@link PhoneAccountHandle} that the attempt to create a new connection has failed.
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index 388ac95..4e966f0 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -151,6 +151,8 @@
             public static final String BLOCK_CHECK_FINISHED_TIMING = "block_check_finished";
             public static final String FILTERING_COMPLETED_TIMING = "filtering_completed";
             public static final String FILTERING_TIMED_OUT_TIMING = "filtering_timed_out";
+            public static final String START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING =
+                    "start_connection_to_request_disconnect";
 
             private static final TimedEventPair[] sTimedEvents = {
                     new TimedEventPair(REQUEST_ACCEPT, SET_ACTIVE, ACCEPT_TIMING),
@@ -171,6 +173,8 @@
                             FILTERING_COMPLETED_TIMING),
                     new TimedEventPair(FILTERING_INITIATED, FILTERING_TIMED_OUT,
                             FILTERING_TIMED_OUT_TIMING, 6000L),
+                    new TimedEventPair(START_CONNECTION, REQUEST_DISCONNECT,
+                            START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING),
             };
         }
     }