Add APIs to support background call screening

Add Telecom APIs and AIDL code.

Test: CTS
Bug: 140317205
Change-Id: I99970f5ce12442f307a656db76cb26f5101e6c7f
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 1822cee..5e71416 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Build;
@@ -119,6 +120,20 @@
     public static final int STATE_PULLING_CALL = 11;
 
     /**
+     * The state of a call that is active with the network, but the audio from the call is
+     * being intercepted by an app on the local device. Telecom does not hold audio focus in this
+     * state, and the call will be invisible to the user except for a persistent notification.
+     */
+    public static final int STATE_AUDIO_PROCESSING = 12;
+
+    /**
+     * The state of a call that is being presented to the user after being in
+     * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and
+     * Telecom will hold audio focus and play a ringtone if appropriate.
+     */
+    public static final int STATE_SIMULATED_RINGING = 13;
+
+    /**
      * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
      * extras. Used to pass the phone accounts to display on the front end to the user in order to
      * select phone accounts to (for example) place a call.
@@ -1479,6 +1494,49 @@
     }
 
     /**
+     * Instructs Telecom to put the call into the background audio processing state.
+     *
+     * This method can be called either when the call is in {@link #STATE_RINGING} or
+     * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
+     * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
+     * order to capture and play audio on the call stream.
+     *
+     * This method can only be called by the default dialer app.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    //@RequiresPermission(android.Manifest.permission.BACKGROUND_CALL_AUDIO)
+    public void enterBackgroundAudioProcessing() {
+        if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
+            throw new IllegalStateException("Call must be active or ringing");
+        }
+        mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
+    }
+
+    /**
+     * Instructs Telecom to come out of the background audio processing state requested by
+     * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
+     *
+     * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
+     *
+     * @param shouldRing If true, Telecom will put the call into the
+     *                   {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
+     *                   a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
+     *                   immediately.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    //@RequiresPermission(android.Manifest.permission.BACKGROUND_CALL_AUDIO)
+    public void exitBackgroundAudioProcessing(boolean shouldRing) {
+        if (mState != STATE_AUDIO_PROCESSING) {
+            throw new IllegalStateException("Call must in the audio processing state");
+        }
+        mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
+    }
+
+    /**
      * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
      *
      * Any other currently playing DTMF tone in the specified call is immediately stopped.
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 0e0406d..9016b3e8 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -19,6 +19,8 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -140,23 +142,30 @@
         private final boolean mShouldSilenceCall;
         private final boolean mShouldSkipCallLog;
         private final boolean mShouldSkipNotification;
+        private final boolean mShouldScreenCallFurther;
 
         private CallResponse(
                 boolean shouldDisallowCall,
                 boolean shouldRejectCall,
                 boolean shouldSilenceCall,
                 boolean shouldSkipCallLog,
-                boolean shouldSkipNotification) {
+                boolean shouldSkipNotification,
+                boolean shouldScreenCallFurther) {
             if (!shouldDisallowCall
                     && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) {
                 throw new IllegalStateException("Invalid response state for allowed call.");
             }
 
+            if (shouldDisallowCall && shouldScreenCallFurther) {
+                throw new IllegalStateException("Invalid response state for allowed call.");
+            }
+
             mShouldDisallowCall = shouldDisallowCall;
             mShouldRejectCall = shouldRejectCall;
             mShouldSkipCallLog = shouldSkipCallLog;
             mShouldSkipNotification = shouldSkipNotification;
             mShouldSilenceCall = shouldSilenceCall;
+            mShouldScreenCallFurther = shouldScreenCallFurther;
         }
 
         /*
@@ -195,12 +204,22 @@
             return mShouldSkipNotification;
         }
 
+        /**
+         * @return Whether we should enter the {@link Call#STATE_AUDIO_PROCESSING} state to allow
+         * for further screening of the call.
+         * @hide
+         */
+        public boolean getShouldScreenCallFurther() {
+            return mShouldScreenCallFurther;
+        }
+
         public static class Builder {
             private boolean mShouldDisallowCall;
             private boolean mShouldRejectCall;
             private boolean mShouldSilenceCall;
             private boolean mShouldSkipCallLog;
             private boolean mShouldSkipNotification;
+            private boolean mShouldScreenCallFurther;
 
             /**
              * Sets whether the incoming call should be blocked.
@@ -256,13 +275,32 @@
                 return this;
             }
 
+            /**
+             * Sets whether to request background audio processing so that the in-call service can
+             * screen the call further. If set to {@code true}, {@link #setDisallowCall} should be
+             * called with {@code false}, and all other parameters in this builder will be ignored.
+             *
+             * This request will only be honored if the {@link CallScreeningService} shares the same
+             * uid as the default dialer app. Otherwise, the call will go through as usual.
+             *
+             * @param shouldScreenCallFurther Whether to request further call screening.
+             * @hide
+             */
+            @SystemApi
+            @TestApi
+            public Builder setShouldScreenCallFurther(boolean shouldScreenCallFurther) {
+                mShouldScreenCallFurther = shouldScreenCallFurther;
+                return this;
+            }
+
             public CallResponse build() {
                 return new CallResponse(
                         mShouldDisallowCall,
                         mShouldRejectCall,
                         mShouldSilenceCall,
                         mShouldSkipCallLog,
-                        mShouldSkipNotification);
+                        mShouldSkipNotification,
+                        mShouldScreenCallFurther);
             }
        }
     }
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 8678e33..2612468 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -16,8 +16,8 @@
 
 package android.telecom;
 
-import android.net.Uri;
 import android.bluetooth.BluetoothDevice;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
 
@@ -149,6 +149,26 @@
     }
 
     /**
+     * @see Call#enterBackgroundAudioProcessing()
+     */
+    public void enterBackgroundAudioProcessing(String callId) {
+        try {
+            mAdapter.enterBackgroundAudioProcessing(callId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * @see Call#exitBackgroundAudioProcessing(boolean)
+     */
+    public void exitBackgroundAudioProcessing(String callId, boolean shouldRing) {
+        try {
+            mAdapter.exitBackgroundAudioProcessing(callId, shouldRing);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Request audio routing to a specific bluetooth device. Calling this method may result in
      * the device routing audio to a different bluetooth device than the one specified. A list of
      * available devices can be obtained via {@link CallAudioState#getSupportedBluetoothDevices()}