Allow timeouts to be configurable

Read the various timeouts from Settings so that they can be configured
and tuned at runtime (instead of baking them into the source code).

Bug: 13329970

Change-Id: I0113d171b5f5098305dff89e86eee8ad11939c27
diff --git a/src/com/android/telecomm/CallServiceRepository.java b/src/com/android/telecomm/CallServiceRepository.java
index 5567e51..6cd7a9d 100644
--- a/src/com/android/telecomm/CallServiceRepository.java
+++ b/src/com/android/telecomm/CallServiceRepository.java
@@ -52,13 +52,6 @@
 
     private static final String TAG = CallServiceRepository.class.getSimpleName();
 
-    /**
-     * The longest period in milliseconds each lookup cycle is allowed to span over, see
-     * {@link #mLookupTerminator}.
-     * TODO(gilad): Likely requires tuning.
-     */
-    private static final int LOOKUP_TIMEOUT_MS = 100;
-
     private final Switchboard mSwitchboard;
 
     private final OutgoingCallsManager mOutgoingCallsManager;
@@ -70,7 +63,7 @@
 
     /**
      * Used to interrupt lookup cycles that didn't terminate naturally within the allowed
-     * period, see LOOKUP_TIMEOUT_MS.
+     * period, see {@link Timeouts#getProviderLookupMs()}.
      */
     private final Runnable mLookupTerminator = new Runnable() {
         @Override
@@ -158,8 +151,8 @@
         Log.i(TAG, "Found " + mOutstandingProviders.size() +
                 " implementations of ICallServiceProvider.");
 
-        // Schedule a lookup terminator to run after LOOKUP_TIMEOUT_MS milliseconds.
-        mHandler.postDelayed(mLookupTerminator, LOOKUP_TIMEOUT_MS);
+        // Schedule a lookup terminator to run after Timeouts.getProviderLookupMs() milliseconds.
+        mHandler.postDelayed(mLookupTerminator, Timeouts.getProviderLookupMs());
     }
 
     /**
diff --git a/src/com/android/telecomm/CallServiceSelectorRepository.java b/src/com/android/telecomm/CallServiceSelectorRepository.java
index 13249c5..1935e25 100644
--- a/src/com/android/telecomm/CallServiceSelectorRepository.java
+++ b/src/com/android/telecomm/CallServiceSelectorRepository.java
@@ -46,13 +46,6 @@
     private static final String TAG = CallServiceSelectorRepository.class.getSimpleName();
 
     /**
-     * The longest period in milliseconds each lookup cycle is allowed to span over, see
-     * {@link #mLookupTerminator}.
-     * TODO(gilad): Likely requires tuning.
-     */
-    private static final int LOOKUP_TIMEOUT_MS = 100;
-
-    /**
      * Used to retrieve all known ICallServiceSelector implementations from the framework.
      */
     private static final String CALL_SERVICE_SELECTOR_CLASS_NAME =
@@ -60,7 +53,7 @@
 
     /**
      * Used to interrupt lookup cycles that didn't terminate naturally within the allowed
-     * period, see LOOKUP_TIMEOUT.
+     * period, see {@link Timeouts#getSelectorLookupMs()}.
      */
     private final Runnable mLookupTerminator = new Runnable() {
         @Override
@@ -158,9 +151,10 @@
             // back to the switchboard.
             updateSwitchboard();
         } else {
-            // Schedule a lookup terminator to run after LOOKUP_TIMEOUT_MS milliseconds.
+            // Schedule a lookup terminator to run after Timeouts.getSelectorLookupMs()
+            // milliseconds.
             mHandler.removeCallbacks(mLookupTerminator);
-            mHandler.postDelayed(mLookupTerminator, LOOKUP_TIMEOUT_MS);
+            mHandler.postDelayed(mLookupTerminator, Timeouts.getSelectorLookupMs());
         }
     }
 
diff --git a/src/com/android/telecomm/Switchboard.java b/src/com/android/telecomm/Switchboard.java
index a9889c5..bb40ef6 100644
--- a/src/com/android/telecomm/Switchboard.java
+++ b/src/com/android/telecomm/Switchboard.java
@@ -41,17 +41,6 @@
 final class Switchboard {
 
     private final static String TAG = Switchboard.class.getSimpleName();
-    /**
-     * The frequency of invoking tick in milliseconds.
-     * TODO(gilad): May require tuning.
-     */
-    private final static int TICK_FREQUENCY_MS = 250;
-
-    /**
-     * The timeout beyond which to drop ongoing attempts to place/receive calls.
-     * TODO(gilad): May require tuning.
-     */
-    private final static int NEW_CALL_TIMEOUT_MS = 5000;
 
     private final CallsManager mCallsManager;
 
@@ -276,7 +265,7 @@
      * Schedules the next tick invocation.
      */
     private void scheduleNextTick() {
-         mHandler.postDelayed(mTicker, TICK_FREQUENCY_MS);
+         mHandler.postDelayed(mTicker, Timeouts.getTickMs());
     }
 
     /**
@@ -346,10 +335,11 @@
             return;
         }
 
+        final long newCallTimeoutMs = Timeouts.getNewOutgoingCallMs();
         Iterator<Call> iterator = calls.iterator();
         while (iterator.hasNext()) {
             Call call = iterator.next();
-            if (call.getAgeInMilliseconds() >= NEW_CALL_TIMEOUT_MS) {
+            if (call.getAgeInMilliseconds() >= newCallTimeoutMs) {
                 mOutgoingCallsManager.abort(call);
                 calls.remove(call);
 
diff --git a/src/com/android/telecomm/Timeouts.java b/src/com/android/telecomm/Timeouts.java
new file mode 100644
index 0000000..a69319d
--- /dev/null
+++ b/src/com/android/telecomm/Timeouts.java
@@ -0,0 +1,67 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+
+package com.android.telecomm;
+
+import android.provider.Settings;
+import android.telecomm.CallServiceProvider;
+import android.telecomm.CallServiceSelector;
+
+/**
+ * A helper class which serves only to make it easier to lookup timeout values. This class should
+ * never be instantiated, and only accessed through the {@link #get(String, long)} method.
+ *
+ * These methods are safe to call from any thread, including the UI thread.
+ */
+public final class Timeouts {
+    /** A prefix to use for all keys so to not clobber the global namespace. */
+    private static final String PREFIX = "telecomm.";
+
+    private Timeouts() {}
+
+    /**
+     * Returns the timeout value from Settings or the default value if it hasn't been changed. This
+     * method is safe to call from any thread, including the UI thread.
+     *
+     * @param key Settings key to retrieve.
+     * @param defaultValue Default value, in milliseconds.
+     * @return The timeout value from Settings or the default value if it hasn't been changed.
+     */
+    private static long get(String key, long defaultValue) {
+        return Settings.Secure.getLong(
+                TelecommApp.getInstance().getContentResolver(), PREFIX + key, defaultValue);
+    }
+
+    /**
+     * @return The longest period in milliseconds each {@link CallServiceProvider} lookup cycle is
+     *     allowed to span over.
+     */
+    public static long getProviderLookupMs() {
+        return get("provider_lookup_ms", 100);
+    }
+
+    /**
+     * @return The longest period in milliseconds each {@link CallServiceSelector} lookup cycle is
+     *     allowed to span over.
+     */
+    public static long getSelectorLookupMs() {
+        return get("selector_lookup_ms", 100);
+    }
+
+    /**
+     * @return How frequently, in milliseconds, to run {@link Switchboard}'s clean-up "tick" cycle.
+     */
+    public static long getTickMs() {
+        return get("tick_ms", 250);
+    }
+
+    /**
+     * Returns the longest period, in milliseconds, each new outgoing call is allowed to wait before
+     * being established. If the call does not connect before this time, abort the call.
+     *
+     * @return The longest period, in milliseconds, each new call is allowed to wait before being
+     *     established.
+     */
+    public static long getNewOutgoingCallMs() {
+        return get("new_outgoing_call_ms", 5000);
+    }
+}