Merge "AudioFormat: add ENCODING_IEC61937"
diff --git a/Android.mk b/Android.mk
index 8daa1aa..c947b0e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -385,6 +385,8 @@
 	media/java/android/media/tv/ITvInputSessionCallback.aidl \
 	media/java/android/service/media/IMediaBrowserService.aidl \
 	media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl \
+	telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl \
+	telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl \
 	telecomm/java/com/android/internal/telecom/IVideoCallback.aidl \
 	telecomm/java/com/android/internal/telecom/IVideoProvider.aidl \
 	telecomm/java/com/android/internal/telecom/IConnectionService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 56b0d3a..92d6d21 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -33,6 +33,7 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
@@ -35373,6 +35374,30 @@
     field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
   }
 
+  public abstract class CallScreeningService extends android.app.Service {
+    ctor public CallScreeningService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onScreenCall(android.telecom.Call.Details);
+    method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+  }
+
+  public class CallScreeningService.CallResponse {
+    method public boolean getDisallowCall();
+    method public boolean getRejectCall();
+    method public boolean getSkipCallLog();
+    method public boolean getSkipNotification();
+  }
+
+  public class CallScreeningService.CallResponse.Builder {
+    ctor public CallScreeningService.CallResponse.Builder();
+    method public android.telecom.CallScreeningService.CallResponse build();
+    method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+  }
+
   public abstract class Conference extends android.telecom.Conferenceable {
     ctor public Conference(android.telecom.PhoneAccountHandle);
     method public final boolean addConnection(android.telecom.Connection);
@@ -35612,6 +35637,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -35872,6 +35898,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
     field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
diff --git a/api/system-current.txt b/api/system-current.txt
index 632c37c..0888f30 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -46,6 +46,7 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
@@ -37680,6 +37681,30 @@
     field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
   }
 
+  public abstract class CallScreeningService extends android.app.Service {
+    ctor public CallScreeningService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onScreenCall(android.telecom.Call.Details);
+    method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+  }
+
+  public class CallScreeningService.CallResponse {
+    method public boolean getDisallowCall();
+    method public boolean getRejectCall();
+    method public boolean getSkipCallLog();
+    method public boolean getSkipNotification();
+  }
+
+  public class CallScreeningService.CallResponse.Builder {
+    ctor public CallScreeningService.CallResponse.Builder();
+    method public android.telecom.CallScreeningService.CallResponse build();
+    method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+  }
+
   public abstract class Conference extends android.telecom.Conferenceable {
     ctor public Conference(android.telecom.PhoneAccountHandle);
     method public final boolean addConnection(android.telecom.Connection);
@@ -37929,6 +37954,7 @@
     method public void onCanAddCallChanged(boolean);
     method public deprecated void onPhoneCreated(android.telecom.Phone);
     method public deprecated void onPhoneDestroyed(android.telecom.Phone);
+    method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -38010,6 +38036,7 @@
     method public void onCallAudioStateChanged(android.telecom.Phone, android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Phone, android.telecom.Call);
     method public void onCanAddCallChanged(android.telecom.Phone, boolean);
+    method public void onSilenceRinger(android.telecom.Phone);
   }
 
   public final class PhoneAccount implements android.os.Parcelable {
@@ -38269,6 +38296,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
     field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
diff --git a/api/test-current.txt b/api/test-current.txt
index b153533..fe14793 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -33,6 +33,7 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
@@ -35387,6 +35388,30 @@
     field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
   }
 
+  public abstract class CallScreeningService extends android.app.Service {
+    ctor public CallScreeningService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onScreenCall(android.telecom.Call.Details);
+    method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+  }
+
+  public class CallScreeningService.CallResponse {
+    method public boolean getDisallowCall();
+    method public boolean getRejectCall();
+    method public boolean getSkipCallLog();
+    method public boolean getSkipNotification();
+  }
+
+  public class CallScreeningService.CallResponse.Builder {
+    ctor public CallScreeningService.CallResponse.Builder();
+    method public android.telecom.CallScreeningService.CallResponse build();
+    method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+  }
+
   public abstract class Conference extends android.telecom.Conferenceable {
     ctor public Conference(android.telecom.PhoneAccountHandle);
     method public final boolean addConnection(android.telecom.Connection);
@@ -35626,6 +35651,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -35886,6 +35912,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
     field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5a2f601..3aa7de5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1407,6 +1407,13 @@
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Must be required by a {@link android.telecom.CallScreeningService},
+         to ensure that only the system can bind to it.
+         <p>Protection level: signature|privileged
+    -->
+    <permission android:name="android.permission.BIND_SCREENING_SERVICE"
+        android:protectionLevel="signature|privileged" />
+
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
          @deprecated {@link android.telecom.ConnectionService}s should require
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 3859294..de902025 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -265,6 +265,7 @@
         // Next PROPERTY value: 0x00000040
         //******************************************************************************************
 
+        private final String mTelecomCallId;
         private final Uri mHandle;
         private final int mHandlePresentation;
         private final String mCallerDisplayName;
@@ -414,6 +415,11 @@
             return builder.toString();
         }
 
+        /** {@hide} */
+        public String getTelecomCallId() {
+            return mTelecomCallId;
+        }
+
         /**
          * @return The handle (e.g., phone number) to which the {@code Call} is currently
          * connected.
@@ -567,6 +573,7 @@
 
         /** {@hide} */
         public Details(
+                String telecomCallId,
                 Uri handle,
                 int handlePresentation,
                 String callerDisplayName,
@@ -581,6 +588,7 @@
                 StatusHints statusHints,
                 Bundle extras,
                 Bundle intentExtras) {
+            mTelecomCallId = telecomCallId;
             mHandle = handle;
             mHandlePresentation = handlePresentation;
             mCallerDisplayName = callerDisplayName;
@@ -596,6 +604,26 @@
             mExtras = extras;
             mIntentExtras = intentExtras;
         }
+
+        /** {@hide} */
+        public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
+            return new Details(
+                    parcelableCall.getId(),
+                    parcelableCall.getHandle(),
+                    parcelableCall.getHandlePresentation(),
+                    parcelableCall.getCallerDisplayName(),
+                    parcelableCall.getCallerDisplayNamePresentation(),
+                    parcelableCall.getAccountHandle(),
+                    parcelableCall.getCapabilities(),
+                    parcelableCall.getProperties(),
+                    parcelableCall.getDisconnectCause(),
+                    parcelableCall.getConnectTimeMillis(),
+                    parcelableCall.getGatewayInfo(),
+                    parcelableCall.getVideoState(),
+                    parcelableCall.getStatusHints(),
+                    parcelableCall.getExtras(),
+                    parcelableCall.getIntentExtras());
+        }
     }
 
     public static abstract class Callback {
@@ -1022,21 +1050,7 @@
     /** {@hide} */
     final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
         // First, we update the internal state as far as possible before firing any updates.
-        Details details = new Details(
-                parcelableCall.getHandle(),
-                parcelableCall.getHandlePresentation(),
-                parcelableCall.getCallerDisplayName(),
-                parcelableCall.getCallerDisplayNamePresentation(),
-                parcelableCall.getAccountHandle(),
-                parcelableCall.getCapabilities(),
-                parcelableCall.getProperties(),
-                parcelableCall.getDisconnectCause(),
-                parcelableCall.getConnectTimeMillis(),
-                parcelableCall.getGatewayInfo(),
-                parcelableCall.getVideoState(),
-                parcelableCall.getStatusHints(),
-                parcelableCall.getExtras(),
-                parcelableCall.getIntentExtras());
+        Details details = Details.createFromParcelableCall(parcelableCall);
         boolean detailsChanged = !Objects.equals(mDetails, details);
         if (detailsChanged) {
             mDetails = details;
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
new file mode 100644
index 0000000..1b6e162
--- /dev/null
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.telecom;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+
+import com.android.internal.os.SomeArgs;
+import com.android.internal.telecom.ICallScreeningService;
+import com.android.internal.telecom.ICallScreeningAdapter;
+
+/**
+ * This service can be implemented by the default dialer (see
+ * {@link TelecomManager#getDefaultDialerPackage()}) to allow or disallow incoming calls before
+ * they are shown to a user.
+ * <p>
+ * Below is an example manifest registration for a {@code CallScreeningService}.
+ * <pre>
+ * {@code
+ * <service android:name="your.package.YourCallScreeningServiceImplementation"
+ *          android:permission="android.permission.BIND_SCREENING_SERVICE">
+ *      <intent-filter>
+ *          <action android:name="android.telecom.CallScreeningService"/>
+ *      </intent-filter>
+ * </service>
+ * }
+ * </pre>
+ */
+public abstract class CallScreeningService extends Service {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+
+    private static final int MSG_SCREEN_CALL = 1;
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SCREEN_CALL:
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        mCallScreeningAdapter = (ICallScreeningAdapter) args.arg1;
+                        onScreenCall(
+                                Call.Details.createFromParcelableCall((ParcelableCall) args.arg2));
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+            }
+        }
+    };
+
+    private final class CallScreeningBinder extends ICallScreeningService.Stub {
+        @Override
+        public void screenCall(ICallScreeningAdapter adapter, ParcelableCall call) {
+            Log.v(this, "screenCall");
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = adapter;
+            args.arg2 = call;
+            mHandler.obtainMessage(MSG_SCREEN_CALL, args).sendToTarget();
+        }
+    }
+
+    private ICallScreeningAdapter mCallScreeningAdapter;
+
+    /*
+     * Information about how to respond to an incoming call.
+     */
+    public class CallResponse {
+        private final boolean mShouldDisallowCall;
+        private final boolean mShouldRejectCall;
+        private final boolean mShouldSkipCallLog;
+        private final boolean mShouldSkipNotification;
+
+        private CallResponse(
+                boolean shouldDisallowCall,
+                boolean shouldRejectCall,
+                boolean shouldSkipCallLog,
+                boolean shouldSkipNotification) {
+            if (!shouldDisallowCall
+                    && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) {
+                throw new IllegalStateException("Invalid response state for allowed call.");
+            }
+
+            mShouldDisallowCall = shouldDisallowCall;
+            mShouldRejectCall = shouldRejectCall;
+            mShouldSkipCallLog = shouldSkipCallLog;
+            mShouldSkipNotification = shouldSkipNotification;
+        }
+
+        /*
+         * @return Whether the incoming call should be blocked.
+         */
+        public boolean getDisallowCall() {
+            return mShouldDisallowCall;
+        }
+
+        /*
+         * @return Whether the incoming call should be disconnected as if the user had manually
+         * rejected it.
+         */
+        public boolean getRejectCall() {
+            return mShouldRejectCall;
+        }
+
+        /*
+         * @return Whether the incoming call should not be displayed in the call log.
+         */
+        public boolean getSkipCallLog() {
+            return mShouldSkipCallLog;
+        }
+
+        /*
+         * @return Whether a missed call notification should not be shown for the incoming call.
+         */
+        public boolean getSkipNotification() {
+            return mShouldSkipNotification;
+        }
+
+        public class Builder {
+            private boolean mShouldDisallowCall;
+            private boolean mShouldRejectCall;
+            private boolean mShouldSkipCallLog;
+            private boolean mShouldSkipNotification;
+
+            /*
+             * Sets whether the incoming call should be blocked.
+             */
+            public Builder setDisallowCall(boolean shouldDisallowCall) {
+                mShouldDisallowCall = shouldDisallowCall;
+                return this;
+            }
+
+            /*
+             * Sets whether the incoming call should be disconnected as if the user had manually
+             * rejected it. This property should only be set to true if the call is disallowed.
+             */
+            public Builder setRejectCall(boolean shouldRejectCall) {
+                mShouldRejectCall = shouldRejectCall;
+                return this;
+            }
+
+            /*
+             * Sets whether the incoming call should not be displayed in the call log. This property
+             * should only be set to true if the call is disallowed.
+             */
+            public Builder setSkipCallLog(boolean shouldSkipCallLog) {
+                mShouldSkipCallLog = shouldSkipCallLog;
+                return this;
+            }
+
+            /*
+             * Sets whether a missed call notification should not be shown for the incoming call.
+             * This property should only be set to true if the call is disallowed.
+             */
+            public Builder setSkipNotification(boolean shouldSkipNotification) {
+                mShouldSkipNotification = shouldSkipNotification;
+                return this;
+            }
+
+            public CallResponse build() {
+                return new CallResponse(
+                        mShouldDisallowCall,
+                        mShouldRejectCall,
+                        mShouldSkipCallLog,
+                        mShouldSkipNotification);
+            }
+       }
+    }
+
+    public CallScreeningService() {
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.v(this, "onBind");
+        return new CallScreeningBinder();
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Log.v(this, "onUnbind");
+        return false;
+    }
+
+    /**
+     * Called when a new incoming call is added.
+     * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}
+     * should be called to allow or disallow the call.
+     *
+     * @param callDetails Information about a new incoming call, see {@link Call.Details}.
+     */
+    public abstract void onScreenCall(Call.Details callDetails);
+
+    /**
+     * Responds to the given call, either allowing it or disallowing it.
+     *
+     * @param callDetails The call to allow.
+     * @param response The {@link CallScreeningService.CallResponse} which contains information
+     * about how to respond to a call.
+     */
+    public final void respondToCall(Call.Details callDetails, CallResponse response) {
+        try {
+            if (response.getDisallowCall()) {
+                mCallScreeningAdapter.disallowCall(
+                        callDetails.getTelecomCallId(),
+                        response.getRejectCall(),
+                        !response.getSkipCallLog(),
+                        !response.getSkipNotification());
+            } else {
+                mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
+            }
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 426b240..671399b 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -73,6 +73,7 @@
     private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 5;
     private static final int MSG_BRING_TO_FOREGROUND = 6;
     private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
+    private static final int MSG_SILENCE_RINGER = 8;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -114,6 +115,9 @@
                 case MSG_ON_CAN_ADD_CALL_CHANGED:
                     mPhone.internalSetCanAddCall(msg.arg1 == 1);
                     break;
+                case MSG_SILENCE_RINGER:
+                    mPhone.internalSilenceRinger();
+                    break;
                 default:
                     break;
             }
@@ -165,6 +169,11 @@
             mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0)
                     .sendToTarget();
         }
+
+        @Override
+        public void silenceRinger() {
+            mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
+        }
     }
 
     private Phone.Listener mPhoneListener = new Phone.Listener() {
@@ -202,6 +211,12 @@
             InCallService.this.onCanAddCallChanged(canAddCall);
         }
 
+        /** ${inheritDoc} */
+        @Override
+        public void onSilenceRinger(Phone phone) {
+            InCallService.this.onSilenceRinger();
+        }
+
     };
 
     private Phone mPhone;
@@ -405,6 +420,12 @@
     }
 
     /**
+     * Called to silence the ringer if a ringing call exists.
+     */
+    public void onSilenceRinger() {
+    }
+
+    /**
      * Used to issue commands to the {@link Connection.VideoProvider} associated with a
      * {@link Call}.
      */
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 47154da..56eb7ec 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -97,6 +97,13 @@
          * @param canAddCall Indicates whether an additional call can be added.
          */
         public void onCanAddCallChanged(Phone phone, boolean canAddCall) { }
+
+        /**
+         * Called to silence the ringer if a ringing call exists.
+         *
+         * @param phone The {@code Phone} calling this method.
+         */
+        public void onSilenceRinger(Phone phone) { }
     }
 
     // A Map allows us to track each Call by its Telecom-specified call ID
@@ -179,6 +186,10 @@
         }
     }
 
+    final void internalSilenceRinger() {
+        fireSilenceRinger();
+    }
+
     /**
      * Called to destroy the phone and cleanup any lingering calls.
      */
@@ -330,6 +341,12 @@
         }
     }
 
+    private void fireSilenceRinger() {
+        for (Listener listener : mListeners) {
+            listener.onSilenceRinger(this);
+        }
+    }
+
     private void checkCallTree(ParcelableCall parcelableCall) {
         if (parcelableCall.getParentCallId() != null &&
                 !mCallByTelecomCallId.containsKey(parcelableCall.getParentCallId())) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 497864e8..72ff272 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -308,6 +308,15 @@
             "android.telecom.IN_CALL_SERVICE_CAR_MODE_UI";
 
     /**
+     * A boolean meta-data value indicating whether an {@link InCallService} implements ringing.
+     * Dialer implementations (see {@link #getDefaultDialerPackage()}) which would also like to
+     * override the system provided ringing should set this meta-data to {@code true} in the
+     * manifest registration of their {@link InCallService}.
+     */
+    public static final String METADATA_IN_CALL_SERVICE_RINGING =
+            "android.telecom.IN_CALL_SERVICE_RINGING";
+
+    /**
      * The dual tone multi-frequency signaling character sent to indicate the dialing system should
      * pause for a predefined period.
      */
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
new file mode 100644
index 0000000..2e0af27
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telecom;
+
+/**
+ * Internal remote callback interface for call screening services.
+ *
+ * @see android.telecom.CallScreeningService
+ *
+ * {@hide}
+ */
+oneway interface ICallScreeningAdapter {
+    void allowCall(String callId);
+
+    void disallowCall(
+            String callId,
+            boolean shouldReject,
+            boolean shouldAddToCallLog,
+            boolean shouldShowNotification);
+}
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl
new file mode 100644
index 0000000..c3fe1af
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telecom;
+
+import android.telecom.ParcelableCall;
+
+import com.android.internal.telecom.ICallScreeningAdapter;
+
+/**
+ * Internal remote interface for a call screening service.
+ * @see android.telecom.CallScreeningService
+ * @hide
+ */
+oneway interface ICallScreeningService {
+    void screenCall(in ICallScreeningAdapter adapter, in ParcelableCall call);
+}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index ded47d5..0088e0c 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -45,4 +45,6 @@
     void bringToForeground(boolean showDialpad);
 
     void onCanAddCallChanged(boolean canAddCall);
+
+    void silenceRinger();
 }