Loading src/com/android/server/telecom/callfiltering/CallFilteringResult.java +31 −3 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ public class CallFilteringResult { private boolean mShouldShowNotification; private boolean mShouldSilence = false; private boolean mShouldScreenViaAudio = false; private boolean mContactExists = false; private int mCallBlockReason = Calls.BLOCK_REASON_NOT_BLOCKED; private CharSequence mCallScreeningAppName = null; private String mCallScreeningComponentName = null; Loading Loading @@ -77,11 +78,30 @@ public class CallFilteringResult { return this; } public Builder setContactExists(boolean contactExists) { mContactExists = contactExists; return this; } public static Builder from(CallFilteringResult result) { return new Builder() .setShouldAllowCall(result.shouldAllowCall) .setShouldReject(result.shouldReject) .setShouldAddToCallLog(result.shouldAddToCallLog) .setShouldShowNotification(result.shouldShowNotification) .setShouldSilence(result.shouldSilence) .setCallBlockReason(result.mCallBlockReason) .setShouldScreenViaAudio(result.shouldScreenViaAudio) .setCallScreeningAppName(result.mCallScreeningAppName) .setCallScreeningComponentName(result.mCallScreeningComponentName) .setContactExists(result.contactExists); } public CallFilteringResult build() { return new CallFilteringResult(mShouldAllowCall, mShouldReject, mShouldSilence, mShouldAddToCallLog, mShouldShowNotification, mCallBlockReason, mCallScreeningAppName, mCallScreeningComponentName, mShouldScreenViaAudio); mCallScreeningAppName, mCallScreeningComponentName, mShouldScreenViaAudio, mContactExists); } } Loading @@ -94,11 +114,12 @@ public class CallFilteringResult { public int mCallBlockReason; public CharSequence mCallScreeningAppName; public String mCallScreeningComponentName; public boolean contactExists; private CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean shouldSilence, boolean shouldAddToCallLog, boolean shouldShowNotification, int callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName, boolean shouldScreenViaAudio) { boolean shouldScreenViaAudio, boolean contactExists) { this.shouldAllowCall = shouldAllowCall; this.shouldReject = shouldReject; this.shouldSilence = shouldSilence; Loading @@ -108,6 +129,7 @@ public class CallFilteringResult { this.mCallBlockReason = callBlockReason; this.mCallScreeningAppName = callScreeningAppName; this.mCallScreeningComponentName = callScreeningComponentName; this.contactExists = contactExists; } /** Loading Loading @@ -187,6 +209,7 @@ public class CallFilteringResult { .setCallBlockReason(callBlockReason) .setCallScreeningAppName(callScreeningAppName) .setCallScreeningComponentName(callScreeningComponentName) .setContactExists(contactExists || other.contactExists) .build(); } Loading @@ -204,6 +227,7 @@ public class CallFilteringResult { if (shouldAddToCallLog != that.shouldAddToCallLog) return false; if (shouldShowNotification != that.shouldShowNotification) return false; if (mCallBlockReason != that.mCallBlockReason) return false; if (contactExists != that.contactExists) return false; if ((TextUtils.isEmpty(mCallScreeningAppName) && TextUtils.isEmpty(that.mCallScreeningAppName)) && Loading Loading @@ -258,6 +282,10 @@ public class CallFilteringResult { sb.append(", notified"); } if (contactExists) { sb.append(", contact exists"); } if (mCallBlockReason != 0) { sb.append(", mCallBlockReason = "); sb.append(mCallBlockReason); Loading src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java +2 −2 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ import java.util.concurrent.Executor; public class IncomingCallFilterGraph { //TODO: Add logging for control flow. public static final String TAG = "IncomingCallFilterGraph"; public static final CallFilteringResult DEFAULT_SCREENING_RESULT = public static final CallFilteringResult DEFAULT_RESULT = new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) Loading Loading @@ -92,8 +92,8 @@ public class IncomingCallFilterGraph { mFinished = false; mContext = context; mTimeoutsAdapter = timeoutsAdapter; mCurrentResult = DEFAULT_SCREENING_RESULT; mLock = lock; mCurrentResult = DEFAULT_RESULT; } public void addFilter(CallFilter filter) { Loading src/com/android/server/telecom/callfiltering/NewCallScreeningServiceFilter.java 0 → 100644 +271 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 com.android.server.telecom.callfiltering; import static com.android.server.telecom.callfiltering.IncomingCallFilterGraph.DEFAULT_RESULT; import android.Manifest; import android.content.ComponentName; import android.content.Context; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.provider.CallLog; import android.telecom.Log; import android.telecom.TelecomManager; import com.android.internal.telecom.ICallScreeningAdapter; import com.android.internal.telecom.ICallScreeningService; import com.android.server.telecom.Call; import com.android.server.telecom.CallScreeningServiceHelper; import com.android.server.telecom.CallsManager; import com.android.server.telecom.ParcelableCallUtils; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; public class NewCallScreeningServiceFilter extends CallFilter { //TODO: Change the name of this class with CallScreeningServiceFilter public static final int PACKAGE_TYPE_CARRIER = 0; public static final int PACKAGE_TYPE_DEFAULT_DIALER = 1; public static final int PACKAGE_TYPE_USER_CHOSEN = 2; public static final long CALL_SCREENING_FILTER_TIMEOUT = 5000; private final Call mCall; private final String mPackageName; private final int mPackagetype; private PackageManager mPackageManager; private Context mContext; private CallScreeningServiceConnection mConnection; private final CallsManager mCallsManager; private CharSequence mAppName; private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter; private class CallScreeningAdapter extends ICallScreeningAdapter.Stub { private CompletableFuture<CallFilteringResult> mResultFuture; public CallScreeningAdapter(CompletableFuture<CallFilteringResult> resultFuture) { mResultFuture = resultFuture; } @Override public void allowCall(String callId) { Long token = Binder.clearCallingIdentity(); if (mCall == null || (!mCall.getId().equals(callId))) { Log.w(this, "allowCall, unknown call id: %s", callId); } mResultFuture.complete(DEFAULT_RESULT); Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } @Override public void disallowCall(String callId, boolean shouldReject, boolean shouldAddToCallLog, boolean shouldShowNotification, ComponentName componentName) { long token = Binder.clearCallingIdentity(); if (mCall != null && mCall.getId().equals(callId)) { mResultFuture.complete(new CallFilteringResult.Builder() .setShouldAllowCall(false) .setShouldReject(shouldReject) .setShouldSilence(false) .setShouldAddToCallLog(shouldAddToCallLog || packageTypeShouldAdd(mPackagetype)) .setShouldShowNotification(shouldShowNotification) .setCallBlockReason(CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) .setCallScreeningAppName(mAppName) .setCallScreeningComponentName(componentName.flattenToString()) .build()); } else { Log.w(this, "disallowCall, unknown call id: %s", callId); mResultFuture.complete(DEFAULT_RESULT); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } @Override public void silenceCall(String callId) { long token = Binder.clearCallingIdentity(); if (mCall != null && mCall.getId().equals(callId)) { mResultFuture.complete(new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) .setShouldSilence(true) .setShouldAddToCallLog(true) .setShouldShowNotification(true) .build()); } else { Log.w(this, "silenceCall, unknown call id: %s" , callId); mResultFuture.complete(DEFAULT_RESULT); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } @Override public void screenCallFurther(String callId) { long token = Binder.clearCallingIdentity(); if (mPackagetype != PACKAGE_TYPE_DEFAULT_DIALER) { throw new SecurityException("Only the default/system dialer may request screen via" + "background call audio"); } // TODO: add permission check for the additional role-based permission if (mCall != null && mCall.getId().equals(callId)) { mResultFuture.complete(new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) .setShouldSilence(false) .setShouldScreenViaAudio(true) .build()); } else { Log.w(this, "screenCallFurther, unknown call id: %s", callId); mResultFuture.complete(DEFAULT_RESULT); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } } private class CallScreeningServiceConnection implements ServiceConnection { private CompletableFuture<CallFilteringResult> mResultFuture; public CallScreeningServiceConnection(CompletableFuture<CallFilteringResult> resultFuture) { mResultFuture = resultFuture; } @Override public void onServiceConnected(ComponentName componentName, IBinder service) { ICallScreeningService callScreeningService = ICallScreeningService.Stub.asInterface(service); try { callScreeningService.screenCall(new CallScreeningAdapter(mResultFuture), mParcelableCallUtilsConverter. toParcelableCallForScreening(mCall, isSystemDialer())); } catch (RemoteException e) { Log.e(this, e, "Failed to set the call screening adapter"); mResultFuture.complete(DEFAULT_RESULT); } Log.i(this, "Binding completed."); } @Override public void onServiceDisconnected(ComponentName componentName) { mResultFuture.complete(DEFAULT_RESULT); Log.i(this, "Service disconnected."); } @Override public void onBindingDied(ComponentName name) { mResultFuture.complete(DEFAULT_RESULT); Log.i(this, "Binding died."); } @Override public void onNullBinding(ComponentName name) { mResultFuture.complete(DEFAULT_RESULT); Log.i(this, "Null binding."); } } public NewCallScreeningServiceFilter( Call call, String packageName, int packageType, Context context, CallsManager callsManager, CallScreeningServiceHelper.AppLabelProxy appLabelProxy, ParcelableCallUtils.Converter parcelableCallUtilsConverter) { super(); mCall = call; mPackageName = packageName; mPackagetype = packageType; mContext = context; mPackageManager = mContext.getPackageManager(); mCallsManager = callsManager; mAppName = appLabelProxy.getAppLabel(mPackageName); mParcelableCallUtilsConverter = parcelableCallUtilsConverter; } @Override public CompletionStage<CallFilteringResult> startFilterLookup(CallFilteringResult priorStageResult) { if (mPackageName == null) { return CompletableFuture.completedFuture(DEFAULT_RESULT); } if (!priorStageResult.shouldAllowCall) { // Call already blocked by other filters, no need to bind to call screening service. return CompletableFuture.completedFuture(DEFAULT_RESULT); } if (priorStageResult.contactExists && (!hasReadContactsPermission())) { // Binding to the call screening service will be skipped if it does NOT hold // READ_CONTACTS permission and the number is in the user’s contacts return CompletableFuture.completedFuture(DEFAULT_RESULT); } CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>(); bindCallScreeningService(resultFuture); return resultFuture; } private boolean hasReadContactsPermission() { int permission = PackageManager.PERMISSION_DENIED; if (mPackagetype == PACKAGE_TYPE_CARRIER || mPackagetype == PACKAGE_TYPE_DEFAULT_DIALER) { permission = PackageManager.PERMISSION_GRANTED; } else if (mPackageManager != null) { permission = mPackageManager.checkPermission(Manifest.permission.READ_CONTACTS, mPackageName); } return permission == PackageManager.PERMISSION_GRANTED; } private void bindCallScreeningService( CompletableFuture<CallFilteringResult> resultFuture) { mConnection = new CallScreeningServiceConnection(resultFuture); if (!CallScreeningServiceHelper.bindCallScreeningService(mContext, mCallsManager.getCurrentUserHandle(), mPackageName, mConnection)) { Log.i(this, "Call screening service binding failed."); resultFuture.complete(DEFAULT_RESULT); } } private void unbindCallScreeningService() { if (mConnection != null) { mContext.unbindService(mConnection); } mConnection = null; } private boolean isSystemDialer() { if (mPackagetype != PACKAGE_TYPE_DEFAULT_DIALER) { return false; } else { return mPackageName.equals(TelecomManager.from(mContext).getSystemDialerPackage()); } } private boolean packageTypeShouldAdd(int packageType) { return packageType == PACKAGE_TYPE_CARRIER; } } tests/src/com/android/server/telecom/tests/NewCallScreeningServiceFilterTest.java 0 → 100644 +320 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
src/com/android/server/telecom/callfiltering/CallFilteringResult.java +31 −3 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ public class CallFilteringResult { private boolean mShouldShowNotification; private boolean mShouldSilence = false; private boolean mShouldScreenViaAudio = false; private boolean mContactExists = false; private int mCallBlockReason = Calls.BLOCK_REASON_NOT_BLOCKED; private CharSequence mCallScreeningAppName = null; private String mCallScreeningComponentName = null; Loading Loading @@ -77,11 +78,30 @@ public class CallFilteringResult { return this; } public Builder setContactExists(boolean contactExists) { mContactExists = contactExists; return this; } public static Builder from(CallFilteringResult result) { return new Builder() .setShouldAllowCall(result.shouldAllowCall) .setShouldReject(result.shouldReject) .setShouldAddToCallLog(result.shouldAddToCallLog) .setShouldShowNotification(result.shouldShowNotification) .setShouldSilence(result.shouldSilence) .setCallBlockReason(result.mCallBlockReason) .setShouldScreenViaAudio(result.shouldScreenViaAudio) .setCallScreeningAppName(result.mCallScreeningAppName) .setCallScreeningComponentName(result.mCallScreeningComponentName) .setContactExists(result.contactExists); } public CallFilteringResult build() { return new CallFilteringResult(mShouldAllowCall, mShouldReject, mShouldSilence, mShouldAddToCallLog, mShouldShowNotification, mCallBlockReason, mCallScreeningAppName, mCallScreeningComponentName, mShouldScreenViaAudio); mCallScreeningAppName, mCallScreeningComponentName, mShouldScreenViaAudio, mContactExists); } } Loading @@ -94,11 +114,12 @@ public class CallFilteringResult { public int mCallBlockReason; public CharSequence mCallScreeningAppName; public String mCallScreeningComponentName; public boolean contactExists; private CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean shouldSilence, boolean shouldAddToCallLog, boolean shouldShowNotification, int callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName, boolean shouldScreenViaAudio) { boolean shouldScreenViaAudio, boolean contactExists) { this.shouldAllowCall = shouldAllowCall; this.shouldReject = shouldReject; this.shouldSilence = shouldSilence; Loading @@ -108,6 +129,7 @@ public class CallFilteringResult { this.mCallBlockReason = callBlockReason; this.mCallScreeningAppName = callScreeningAppName; this.mCallScreeningComponentName = callScreeningComponentName; this.contactExists = contactExists; } /** Loading Loading @@ -187,6 +209,7 @@ public class CallFilteringResult { .setCallBlockReason(callBlockReason) .setCallScreeningAppName(callScreeningAppName) .setCallScreeningComponentName(callScreeningComponentName) .setContactExists(contactExists || other.contactExists) .build(); } Loading @@ -204,6 +227,7 @@ public class CallFilteringResult { if (shouldAddToCallLog != that.shouldAddToCallLog) return false; if (shouldShowNotification != that.shouldShowNotification) return false; if (mCallBlockReason != that.mCallBlockReason) return false; if (contactExists != that.contactExists) return false; if ((TextUtils.isEmpty(mCallScreeningAppName) && TextUtils.isEmpty(that.mCallScreeningAppName)) && Loading Loading @@ -258,6 +282,10 @@ public class CallFilteringResult { sb.append(", notified"); } if (contactExists) { sb.append(", contact exists"); } if (mCallBlockReason != 0) { sb.append(", mCallBlockReason = "); sb.append(mCallBlockReason); Loading
src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java +2 −2 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ import java.util.concurrent.Executor; public class IncomingCallFilterGraph { //TODO: Add logging for control flow. public static final String TAG = "IncomingCallFilterGraph"; public static final CallFilteringResult DEFAULT_SCREENING_RESULT = public static final CallFilteringResult DEFAULT_RESULT = new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) Loading Loading @@ -92,8 +92,8 @@ public class IncomingCallFilterGraph { mFinished = false; mContext = context; mTimeoutsAdapter = timeoutsAdapter; mCurrentResult = DEFAULT_SCREENING_RESULT; mLock = lock; mCurrentResult = DEFAULT_RESULT; } public void addFilter(CallFilter filter) { Loading
src/com/android/server/telecom/callfiltering/NewCallScreeningServiceFilter.java 0 → 100644 +271 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 com.android.server.telecom.callfiltering; import static com.android.server.telecom.callfiltering.IncomingCallFilterGraph.DEFAULT_RESULT; import android.Manifest; import android.content.ComponentName; import android.content.Context; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.provider.CallLog; import android.telecom.Log; import android.telecom.TelecomManager; import com.android.internal.telecom.ICallScreeningAdapter; import com.android.internal.telecom.ICallScreeningService; import com.android.server.telecom.Call; import com.android.server.telecom.CallScreeningServiceHelper; import com.android.server.telecom.CallsManager; import com.android.server.telecom.ParcelableCallUtils; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; public class NewCallScreeningServiceFilter extends CallFilter { //TODO: Change the name of this class with CallScreeningServiceFilter public static final int PACKAGE_TYPE_CARRIER = 0; public static final int PACKAGE_TYPE_DEFAULT_DIALER = 1; public static final int PACKAGE_TYPE_USER_CHOSEN = 2; public static final long CALL_SCREENING_FILTER_TIMEOUT = 5000; private final Call mCall; private final String mPackageName; private final int mPackagetype; private PackageManager mPackageManager; private Context mContext; private CallScreeningServiceConnection mConnection; private final CallsManager mCallsManager; private CharSequence mAppName; private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter; private class CallScreeningAdapter extends ICallScreeningAdapter.Stub { private CompletableFuture<CallFilteringResult> mResultFuture; public CallScreeningAdapter(CompletableFuture<CallFilteringResult> resultFuture) { mResultFuture = resultFuture; } @Override public void allowCall(String callId) { Long token = Binder.clearCallingIdentity(); if (mCall == null || (!mCall.getId().equals(callId))) { Log.w(this, "allowCall, unknown call id: %s", callId); } mResultFuture.complete(DEFAULT_RESULT); Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } @Override public void disallowCall(String callId, boolean shouldReject, boolean shouldAddToCallLog, boolean shouldShowNotification, ComponentName componentName) { long token = Binder.clearCallingIdentity(); if (mCall != null && mCall.getId().equals(callId)) { mResultFuture.complete(new CallFilteringResult.Builder() .setShouldAllowCall(false) .setShouldReject(shouldReject) .setShouldSilence(false) .setShouldAddToCallLog(shouldAddToCallLog || packageTypeShouldAdd(mPackagetype)) .setShouldShowNotification(shouldShowNotification) .setCallBlockReason(CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) .setCallScreeningAppName(mAppName) .setCallScreeningComponentName(componentName.flattenToString()) .build()); } else { Log.w(this, "disallowCall, unknown call id: %s", callId); mResultFuture.complete(DEFAULT_RESULT); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } @Override public void silenceCall(String callId) { long token = Binder.clearCallingIdentity(); if (mCall != null && mCall.getId().equals(callId)) { mResultFuture.complete(new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) .setShouldSilence(true) .setShouldAddToCallLog(true) .setShouldShowNotification(true) .build()); } else { Log.w(this, "silenceCall, unknown call id: %s" , callId); mResultFuture.complete(DEFAULT_RESULT); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } @Override public void screenCallFurther(String callId) { long token = Binder.clearCallingIdentity(); if (mPackagetype != PACKAGE_TYPE_DEFAULT_DIALER) { throw new SecurityException("Only the default/system dialer may request screen via" + "background call audio"); } // TODO: add permission check for the additional role-based permission if (mCall != null && mCall.getId().equals(callId)) { mResultFuture.complete(new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) .setShouldSilence(false) .setShouldScreenViaAudio(true) .build()); } else { Log.w(this, "screenCallFurther, unknown call id: %s", callId); mResultFuture.complete(DEFAULT_RESULT); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } } private class CallScreeningServiceConnection implements ServiceConnection { private CompletableFuture<CallFilteringResult> mResultFuture; public CallScreeningServiceConnection(CompletableFuture<CallFilteringResult> resultFuture) { mResultFuture = resultFuture; } @Override public void onServiceConnected(ComponentName componentName, IBinder service) { ICallScreeningService callScreeningService = ICallScreeningService.Stub.asInterface(service); try { callScreeningService.screenCall(new CallScreeningAdapter(mResultFuture), mParcelableCallUtilsConverter. toParcelableCallForScreening(mCall, isSystemDialer())); } catch (RemoteException e) { Log.e(this, e, "Failed to set the call screening adapter"); mResultFuture.complete(DEFAULT_RESULT); } Log.i(this, "Binding completed."); } @Override public void onServiceDisconnected(ComponentName componentName) { mResultFuture.complete(DEFAULT_RESULT); Log.i(this, "Service disconnected."); } @Override public void onBindingDied(ComponentName name) { mResultFuture.complete(DEFAULT_RESULT); Log.i(this, "Binding died."); } @Override public void onNullBinding(ComponentName name) { mResultFuture.complete(DEFAULT_RESULT); Log.i(this, "Null binding."); } } public NewCallScreeningServiceFilter( Call call, String packageName, int packageType, Context context, CallsManager callsManager, CallScreeningServiceHelper.AppLabelProxy appLabelProxy, ParcelableCallUtils.Converter parcelableCallUtilsConverter) { super(); mCall = call; mPackageName = packageName; mPackagetype = packageType; mContext = context; mPackageManager = mContext.getPackageManager(); mCallsManager = callsManager; mAppName = appLabelProxy.getAppLabel(mPackageName); mParcelableCallUtilsConverter = parcelableCallUtilsConverter; } @Override public CompletionStage<CallFilteringResult> startFilterLookup(CallFilteringResult priorStageResult) { if (mPackageName == null) { return CompletableFuture.completedFuture(DEFAULT_RESULT); } if (!priorStageResult.shouldAllowCall) { // Call already blocked by other filters, no need to bind to call screening service. return CompletableFuture.completedFuture(DEFAULT_RESULT); } if (priorStageResult.contactExists && (!hasReadContactsPermission())) { // Binding to the call screening service will be skipped if it does NOT hold // READ_CONTACTS permission and the number is in the user’s contacts return CompletableFuture.completedFuture(DEFAULT_RESULT); } CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>(); bindCallScreeningService(resultFuture); return resultFuture; } private boolean hasReadContactsPermission() { int permission = PackageManager.PERMISSION_DENIED; if (mPackagetype == PACKAGE_TYPE_CARRIER || mPackagetype == PACKAGE_TYPE_DEFAULT_DIALER) { permission = PackageManager.PERMISSION_GRANTED; } else if (mPackageManager != null) { permission = mPackageManager.checkPermission(Manifest.permission.READ_CONTACTS, mPackageName); } return permission == PackageManager.PERMISSION_GRANTED; } private void bindCallScreeningService( CompletableFuture<CallFilteringResult> resultFuture) { mConnection = new CallScreeningServiceConnection(resultFuture); if (!CallScreeningServiceHelper.bindCallScreeningService(mContext, mCallsManager.getCurrentUserHandle(), mPackageName, mConnection)) { Log.i(this, "Call screening service binding failed."); resultFuture.complete(DEFAULT_RESULT); } } private void unbindCallScreeningService() { if (mConnection != null) { mContext.unbindService(mConnection); } mConnection = null; } private boolean isSystemDialer() { if (mPackagetype != PACKAGE_TYPE_DEFAULT_DIALER) { return false; } else { return mPackageName.equals(TelecomManager.from(mContext).getSystemDialerPackage()); } } private boolean packageTypeShouldAdd(int packageType) { return packageType == PACKAGE_TYPE_CARRIER; } }
tests/src/com/android/server/telecom/tests/NewCallScreeningServiceFilterTest.java 0 → 100644 +320 −0 File added.Preview size limit exceeded, changes collapsed. Show changes