Adding the basic Telecomm flow components.

Change-Id: I1044d42ba4e05e03a88e858ef0357c2cc788393f
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
new file mode 100644
index 0000000..4f1028d
--- /dev/null
+++ b/src/com/android/telecomm/Call.java
@@ -0,0 +1,4 @@
+package com.android.telecomm;
+
+public class Call {
+}
diff --git a/src/com/android/telecomm/CallLogManager.java b/src/com/android/telecomm/CallLogManager.java
new file mode 100644
index 0000000..eb3b0f5
--- /dev/null
+++ b/src/com/android/telecomm/CallLogManager.java
@@ -0,0 +1,5 @@
+package com.android.telecomm;
+
+/** Package private */
+class CallLogManager {
+}
diff --git a/src/com/android/telecomm/CallService.java b/src/com/android/telecomm/CallService.java
new file mode 100644
index 0000000..72b73a7
--- /dev/null
+++ b/src/com/android/telecomm/CallService.java
@@ -0,0 +1,14 @@
+package com.android.telecomm;
+
+import com.android.telecomm.exceptions.OutgoingCallException;
+
+// TODO(gilad): Move to use the AIDL-based implementation.
+public interface CallService {
+
+  public void setCallServiceAdapter(CallServiceAdapter adapter);
+
+  public boolean isCompatibleWith(String userInput, ContactInfo contactInfo);
+
+  public void placeOutgoingCall(String userInput, ContactInfo contactInfo)
+    throws OutgoingCallException;
+}
diff --git a/src/com/android/telecomm/CallServiceAdapter.java b/src/com/android/telecomm/CallServiceAdapter.java
new file mode 100644
index 0000000..43aab4a
--- /dev/null
+++ b/src/com/android/telecomm/CallServiceAdapter.java
@@ -0,0 +1,16 @@
+package com.android.telecomm;
+
+/**
+ * Only exposes the CallsManager APIs that CallService implementations should
+ * have access to.
+ */
+public class CallServiceAdapter {
+  private CallsManager callsManager;
+
+  private CallService callService;
+
+  /** Package private */
+  CallServiceAdapter(CallsManager callsManager) {
+    this.callsManager = callsManager;
+  }
+}
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
new file mode 100644
index 0000000..99b68bd
--- /dev/null
+++ b/src/com/android/telecomm/CallsManager.java
@@ -0,0 +1,62 @@
+package com.android.telecomm;
+
+import com.android.telecomm.exceptions.CallServiceUnavailableException;
+import com.android.telecomm.exceptions.RestrictedCallException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Singleton */
+public class CallsManager {
+
+  private static final CallsManager INSTANCE = new CallsManager();
+
+  private DialerAdapter dialerAdapter;
+
+  private InCallAdapter inCallAdapter;
+
+  private Switchboard switchboard;
+
+  private CallLogManager callLogManager;
+
+  private VoicemailManager voicemailManager;
+
+  private List<OutgoingCallFilter> outgoingCallFilters =
+      new ArrayList<OutgoingCallFilter>();
+
+  private List<IncomingCallFilter> incomingCallFilters =
+      new ArrayList<IncomingCallFilter>();
+
+  // Singleton, private constructor (see getInstance).
+  private CallsManager() {
+    switchboard = new Switchboard();
+    callLogManager = new CallLogManager();
+    voicemailManager = new VoicemailManager();  // As necessary etc.
+  }
+
+  /** Package private */
+  static CallsManager getInstance() {
+    return INSTANCE;
+  }
+
+  /** Package private */
+  // TODO(gilad): Circle back to how we'd want to do this.
+  void addCallService(CallService callService) {
+    if (callService != null) {
+      switchboard.addCallService(callService);
+      callService.setCallServiceAdapter(new CallServiceAdapter(this));
+    }
+  }
+
+  /** Package private */
+  void connectTo(String userInput, ContactInfo contactInfo)
+      throws RestrictedCallException, CallServiceUnavailableException {
+
+    for (OutgoingCallFilter policy : outgoingCallFilters) {
+      policy.validate(userInput, contactInfo);
+    }
+
+    // No objection to issue the call, proceed with trying to put it through.
+    switchboard.placeOutgoingCall(userInput, contactInfo);
+  }
+}
diff --git a/src/com/android/telecomm/ContactInfo.java b/src/com/android/telecomm/ContactInfo.java
new file mode 100644
index 0000000..649b34d
--- /dev/null
+++ b/src/com/android/telecomm/ContactInfo.java
@@ -0,0 +1,4 @@
+package com.android.telecomm;
+
+public class ContactInfo {
+}
diff --git a/src/com/android/telecomm/DialerAdapter.java b/src/com/android/telecomm/DialerAdapter.java
new file mode 100644
index 0000000..fef3d9f
--- /dev/null
+++ b/src/com/android/telecomm/DialerAdapter.java
@@ -0,0 +1,11 @@
+package com.android.telecomm;
+
+/** Only exposes the CallsManager APIs that the Dialer should have access to. */
+public class DialerAdapter {
+  private CallsManager callsManager;
+
+  /** Package private */
+  DialerAdapter(CallsManager callsManager) {
+    this.callsManager = callsManager;
+  }
+}
diff --git a/src/com/android/telecomm/InCallAdapter.java b/src/com/android/telecomm/InCallAdapter.java
new file mode 100644
index 0000000..143e324
--- /dev/null
+++ b/src/com/android/telecomm/InCallAdapter.java
@@ -0,0 +1,11 @@
+package com.android.telecomm;
+
+/** Only exposes the CallsManager APIs that In-Call should have access to. */
+public class InCallAdapter {
+  private CallsManager callsManager;
+
+  /** Package private */
+  InCallAdapter(CallsManager callsManager) {
+    this.callsManager = callsManager;
+  }
+}
diff --git a/src/com/android/telecomm/IncomingCallFilter.java b/src/com/android/telecomm/IncomingCallFilter.java
new file mode 100644
index 0000000..2d5e867
--- /dev/null
+++ b/src/com/android/telecomm/IncomingCallFilter.java
@@ -0,0 +1,6 @@
+package com.android.telecomm;
+
+// Can be used to reject incoming calls, see OutgoingCallFilter regarding
+// outgoing calls.
+public interface IncomingCallFilter {
+}
diff --git a/src/com/android/telecomm/OutgoingCallFilter.java b/src/com/android/telecomm/OutgoingCallFilter.java
new file mode 100644
index 0000000..07b24f9
--- /dev/null
+++ b/src/com/android/telecomm/OutgoingCallFilter.java
@@ -0,0 +1,15 @@
+package com.android.telecomm;
+
+import com.android.telecomm.exceptions.RestrictedCallException;
+
+// Can be used to prevent outgoing calls based on arbitrary restrictions across
+// call services (e.g. black listing a phone number regardless if it is
+// attempted over PSTN or WiFi).  That being the case, FDN which is specific to
+// GSM may need to be implemented separately since these policies are generally
+// invoked before a particular call service is selected.
+// See http://en.wikipedia.org/wiki/Fixed_Dialing_Number and IncomingCallFilter
+// regarding incoming calls.
+public interface OutgoingCallFilter {
+  public boolean validate(String userInput, ContactInfo contactInfo)
+      throws RestrictedCallException;
+}
diff --git a/src/com/android/telecomm/Switchboard.java b/src/com/android/telecomm/Switchboard.java
new file mode 100644
index 0000000..4d735b1
--- /dev/null
+++ b/src/com/android/telecomm/Switchboard.java
@@ -0,0 +1,68 @@
+package com.android.telecomm;
+
+import com.android.telecomm.exceptions.CallServiceUnavailableException;
+import com.android.telecomm.exceptions.OutgoingCallException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Package private */
+class Switchboard {
+
+  private List<CallService> callServices = new ArrayList<CallService>();
+
+  /** Package private */
+  void addCallService(CallService callService) {
+    if (callService != null && !callServices.contains(callService)) {
+      callServices.add(callService);
+    }
+  }
+
+  /** Package private */
+  void placeOutgoingCall(String userInput, ContactInfo contactInfo)
+      throws CallServiceUnavailableException {
+
+    if (callServices.isEmpty()) {
+      // No call services, bail out.
+      // TODO(contacts-team): Add logging?
+      throw new CallServiceUnavailableException();
+    }
+
+    List<CallService> compatibleCallServices = new ArrayList<CallService>();
+    for (CallService service : callServices) {
+      if (service.isCompatibleWith(userInput, contactInfo)) {
+        // NOTE(android-contacts): If we end up taking the liberty to issue
+        // calls not using the explicit user input (in case one is provided)
+        // and instead pull an alternative method of communication from the
+        // specified user-info object, it may be desirable to give precedence
+        // to services that can in fact respect the user's intent.
+        compatibleCallServices.add(service);
+      }
+    }
+
+    if (compatibleCallServices.isEmpty()) {
+      // None of the available call services is suitable for making this call.
+      // TODO(contacts-team): Same here re logging.
+      throw new CallServiceUnavailableException();
+    }
+
+    // NOTE(android-team): At this point we can also prompt the user for
+    // preference, i.e. instead of the logic just below.
+    if (compatibleCallServices.size() > 1) {
+      compatibleCallServices = sort(compatibleCallServices);
+    }
+    for (CallService service : compatibleCallServices) {
+      try {
+        service.placeOutgoingCall(userInput, contactInfo);
+        return;
+      } catch (OutgoingCallException ignored) { }
+    }
+  }
+  
+  private List<CallService> sort(List<CallService> callServices) {
+    // TODO(android-contacts): Sort by reliability, cost, and ultimately
+    // the desirability to issue a given call over each of the specified
+    // call services.
+    return callServices;
+  }
+}
diff --git a/src/com/android/telecomm/VoicemailManager.java b/src/com/android/telecomm/VoicemailManager.java
new file mode 100644
index 0000000..e998519
--- /dev/null
+++ b/src/com/android/telecomm/VoicemailManager.java
@@ -0,0 +1,5 @@
+package com.android.telecomm;
+
+/** Package private */
+class VoicemailManager {
+}
diff --git a/src/com/android/telecomm/exceptions/CallServiceUnavailableException.java b/src/com/android/telecomm/exceptions/CallServiceUnavailableException.java
new file mode 100644
index 0000000..960b47f
--- /dev/null
+++ b/src/com/android/telecomm/exceptions/CallServiceUnavailableException.java
@@ -0,0 +1,19 @@
+package com.android.telecomm.exceptions;
+
+public class CallServiceUnavailableException extends Exception {
+  public CallServiceUnavailableException() {
+    super();
+  }
+
+  public CallServiceUnavailableException(String message) {
+    super(message);
+  }
+
+  public CallServiceUnavailableException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public CallServiceUnavailableException(Throwable cause) {
+    super(cause);
+  }
+}
diff --git a/src/com/android/telecomm/exceptions/NoCompatibleCallServiceException.java b/src/com/android/telecomm/exceptions/NoCompatibleCallServiceException.java
new file mode 100644
index 0000000..2422fa5
--- /dev/null
+++ b/src/com/android/telecomm/exceptions/NoCompatibleCallServiceException.java
@@ -0,0 +1,19 @@
+package com.android.telecomm.exceptions;
+
+public class NoCompatibleCallServiceException extends Exception {
+  public NoCompatibleCallServiceException() {
+    super();
+  }
+
+  public NoCompatibleCallServiceException(String message) {
+    super(message);
+  }
+
+  public NoCompatibleCallServiceException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public NoCompatibleCallServiceException(Throwable cause) {
+    super(cause);
+  }
+}
diff --git a/src/com/android/telecomm/exceptions/OutgoingCallException.java b/src/com/android/telecomm/exceptions/OutgoingCallException.java
new file mode 100644
index 0000000..e5d46a2
--- /dev/null
+++ b/src/com/android/telecomm/exceptions/OutgoingCallException.java
@@ -0,0 +1,20 @@
+package com.android.telecomm.exceptions;
+
+public class OutgoingCallException extends Exception {
+  public OutgoingCallException() {
+    super();
+  }
+
+  public OutgoingCallException(String message) {
+    super(message);
+  }
+
+  public OutgoingCallException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public OutgoingCallException(Throwable cause) {
+    super(cause);
+  }
+}
+
diff --git a/src/com/android/telecomm/exceptions/RestrictedCallException.java b/src/com/android/telecomm/exceptions/RestrictedCallException.java
new file mode 100644
index 0000000..616f4fd
--- /dev/null
+++ b/src/com/android/telecomm/exceptions/RestrictedCallException.java
@@ -0,0 +1,19 @@
+package com.android.telecomm.exceptions;
+
+public class RestrictedCallException extends Exception {
+  public RestrictedCallException() {
+    super();
+  }
+
+  public RestrictedCallException(String message) {
+    super(message);
+  }
+
+  public RestrictedCallException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public RestrictedCallException(Throwable cause) {
+    super(cause);
+  }
+}