Refactor CallScreeningService's internal structure

Use a single AIDL method and perform logic in Telecom instead of slicing
up the call response on the client side.

Also pass through the call response to the connection service.

Bug: 179412110
Test: atest ConnectionServiceTest CallScreeningServiceTest
Change-Id: I878c0ce34142da104dc0e2795487b03a6bdacb5f
This commit is contained in:
Hall Liu
2021-02-04 13:09:45 -08:00
parent 191b3b9db5
commit 5efe997539
8 changed files with 215 additions and 38 deletions

View File

@@ -30,12 +30,16 @@ 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.util.Objects;
/**
* This service can be implemented by the default dialer (see
* {@link TelecomManager#getDefaultDialerPackage()}) or a third party app to allow or disallow
@@ -132,7 +136,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);
@@ -157,6 +164,106 @@ public abstract class CallScreeningService extends Service {
private ICallScreeningAdapter mCallScreeningAdapter;
/**
* 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 ParcelableCallResponse(
boolean shouldDisallowCall,
boolean shouldRejectCall,
boolean shouldSilenceCall,
boolean shouldSkipCallLog,
boolean shouldSkipNotification,
boolean shouldScreenCallViaAudioProcessing) {
mShouldDisallowCall = shouldDisallowCall;
mShouldRejectCall = shouldRejectCall;
mShouldSilenceCall = shouldSilenceCall;
mShouldSkipCallLog = shouldSkipCallLog;
mShouldSkipNotification = shouldSkipNotification;
mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing;
}
protected ParcelableCallResponse(Parcel in) {
mShouldDisallowCall = in.readBoolean();
mShouldRejectCall = in.readBoolean();
mShouldSilenceCall = in.readBoolean();
mShouldSkipCallLog = in.readBoolean();
mShouldSkipNotification = in.readBoolean();
mShouldScreenCallViaAudioProcessing = in.readBoolean();
}
public CallResponse toCallResponse() {
return new CallResponse.Builder()
.setDisallowCall(mShouldDisallowCall)
.setRejectCall(mShouldRejectCall)
.setSilenceCall(mShouldSilenceCall)
.setSkipCallLog(mShouldSkipCallLog)
.setSkipNotification(mShouldSkipNotification)
.setShouldScreenCallViaAudioProcessing(mShouldScreenCallViaAudioProcessing)
.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 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);
}
}
/*
* Information about how to respond to an incoming call.
*/
@@ -237,6 +344,38 @@ public abstract class CallScreeningService extends Service {
return mShouldScreenCallViaAudioProcessing;
}
/** @hide */
public ParcelableCallResponse toParcelable() {
return new ParcelableCallResponse(
mShouldDisallowCall,
mShouldRejectCall,
mShouldSilenceCall,
mShouldSkipCallLog,
mShouldSkipNotification,
mShouldScreenCallViaAudioProcessing
);
}
@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;
}
@Override
public int hashCode() {
return Objects.hash(mShouldDisallowCall, mShouldRejectCall, mShouldSilenceCall,
mShouldSkipCallLog, mShouldSkipNotification,
mShouldScreenCallViaAudioProcessing);
}
public static class Builder {
private boolean mShouldDisallowCall;
private boolean mShouldRejectCall;
@@ -423,21 +562,12 @@ public abstract class CallScreeningService extends Service {
public final void respondToCall(@NonNull Call.Details callDetails,
@NonNull CallResponse response) {
try {
if (response.getDisallowCall()) {
mCallScreeningAdapter.disallowCall(
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());
}
mCallScreeningAdapter.onScreeningResponse(
callDetails.getTelecomCallId(),
new ComponentName(getPackageName(), getClass().getName()),
response.toParcelable());
} catch (RemoteException e) {
Log.e(this, e, "Got remote exception when returning response");
}
}
}