Loading core/api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -39207,16 +39207,22 @@ package android.telecom { } public static class CallScreeningService.CallResponse { method public int getCallComposerAttachmentsToShow(); method public boolean getDisallowCall(); method public boolean getRejectCall(); method public boolean getSilenceCall(); method public boolean getSkipCallLog(); method public boolean getSkipNotification(); field public static final int CALL_COMPOSER_ATTACHMENT_LOCATION = 2; // 0x2 field public static final int CALL_COMPOSER_ATTACHMENT_PICTURE = 1; // 0x1 field public static final int CALL_COMPOSER_ATTACHMENT_PRIORITY = 8; // 0x8 field public static final int CALL_COMPOSER_ATTACHMENT_SUBJECT = 4; // 0x4 } public static class CallScreeningService.CallResponse.Builder { ctor public CallScreeningService.CallResponse.Builder(); method public android.telecom.CallScreeningService.CallResponse build(); method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setCallComposerAttachmentsToShow(int); method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean); method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean); method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setSilenceCall(boolean); core/api/system-current.txt +2 −2 Original line number Diff line number Diff line Loading @@ -10769,7 +10769,7 @@ package android.telecom { method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle(); method @Nullable public final String getTelecomCallId(); method @Deprecated public void onAudioStateChanged(android.telecom.AudioState); method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean); method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, boolean); method public final void resetConnectionTime(); method public void setCallDirection(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectTimeMillis(@IntRange(from=0) long); Loading Loading @@ -10946,7 +10946,7 @@ package android.telecom { } public final class RemoteConnection { method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean); method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, boolean); method @Deprecated public void setAudioState(android.telecom.AudioState); } telecomm/java/android/telecom/CallScreeningService.aidl 0 → 100644 +22 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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; /** * {@hide} */ parcelable CallScreeningService.ParcelableCallResponse; telecomm/java/android/telecom/CallScreeningService.java +254 −19 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.telecom; import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; Loading @@ -30,12 +31,18 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import com.android.internal.os.SomeArgs; import com.android.internal.telecom.ICallScreeningAdapter; import com.android.internal.telecom.ICallScreeningService; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * This service can be implemented by the default dialer (see * {@link TelecomManager#getDefaultDialerPackage()}) or a third party app to allow or disallow Loading Loading @@ -132,7 +139,10 @@ public abstract class CallScreeningService extends Service { .createFromParcelableCall((ParcelableCall) args.arg2); onScreenCall(callDetails); if (callDetails.getCallDirection() == Call.Details.DIRECTION_OUTGOING) { mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId()); mCallScreeningAdapter.onScreeningResponse( callDetails.getTelecomCallId(), new ComponentName(getPackageName(), getClass().getName()), null); } } catch (RemoteException e) { Log.w(this, "Exception when screening call: " + e); Loading @@ -157,16 +167,171 @@ public abstract class CallScreeningService extends Service { private ICallScreeningAdapter mCallScreeningAdapter; /* * Information about how to respond to an incoming call. /** * Parcelable version of {@link CallResponse} used to do IPC. * @hide */ public static class ParcelableCallResponse implements Parcelable { private final boolean mShouldDisallowCall; private final boolean mShouldRejectCall; private final boolean mShouldSilenceCall; private final boolean mShouldSkipCallLog; private final boolean mShouldSkipNotification; private final boolean mShouldScreenCallViaAudioProcessing; private final int mCallComposerAttachmentsToShow; private ParcelableCallResponse( boolean shouldDisallowCall, boolean shouldRejectCall, boolean shouldSilenceCall, boolean shouldSkipCallLog, boolean shouldSkipNotification, boolean shouldScreenCallViaAudioProcessing, int callComposerAttachmentsToShow) { mShouldDisallowCall = shouldDisallowCall; mShouldRejectCall = shouldRejectCall; mShouldSilenceCall = shouldSilenceCall; mShouldSkipCallLog = shouldSkipCallLog; mShouldSkipNotification = shouldSkipNotification; mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing; mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; } protected ParcelableCallResponse(Parcel in) { mShouldDisallowCall = in.readBoolean(); mShouldRejectCall = in.readBoolean(); mShouldSilenceCall = in.readBoolean(); mShouldSkipCallLog = in.readBoolean(); mShouldSkipNotification = in.readBoolean(); mShouldScreenCallViaAudioProcessing = in.readBoolean(); mCallComposerAttachmentsToShow = in.readInt(); } public CallResponse toCallResponse() { return new CallResponse.Builder() .setDisallowCall(mShouldDisallowCall) .setRejectCall(mShouldRejectCall) .setSilenceCall(mShouldSilenceCall) .setSkipCallLog(mShouldSkipCallLog) .setSkipNotification(mShouldSkipNotification) .setShouldScreenCallViaAudioProcessing(mShouldScreenCallViaAudioProcessing) .setCallComposerAttachmentsToShow(mCallComposerAttachmentsToShow) .build(); } public boolean shouldDisallowCall() { return mShouldDisallowCall; } public boolean shouldRejectCall() { return mShouldRejectCall; } public boolean shouldSilenceCall() { return mShouldSilenceCall; } public boolean shouldSkipCallLog() { return mShouldSkipCallLog; } public boolean shouldSkipNotification() { return mShouldSkipNotification; } public boolean shouldScreenCallViaAudioProcessing() { return mShouldScreenCallViaAudioProcessing; } public int getCallComposerAttachmentsToShow() { return mCallComposerAttachmentsToShow; } public static final Creator<ParcelableCallResponse> CREATOR = new Creator<ParcelableCallResponse>() { @Override public ParcelableCallResponse createFromParcel(Parcel in) { return new ParcelableCallResponse(in); } @Override public ParcelableCallResponse[] newArray(int size) { return new ParcelableCallResponse[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeBoolean(mShouldDisallowCall); dest.writeBoolean(mShouldRejectCall); dest.writeBoolean(mShouldSilenceCall); dest.writeBoolean(mShouldSkipCallLog); dest.writeBoolean(mShouldSkipNotification); dest.writeBoolean(mShouldScreenCallViaAudioProcessing); dest.writeInt(mCallComposerAttachmentsToShow); } } /** * Information about how to respond to an incoming call. Call screening apps can construct an * instance of this class using {@link CallResponse.Builder}. */ public static class CallResponse { /** * Bit flag indicating whether to show the picture attachment for call composer. * * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. */ public static final int CALL_COMPOSER_ATTACHMENT_PICTURE = 1; /** * Bit flag indicating whether to show the location attachment for call composer. * * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. */ public static final int CALL_COMPOSER_ATTACHMENT_LOCATION = 1 << 1; /** * Bit flag indicating whether to show the subject attachment for call composer. * * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. */ public static final int CALL_COMPOSER_ATTACHMENT_SUBJECT = 1 << 2; /** * Bit flag indicating whether to show the priority attachment for call composer. * * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. */ public static final int CALL_COMPOSER_ATTACHMENT_PRIORITY = 1 << 3; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "CALL_COMPOSER_ATTACHMENT_", flag = true, value = { CALL_COMPOSER_ATTACHMENT_PICTURE, CALL_COMPOSER_ATTACHMENT_LOCATION, CALL_COMPOSER_ATTACHMENT_SUBJECT, CALL_COMPOSER_ATTACHMENT_PRIORITY } ) public @interface CallComposerAttachmentType {} private static final int NUM_CALL_COMPOSER_ATTACHMENT_TYPES = 4; private final boolean mShouldDisallowCall; private final boolean mShouldRejectCall; private final boolean mShouldSilenceCall; private final boolean mShouldSkipCallLog; private final boolean mShouldSkipNotification; private final boolean mShouldScreenCallViaAudioProcessing; private final int mCallComposerAttachmentsToShow; private CallResponse( boolean shouldDisallowCall, Loading @@ -174,7 +339,8 @@ public abstract class CallScreeningService extends Service { boolean shouldSilenceCall, boolean shouldSkipCallLog, boolean shouldSkipNotification, boolean shouldScreenCallViaAudioProcessing) { boolean shouldScreenCallViaAudioProcessing, int callComposerAttachmentsToShow) { if (!shouldDisallowCall && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) { throw new IllegalStateException("Invalid response state for allowed call."); Loading @@ -190,6 +356,7 @@ public abstract class CallScreeningService extends Service { mShouldSkipNotification = shouldSkipNotification; mShouldSilenceCall = shouldSilenceCall; mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing; mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; } /* Loading Loading @@ -237,6 +404,49 @@ public abstract class CallScreeningService extends Service { return mShouldScreenCallViaAudioProcessing; } /** * @return A bitmask of call composer attachments that should be shown to the user. */ public @CallComposerAttachmentType int getCallComposerAttachmentsToShow() { return mCallComposerAttachmentsToShow; } /** @hide */ public ParcelableCallResponse toParcelable() { return new ParcelableCallResponse( mShouldDisallowCall, mShouldRejectCall, mShouldSilenceCall, mShouldSkipCallLog, mShouldSkipNotification, mShouldScreenCallViaAudioProcessing, mCallComposerAttachmentsToShow ); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CallResponse that = (CallResponse) o; return mShouldDisallowCall == that.mShouldDisallowCall && mShouldRejectCall == that.mShouldRejectCall && mShouldSilenceCall == that.mShouldSilenceCall && mShouldSkipCallLog == that.mShouldSkipCallLog && mShouldSkipNotification == that.mShouldSkipNotification && mShouldScreenCallViaAudioProcessing == that.mShouldScreenCallViaAudioProcessing && mCallComposerAttachmentsToShow == that.mCallComposerAttachmentsToShow; } @Override public int hashCode() { return Objects.hash(mShouldDisallowCall, mShouldRejectCall, mShouldSilenceCall, mShouldSkipCallLog, mShouldSkipNotification, mShouldScreenCallViaAudioProcessing, mCallComposerAttachmentsToShow); } public static class Builder { private boolean mShouldDisallowCall; private boolean mShouldRejectCall; Loading @@ -244,6 +454,7 @@ public abstract class CallScreeningService extends Service { private boolean mShouldSkipCallLog; private boolean mShouldSkipNotification; private boolean mShouldScreenCallViaAudioProcessing; private int mCallComposerAttachmentsToShow = -1; /** * Sets whether the incoming call should be blocked. Loading Loading @@ -329,6 +540,38 @@ public abstract class CallScreeningService extends Service { return this; } /** * Sets the call composer attachments that should be shown to the user. * * Attachments that are not shown will not be passed to the in-call UI responsible for * displaying the call to the user. * * If this method is not called on a {@link Builder}, all attachments will be shown, * except pictures, which will only be shown to users if the call is from a contact. * * Setting attachments to show will have no effect if the call screening service does * not belong to the same package as the system dialer (as returned by * {@link TelecomManager#getSystemDialerPackage()}). * * @param callComposerAttachmentsToShow A bitmask of call composer attachments to show. */ public @NonNull Builder setCallComposerAttachmentsToShow( @CallComposerAttachmentType int callComposerAttachmentsToShow) { // If the argument is less than zero (meaning unset), no-op since the conversion // to/from the parcelable version may call with that value. if (callComposerAttachmentsToShow < 0) { return this; } if ((callComposerAttachmentsToShow & (1 << NUM_CALL_COMPOSER_ATTACHMENT_TYPES)) != 0) { throw new IllegalArgumentException("Attachment types must match the ones" + " defined in CallResponse"); } mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; return this; } public CallResponse build() { return new CallResponse( mShouldDisallowCall, Loading @@ -336,7 +579,8 @@ public abstract class CallScreeningService extends Service { mShouldSilenceCall, mShouldSkipCallLog, mShouldSkipNotification, mShouldScreenCallViaAudioProcessing); mShouldScreenCallViaAudioProcessing, mCallComposerAttachmentsToShow); } } } Loading Loading @@ -423,21 +667,12 @@ public abstract class CallScreeningService extends Service { public final void respondToCall(@NonNull Call.Details callDetails, @NonNull CallResponse response) { try { if (response.getDisallowCall()) { mCallScreeningAdapter.disallowCall( mCallScreeningAdapter.onScreeningResponse( callDetails.getTelecomCallId(), response.getRejectCall(), !response.getSkipCallLog(), !response.getSkipNotification(), new ComponentName(getPackageName(), getClass().getName())); } else if (response.getSilenceCall()) { mCallScreeningAdapter.silenceCall(callDetails.getTelecomCallId()); } else if (response.getShouldScreenCallViaAudioProcessing()) { mCallScreeningAdapter.screenCallFurther(callDetails.getTelecomCallId()); } else { mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId()); } new ComponentName(getPackageName(), getClass().getName()), response.toParcelable()); } catch (RemoteException e) { Log.e(this, e, "Got remote exception when returning response"); } } } telecomm/java/android/telecom/Connection.java +10 −1 Original line number Diff line number Diff line Loading @@ -3390,11 +3390,20 @@ public abstract class Connection extends Conferenceable { * {@code true}, {@link #onDisconnect()} will be called soon after * this is called. * @param isInContacts Indicates whether the caller is in the user's contacts list. * @param callScreeningResponse The response that was returned from the * {@link CallScreeningService} that handled this call. If no * response was received from a call screening service, * this will be {@code null}. * @param isResponseFromSystemDialer Whether {@code callScreeningResponse} was sent from the * system dialer. If {@code callScreeningResponse} is * {@code null}, this will be {@code false}. * @hide */ @SystemApi @RequiresPermission(Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts) { } public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts, @Nullable CallScreeningService.CallResponse callScreeningResponse, boolean isResponseFromSystemDialer) { } static String toLogSafePhoneNumber(String number) { // For unknown number, log empty string. Loading Loading
core/api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -39207,16 +39207,22 @@ package android.telecom { } public static class CallScreeningService.CallResponse { method public int getCallComposerAttachmentsToShow(); method public boolean getDisallowCall(); method public boolean getRejectCall(); method public boolean getSilenceCall(); method public boolean getSkipCallLog(); method public boolean getSkipNotification(); field public static final int CALL_COMPOSER_ATTACHMENT_LOCATION = 2; // 0x2 field public static final int CALL_COMPOSER_ATTACHMENT_PICTURE = 1; // 0x1 field public static final int CALL_COMPOSER_ATTACHMENT_PRIORITY = 8; // 0x8 field public static final int CALL_COMPOSER_ATTACHMENT_SUBJECT = 4; // 0x4 } public static class CallScreeningService.CallResponse.Builder { ctor public CallScreeningService.CallResponse.Builder(); method public android.telecom.CallScreeningService.CallResponse build(); method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setCallComposerAttachmentsToShow(int); method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean); method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean); method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setSilenceCall(boolean);
core/api/system-current.txt +2 −2 Original line number Diff line number Diff line Loading @@ -10769,7 +10769,7 @@ package android.telecom { method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle(); method @Nullable public final String getTelecomCallId(); method @Deprecated public void onAudioStateChanged(android.telecom.AudioState); method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean); method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, boolean); method public final void resetConnectionTime(); method public void setCallDirection(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectTimeMillis(@IntRange(from=0) long); Loading Loading @@ -10946,7 +10946,7 @@ package android.telecom { } public final class RemoteConnection { method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean); method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, boolean); method @Deprecated public void setAudioState(android.telecom.AudioState); }
telecomm/java/android/telecom/CallScreeningService.aidl 0 → 100644 +22 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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; /** * {@hide} */ parcelable CallScreeningService.ParcelableCallResponse;
telecomm/java/android/telecom/CallScreeningService.java +254 −19 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.telecom; import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; Loading @@ -30,12 +31,18 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import com.android.internal.os.SomeArgs; import com.android.internal.telecom.ICallScreeningAdapter; import com.android.internal.telecom.ICallScreeningService; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * This service can be implemented by the default dialer (see * {@link TelecomManager#getDefaultDialerPackage()}) or a third party app to allow or disallow Loading Loading @@ -132,7 +139,10 @@ public abstract class CallScreeningService extends Service { .createFromParcelableCall((ParcelableCall) args.arg2); onScreenCall(callDetails); if (callDetails.getCallDirection() == Call.Details.DIRECTION_OUTGOING) { mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId()); mCallScreeningAdapter.onScreeningResponse( callDetails.getTelecomCallId(), new ComponentName(getPackageName(), getClass().getName()), null); } } catch (RemoteException e) { Log.w(this, "Exception when screening call: " + e); Loading @@ -157,16 +167,171 @@ public abstract class CallScreeningService extends Service { private ICallScreeningAdapter mCallScreeningAdapter; /* * Information about how to respond to an incoming call. /** * Parcelable version of {@link CallResponse} used to do IPC. * @hide */ public static class ParcelableCallResponse implements Parcelable { private final boolean mShouldDisallowCall; private final boolean mShouldRejectCall; private final boolean mShouldSilenceCall; private final boolean mShouldSkipCallLog; private final boolean mShouldSkipNotification; private final boolean mShouldScreenCallViaAudioProcessing; private final int mCallComposerAttachmentsToShow; private ParcelableCallResponse( boolean shouldDisallowCall, boolean shouldRejectCall, boolean shouldSilenceCall, boolean shouldSkipCallLog, boolean shouldSkipNotification, boolean shouldScreenCallViaAudioProcessing, int callComposerAttachmentsToShow) { mShouldDisallowCall = shouldDisallowCall; mShouldRejectCall = shouldRejectCall; mShouldSilenceCall = shouldSilenceCall; mShouldSkipCallLog = shouldSkipCallLog; mShouldSkipNotification = shouldSkipNotification; mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing; mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; } protected ParcelableCallResponse(Parcel in) { mShouldDisallowCall = in.readBoolean(); mShouldRejectCall = in.readBoolean(); mShouldSilenceCall = in.readBoolean(); mShouldSkipCallLog = in.readBoolean(); mShouldSkipNotification = in.readBoolean(); mShouldScreenCallViaAudioProcessing = in.readBoolean(); mCallComposerAttachmentsToShow = in.readInt(); } public CallResponse toCallResponse() { return new CallResponse.Builder() .setDisallowCall(mShouldDisallowCall) .setRejectCall(mShouldRejectCall) .setSilenceCall(mShouldSilenceCall) .setSkipCallLog(mShouldSkipCallLog) .setSkipNotification(mShouldSkipNotification) .setShouldScreenCallViaAudioProcessing(mShouldScreenCallViaAudioProcessing) .setCallComposerAttachmentsToShow(mCallComposerAttachmentsToShow) .build(); } public boolean shouldDisallowCall() { return mShouldDisallowCall; } public boolean shouldRejectCall() { return mShouldRejectCall; } public boolean shouldSilenceCall() { return mShouldSilenceCall; } public boolean shouldSkipCallLog() { return mShouldSkipCallLog; } public boolean shouldSkipNotification() { return mShouldSkipNotification; } public boolean shouldScreenCallViaAudioProcessing() { return mShouldScreenCallViaAudioProcessing; } public int getCallComposerAttachmentsToShow() { return mCallComposerAttachmentsToShow; } public static final Creator<ParcelableCallResponse> CREATOR = new Creator<ParcelableCallResponse>() { @Override public ParcelableCallResponse createFromParcel(Parcel in) { return new ParcelableCallResponse(in); } @Override public ParcelableCallResponse[] newArray(int size) { return new ParcelableCallResponse[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeBoolean(mShouldDisallowCall); dest.writeBoolean(mShouldRejectCall); dest.writeBoolean(mShouldSilenceCall); dest.writeBoolean(mShouldSkipCallLog); dest.writeBoolean(mShouldSkipNotification); dest.writeBoolean(mShouldScreenCallViaAudioProcessing); dest.writeInt(mCallComposerAttachmentsToShow); } } /** * Information about how to respond to an incoming call. Call screening apps can construct an * instance of this class using {@link CallResponse.Builder}. */ public static class CallResponse { /** * Bit flag indicating whether to show the picture attachment for call composer. * * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. */ public static final int CALL_COMPOSER_ATTACHMENT_PICTURE = 1; /** * Bit flag indicating whether to show the location attachment for call composer. * * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. */ public static final int CALL_COMPOSER_ATTACHMENT_LOCATION = 1 << 1; /** * Bit flag indicating whether to show the subject attachment for call composer. * * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. */ public static final int CALL_COMPOSER_ATTACHMENT_SUBJECT = 1 << 2; /** * Bit flag indicating whether to show the priority attachment for call composer. * * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. */ public static final int CALL_COMPOSER_ATTACHMENT_PRIORITY = 1 << 3; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "CALL_COMPOSER_ATTACHMENT_", flag = true, value = { CALL_COMPOSER_ATTACHMENT_PICTURE, CALL_COMPOSER_ATTACHMENT_LOCATION, CALL_COMPOSER_ATTACHMENT_SUBJECT, CALL_COMPOSER_ATTACHMENT_PRIORITY } ) public @interface CallComposerAttachmentType {} private static final int NUM_CALL_COMPOSER_ATTACHMENT_TYPES = 4; private final boolean mShouldDisallowCall; private final boolean mShouldRejectCall; private final boolean mShouldSilenceCall; private final boolean mShouldSkipCallLog; private final boolean mShouldSkipNotification; private final boolean mShouldScreenCallViaAudioProcessing; private final int mCallComposerAttachmentsToShow; private CallResponse( boolean shouldDisallowCall, Loading @@ -174,7 +339,8 @@ public abstract class CallScreeningService extends Service { boolean shouldSilenceCall, boolean shouldSkipCallLog, boolean shouldSkipNotification, boolean shouldScreenCallViaAudioProcessing) { boolean shouldScreenCallViaAudioProcessing, int callComposerAttachmentsToShow) { if (!shouldDisallowCall && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) { throw new IllegalStateException("Invalid response state for allowed call."); Loading @@ -190,6 +356,7 @@ public abstract class CallScreeningService extends Service { mShouldSkipNotification = shouldSkipNotification; mShouldSilenceCall = shouldSilenceCall; mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing; mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; } /* Loading Loading @@ -237,6 +404,49 @@ public abstract class CallScreeningService extends Service { return mShouldScreenCallViaAudioProcessing; } /** * @return A bitmask of call composer attachments that should be shown to the user. */ public @CallComposerAttachmentType int getCallComposerAttachmentsToShow() { return mCallComposerAttachmentsToShow; } /** @hide */ public ParcelableCallResponse toParcelable() { return new ParcelableCallResponse( mShouldDisallowCall, mShouldRejectCall, mShouldSilenceCall, mShouldSkipCallLog, mShouldSkipNotification, mShouldScreenCallViaAudioProcessing, mCallComposerAttachmentsToShow ); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CallResponse that = (CallResponse) o; return mShouldDisallowCall == that.mShouldDisallowCall && mShouldRejectCall == that.mShouldRejectCall && mShouldSilenceCall == that.mShouldSilenceCall && mShouldSkipCallLog == that.mShouldSkipCallLog && mShouldSkipNotification == that.mShouldSkipNotification && mShouldScreenCallViaAudioProcessing == that.mShouldScreenCallViaAudioProcessing && mCallComposerAttachmentsToShow == that.mCallComposerAttachmentsToShow; } @Override public int hashCode() { return Objects.hash(mShouldDisallowCall, mShouldRejectCall, mShouldSilenceCall, mShouldSkipCallLog, mShouldSkipNotification, mShouldScreenCallViaAudioProcessing, mCallComposerAttachmentsToShow); } public static class Builder { private boolean mShouldDisallowCall; private boolean mShouldRejectCall; Loading @@ -244,6 +454,7 @@ public abstract class CallScreeningService extends Service { private boolean mShouldSkipCallLog; private boolean mShouldSkipNotification; private boolean mShouldScreenCallViaAudioProcessing; private int mCallComposerAttachmentsToShow = -1; /** * Sets whether the incoming call should be blocked. Loading Loading @@ -329,6 +540,38 @@ public abstract class CallScreeningService extends Service { return this; } /** * Sets the call composer attachments that should be shown to the user. * * Attachments that are not shown will not be passed to the in-call UI responsible for * displaying the call to the user. * * If this method is not called on a {@link Builder}, all attachments will be shown, * except pictures, which will only be shown to users if the call is from a contact. * * Setting attachments to show will have no effect if the call screening service does * not belong to the same package as the system dialer (as returned by * {@link TelecomManager#getSystemDialerPackage()}). * * @param callComposerAttachmentsToShow A bitmask of call composer attachments to show. */ public @NonNull Builder setCallComposerAttachmentsToShow( @CallComposerAttachmentType int callComposerAttachmentsToShow) { // If the argument is less than zero (meaning unset), no-op since the conversion // to/from the parcelable version may call with that value. if (callComposerAttachmentsToShow < 0) { return this; } if ((callComposerAttachmentsToShow & (1 << NUM_CALL_COMPOSER_ATTACHMENT_TYPES)) != 0) { throw new IllegalArgumentException("Attachment types must match the ones" + " defined in CallResponse"); } mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; return this; } public CallResponse build() { return new CallResponse( mShouldDisallowCall, Loading @@ -336,7 +579,8 @@ public abstract class CallScreeningService extends Service { mShouldSilenceCall, mShouldSkipCallLog, mShouldSkipNotification, mShouldScreenCallViaAudioProcessing); mShouldScreenCallViaAudioProcessing, mCallComposerAttachmentsToShow); } } } Loading Loading @@ -423,21 +667,12 @@ public abstract class CallScreeningService extends Service { public final void respondToCall(@NonNull Call.Details callDetails, @NonNull CallResponse response) { try { if (response.getDisallowCall()) { mCallScreeningAdapter.disallowCall( mCallScreeningAdapter.onScreeningResponse( callDetails.getTelecomCallId(), response.getRejectCall(), !response.getSkipCallLog(), !response.getSkipNotification(), new ComponentName(getPackageName(), getClass().getName())); } else if (response.getSilenceCall()) { mCallScreeningAdapter.silenceCall(callDetails.getTelecomCallId()); } else if (response.getShouldScreenCallViaAudioProcessing()) { mCallScreeningAdapter.screenCallFurther(callDetails.getTelecomCallId()); } else { mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId()); } new ComponentName(getPackageName(), getClass().getName()), response.toParcelable()); } catch (RemoteException e) { Log.e(this, e, "Got remote exception when returning response"); } } }
telecomm/java/android/telecom/Connection.java +10 −1 Original line number Diff line number Diff line Loading @@ -3390,11 +3390,20 @@ public abstract class Connection extends Conferenceable { * {@code true}, {@link #onDisconnect()} will be called soon after * this is called. * @param isInContacts Indicates whether the caller is in the user's contacts list. * @param callScreeningResponse The response that was returned from the * {@link CallScreeningService} that handled this call. If no * response was received from a call screening service, * this will be {@code null}. * @param isResponseFromSystemDialer Whether {@code callScreeningResponse} was sent from the * system dialer. If {@code callScreeningResponse} is * {@code null}, this will be {@code false}. * @hide */ @SystemApi @RequiresPermission(Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts) { } public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts, @Nullable CallScreeningService.CallResponse callScreeningResponse, boolean isResponseFromSystemDialer) { } static String toLogSafePhoneNumber(String number) { // For unknown number, log empty string. Loading