Merge "Add nuisance call reporting API to Telecom."
diff --git a/api/current.txt b/api/current.txt
index e1a3608..fba5597 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -43043,6 +43043,15 @@
     method public abstract void onScreenCall(@NonNull android.telecom.Call.Details);
     method public final void provideCallIdentification(@NonNull android.telecom.Call.Details, @NonNull android.telecom.CallIdentification);
     method public final void respondToCall(@NonNull android.telecom.Call.Details, @NonNull android.telecom.CallScreeningService.CallResponse);
+    field public static final String ACTION_NUISANCE_CALL_STATUS_CHANGED = "android.telecom.action.NUISANCE_CALL_STATUS_CHANGED";
+    field public static final int CALL_DURATION_LONG = 4; // 0x4
+    field public static final int CALL_DURATION_MEDIUM = 3; // 0x3
+    field public static final int CALL_DURATION_SHORT = 2; // 0x2
+    field public static final int CALL_DURATION_VERY_SHORT = 1; // 0x1
+    field public static final String EXTRA_CALL_DURATION = "android.telecom.extra.CALL_DURATION";
+    field public static final String EXTRA_CALL_HANDLE = "android.telecom.extra.CALL_HANDLE";
+    field public static final String EXTRA_CALL_TYPE = "android.telecom.extra.CALL_TYPE";
+    field public static final String EXTRA_IS_NUISANCE = "android.telecom.extra.IS_NUISANCE";
     field public static final String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
   }
 
@@ -43648,6 +43657,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, String);
     method @RequiresPermission(anyOf={android.Manifest.permission.CALL_PHONE, android.Manifest.permission.MANAGE_OWN_CALLS}) public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void reportNuisanceCallStatus(@NonNull android.net.Uri, boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void showInCallScreen(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void silenceRinger();
     method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 96b8dc2..c7cba62 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -487,6 +487,7 @@
     <protected-broadcast android:name="android.security.action.TRUST_STORE_CHANGED" />
     <protected-broadcast android:name="android.security.action.KEYCHAIN_CHANGED" />
     <protected-broadcast android:name="android.security.action.KEY_ACCESS_CHANGED" />
+    <protected-broadcast android:name="android.telecom.action.NUISANCE_CALL_STATUS_CHANGED" />
     <protected-broadcast android:name="android.telecom.action.PHONE_ACCOUNT_REGISTERED" />
     <protected-broadcast android:name="android.telecom.action.PHONE_ACCOUNT_UNREGISTERED" />
     <protected-broadcast android:name="android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION" />
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 826ad82..818ebd9 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
 import android.app.Service;
@@ -32,6 +33,9 @@
 import com.android.internal.telecom.ICallScreeningAdapter;
 import com.android.internal.telecom.ICallScreeningService;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * This service can be implemented by the default dialer (see
  * {@link TelecomManager#getDefaultDialerPackage()}) or a third party app to allow or disallow
@@ -88,6 +92,128 @@
  * </pre>
  */
 public abstract class CallScreeningService extends Service {
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            prefix = { "CALL_DURATION_" },
+            value = {CALL_DURATION_VERY_SHORT, CALL_DURATION_SHORT, CALL_DURATION_MEDIUM,
+                    CALL_DURATION_LONG})
+    public @interface CallDuration {}
+
+    /**
+     * Call duration reported with {@link #EXTRA_CALL_DURATION} to indicate to the
+     * {@link CallScreeningService} the duration of a call for which the user reported the nuisance
+     * status (see {@link TelecomManager#reportNuisanceCallStatus(Uri, boolean)}).  The
+     * {@link CallScreeningService} can use this as a signal for training nuisance detection
+     * algorithms.  The call duration is reported in coarse grained buckets to minimize exposure of
+     * identifying call log information to the {@link CallScreeningService}.
+     * <p>
+     * Indicates the call was < 3 seconds in duration.
+     */
+    public static final int CALL_DURATION_VERY_SHORT = 1;
+
+    /**
+     * Call duration reported with {@link #EXTRA_CALL_DURATION} to indicate to the
+     * {@link CallScreeningService} the duration of a call for which the user reported the nuisance
+     * status (see {@link TelecomManager#reportNuisanceCallStatus(Uri, boolean)}).  The
+     * {@link CallScreeningService} can use this as a signal for training nuisance detection
+     * algorithms.  The call duration is reported in coarse grained buckets to minimize exposure of
+     * identifying call log information to the {@link CallScreeningService}.
+     * <p>
+     * Indicates the call was greater than 3 seconds, but less than 60 seconds in duration.
+     */
+    public static final int CALL_DURATION_SHORT = 2;
+
+    /**
+     * Call duration reported with {@link #EXTRA_CALL_DURATION} to indicate to the
+     * {@link CallScreeningService} the duration of a call for which the user reported the nuisance
+     * status (see {@link TelecomManager#reportNuisanceCallStatus(Uri, boolean)}).  The
+     * {@link CallScreeningService} can use this as a signal for training nuisance detection
+     * algorithms.  The call duration is reported in coarse grained buckets to minimize exposure of
+     * identifying call log information to the {@link CallScreeningService}.
+     * <p>
+     * Indicates the call was greater than 60 seconds, but less than 120 seconds in duration.
+     */
+    public static final int CALL_DURATION_MEDIUM = 3;
+
+    /**
+     * Call duration reported with {@link #EXTRA_CALL_DURATION} to indicate to the
+     * {@link CallScreeningService} the duration of a call for which the user reported the nuisance
+     * status (see {@link TelecomManager#reportNuisanceCallStatus(Uri, boolean)}).  The
+     * {@link CallScreeningService} can use this as a signal for training nuisance detection
+     * algorithms.  The call duration is reported in coarse grained buckets to minimize exposure of
+     * identifying call log information to the {@link CallScreeningService}.
+     * <p>
+     * Indicates the call was greater than 120 seconds.
+     */
+    public static final int CALL_DURATION_LONG = 4;
+
+    /**
+     * Telecom sends this intent to the {@link CallScreeningService} which the user has chosen to
+     * fill the call screening role when the user indicates through the default dialer whether a
+     * call is a nuisance call or not (see
+     * {@link TelecomManager#reportNuisanceCallStatus(Uri, boolean)}).
+     * <p>
+     * The following extra values are provided for the call:
+     * <ol>
+     *     <li>{@link #EXTRA_CALL_HANDLE} - the handle of the call.</li>
+     *     <li>{@link #EXTRA_IS_NUISANCE} - {@code true} if the user reported the call as a nuisance
+     *     call, {@code false} otherwise.</li>
+     *     <li>{@link #EXTRA_CALL_TYPE} - reports the type of call (incoming, rejected, missed,
+     *     blocked).</li>
+     *     <li>{@link #EXTRA_CALL_DURATION} - the duration of the call (see
+     *     {@link #EXTRA_CALL_DURATION} for valid values).</li>
+     * </ol>
+     * <p>
+     * {@link CallScreeningService} implementations which want to track whether the user reports
+     * calls are nuisance calls should use declare a broadcast receiver in their manifest for this
+     * intent.
+     * <p>
+     * Note: Only {@link CallScreeningService} implementations which have provided
+     * {@link CallIdentification} information for calls at some point will receive this intent.
+     */
+    public static final String ACTION_NUISANCE_CALL_STATUS_CHANGED =
+            "android.telecom.action.NUISANCE_CALL_STATUS_CHANGED";
+
+    /**
+     * Extra used to provide the handle of the call for
+     * {@link #ACTION_NUISANCE_CALL_STATUS_CHANGED}.  The call handle is reported as a
+     * {@link Uri}.
+     */
+    public static final String EXTRA_CALL_HANDLE = "android.telecom.extra.CALL_HANDLE";
+
+    /**
+     * Boolean extra used to indicate whether the user reported a call as a nuisance call.
+     * When {@code true}, the user reported that a call was a nuisance call, {@code false}
+     * otherwise.  Sent with {@link #ACTION_NUISANCE_CALL_STATUS_CHANGED}.
+     */
+    public static final String EXTRA_IS_NUISANCE = "android.telecom.extra.IS_NUISANCE";
+
+    /**
+     * Integer extra used with {@link #ACTION_NUISANCE_CALL_STATUS_CHANGED} to report the type of
+     * call. Valid values are:
+     * <UL>
+     *   <li>{@link android.provider.CallLog.Calls#MISSED_TYPE}</li>
+     *   <li>{@link android.provider.CallLog.Calls#INCOMING_TYPE}</li>
+     *   <li>{@link android.provider.CallLog.Calls#BLOCKED_TYPE}</li>
+     *   <li>{@link android.provider.CallLog.Calls#REJECTED_TYPE}</li>
+     * </UL>
+     */
+    public static final String EXTRA_CALL_TYPE = "android.telecom.extra.CALL_TYPE";
+
+    /**
+     * Integer extra used to with {@link #ACTION_NUISANCE_CALL_STATUS_CHANGED} to report how long
+     * the call lasted.  Valid values are:
+     * <UL>
+     *     <LI>{@link #CALL_DURATION_VERY_SHORT}</LI>
+     *     <LI>{@link #CALL_DURATION_SHORT}</LI>
+     *     <LI>{@link #CALL_DURATION_MEDIUM}</LI>
+     *     <LI>{@link #CALL_DURATION_LONG}</LI>
+     * </UL>
+     */
+    public static final String EXTRA_CALL_DURATION = "android.telecom.extra.CALL_DURATION";
+
     /**
      * The {@link Intent} that must be declared as handled by the service.
      */
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 0fe5e08..12a5344 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1970,6 +1970,33 @@
     }
 
     /**
+     * Called by the default dialer to report to Telecom when the user has marked a previous
+     * incoming call as a nuisance call or not.
+     * <p>
+     * Where the user has chosen a {@link CallScreeningService} to fill the call screening role,
+     * Telecom will notify that {@link CallScreeningService} of the user's report.
+     * <p>
+     * Requires that the caller is the default dialer app.
+     *
+     * @param handle The phone number of an incoming call which the user is reporting as either a
+     *               nuisance of non-nuisance call.
+     * @param isNuisanceCall {@code true} if the user is reporting the call as a nuisance call,
+     *                       {@code false} if the user is reporting the call as a non-nuisance call.
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public void reportNuisanceCallStatus(@NonNull Uri handle, boolean isNuisanceCall) {
+        ITelecomService service = getTelecomService();
+        if (service != null) {
+            try {
+                service.reportNuisanceCallStatus(handle, isNuisanceCall,
+                        mContext.getOpPackageName());
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling ITelecomService#showCallScreen", e);
+            }
+        }
+    }
+
+    /**
      * Handles {@link Intent#ACTION_CALL} intents trampolined from UserCallActivity.
      * @param intent The {@link Intent#ACTION_CALL} intent to handle.
      * @hide
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index e1d5c17..5030f90 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -285,6 +285,8 @@
      */
     boolean isInEmergencyCall();
 
+    oneway void reportNuisanceCallStatus(in Uri address, boolean isNuisance, String callingPackage);
+
     /**
      * @see TelecomServiceImpl#handleCallIntent
      */
@@ -299,4 +301,5 @@
     void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded);
 
     void setTestAutoModeApp(String packageName);
+
 }