diff --git a/api/current.txt b/api/current.txt index bba65864ad78d..8d78b560dac05 100644 --- a/api/current.txt +++ b/api/current.txt @@ -43500,6 +43500,7 @@ package android.telecom { method public void registerCallback(android.telecom.Call.Callback); method public void registerCallback(android.telecom.Call.Callback, android.os.Handler); method public void reject(boolean, String); + method public void reject(int); method public void removeExtras(java.util.List); method public void removeExtras(java.lang.String...); method public void respondToRttRequest(int, boolean); @@ -43515,6 +43516,8 @@ package android.telecom { field public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS"; field public static final String EXTRA_SILENT_RINGING_REQUESTED = "android.telecom.extra.SILENT_RINGING_REQUESTED"; field public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS = "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS"; + field public static final int REJECT_REASON_DECLINED = 1; // 0x1 + field public static final int REJECT_REASON_UNWANTED = 2; // 0x2 field public static final int STATE_ACTIVE = 4; // 0x4 field public static final int STATE_AUDIO_PROCESSING = 12; // 0xc field public static final int STATE_CONNECTING = 9; // 0x9 @@ -43782,6 +43785,7 @@ package android.telecom { method public void onPostDialContinue(boolean); method public void onPullExternalCall(); method public void onReject(); + method public void onReject(int); method public void onReject(String); method public void onSeparate(); method public void onShowIncomingCallUi(); diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index acf51f3856d3d..f54f8d1f58324 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -265,6 +265,29 @@ public final class Call { public static final String EVENT_HANDOVER_FAILED = "android.telecom.event.HANDOVER_FAILED"; + + /** + * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this + * call because they have declined to answer it. This typically means that they are unable + * to answer the call at this time and would prefer it be sent to voicemail. + */ + public static final int REJECT_REASON_DECLINED = 1; + + /** + * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this + * call because it is an unwanted call. This allows the user to indicate that they are + * rejecting a call because it is likely a nuisance call. + */ + public static final int REJECT_REASON_UNWANTED = 2; + + /** + * @hide + */ + @IntDef(prefix = { "REJECT_REASON_" }, + value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED}) + @Retention(RetentionPolicy.SOURCE) + public @interface RejectReason {}; + public static class Details { /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -1519,6 +1542,16 @@ public final class Call { mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage); } + /** + * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the + * user has chosen to reject the call and has indicated a reason why the call is being rejected. + * + * @param rejectReason the reason the call is being rejected. + */ + public void reject(@RejectReason int rejectReason) { + mInCallAdapter.rejectCall(mTelecomCallId, rejectReason); + } + /** * Instructs this {@code Call} to disconnect. */ diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index c934625f588b5..72c66d20548a3 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -3036,6 +3036,17 @@ public abstract class Connection extends Conferenceable { */ public void onReject() {} + /** + * Notifies this Connection, which is in {@link #STATE_RINGING}, of a request to reject. + *

+ * For managed {@link ConnectionService}s, this will be called when the user rejects a call via + * the default dialer's {@link InCallService} using {@link Call#reject(int)}. + * @param rejectReason the reason the user provided for rejecting the call. + */ + public void onReject(@android.telecom.Call.RejectReason int rejectReason) { + // to be implemented by ConnectionService. + } + /** * Notifies this Connection, which is in {@link #STATE_RINGING}, of * a request to reject with a message. diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 440f044fdcf78..00c2918837acb 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -194,6 +194,7 @@ public abstract class ConnectionService extends Service { private static final int MSG_CREATE_CONFERENCE = 35; private static final int MSG_CREATE_CONFERENCE_COMPLETE = 36; private static final int MSG_CREATE_CONFERENCE_FAILED = 37; + private static final int MSG_REJECT_WITH_REASON = 38; private static Connection sNullConnection; @@ -449,6 +450,21 @@ public abstract class ConnectionService extends Service { } } + @Override + public void rejectWithReason(String callId, + @android.telecom.Call.RejectReason int rejectReason, Session.Info sessionInfo) { + Log.startSession(sessionInfo, SESSION_REJECT); + try { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + args.argi1 = rejectReason; + args.arg2 = Log.createSubsession(); + mHandler.obtainMessage(MSG_REJECT_WITH_REASON, args).sendToTarget(); + } finally { + Log.endSession(); + } + } + @Override public void rejectWithMessage(String callId, String message, Session.Info sessionInfo) { Log.startSession(sessionInfo, SESSION_REJECT_MESSAGE); @@ -1053,6 +1069,17 @@ public abstract class ConnectionService extends Service { } break; } + case MSG_REJECT_WITH_REASON: { + SomeArgs args = (SomeArgs) msg.obj; + Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT); + try { + reject((String) args.arg1, args.argi1); + } finally { + args.recycle(); + Log.endSession(); + } + break; + } case MSG_REJECT_WITH_MESSAGE: { SomeArgs args = (SomeArgs) msg.obj; Log.continueSession((Session) args.arg3, @@ -1981,6 +2008,11 @@ public abstract class ConnectionService extends Service { findConnectionForAction(callId, "reject").onReject(rejectWithMessage); } + private void reject(String callId, @android.telecom.Call.RejectReason int rejectReason) { + Log.d(this, "reject %s with reason %d", callId, rejectReason); + findConnectionForAction(callId, "reject").onReject(rejectReason); + } + private void silence(String callId) { Log.d(this, "silence %s", callId); findConnectionForAction(callId, "silence").onSilence(); diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java index 261246818f1d3..594c1eb392b3b 100644 --- a/telecomm/java/android/telecom/InCallAdapter.java +++ b/telecomm/java/android/telecom/InCallAdapter.java @@ -88,6 +88,19 @@ public final class InCallAdapter { } } + /** + * Instructs Telecom to reject the specified call. + * + * @param callId The identifier of the call to reject. + * @param rejectReason The reason the call was rejected. + */ + public void rejectCall(String callId, @Call.RejectReason int rejectReason) { + try { + mAdapter.rejectCallWithReason(callId, rejectReason); + } catch (RemoteException e) { + } + } + /** * Instructs Telecom to disconnect the specified call. * diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl index 96f2483f32f90..4249dff151c77 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl @@ -77,6 +77,8 @@ oneway interface IConnectionService { void reject(String callId, in Session.Info sessionInfo); + void rejectWithReason(String callId, int rejectReason, in Session.Info sessionInfo); + void rejectWithMessage(String callId, String message, in Session.Info sessionInfo); void disconnect(String callId, in Session.Info sessionInfo); diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl index 60745e40aa777..eb2d714fe3f4c 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl @@ -34,6 +34,8 @@ oneway interface IInCallAdapter { void rejectCall(String callId, boolean rejectWithMessage, String textMessage); + void rejectCallWithReason(String callId, int rejectReason); + void disconnectCall(String callId); void holdCall(String callId); diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java index f4367da4a4dc1..e8f69ea64a220 100644 --- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java @@ -410,6 +410,13 @@ public class ImsCallSessionImplBase implements AutoCloseable { * Rejects an incoming call or session update. * * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}. + * The {@link android.telecom.InCallService} (dialer app) can use the + * {@link android.telecom.Call#reject(int)} API to reject a call while specifying + * a user-indicated reason for rejecting the call. + * Normal call declines ({@link android.telecom.Call#REJECT_REASON_DECLINED}) will + * map to {@link ImsReasonInfo#CODE_USER_DECLINE}. + * Unwanted calls ({@link android.telecom.Call#REJECT_REASON_UNWANTED}) will map + * to {@link ImsReasonInfo#CODE_SIP_USER_MARKED_UNWANTED}. * {@link ImsCallSession.Listener#callSessionStartFailed} */ public void reject(int reason) {