Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 482556f2 authored by Grace Jia's avatar Grace Jia Committed by Gerrit Code Review
Browse files

Merge "Use IncomingCallFilterGraph to perform incoming call filters."

parents 0582d2ec b2449407
Loading
Loading
Loading
Loading
+72 −14
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -34,6 +35,7 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.Process;
@@ -75,14 +77,15 @@ import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter;
import com.android.server.telecom.callfiltering.BlockCheckerAdapter;
import com.android.server.telecom.callfiltering.BlockCheckerFilter;
import com.android.server.telecom.callfiltering.CallFilterResultCallback;
import com.android.server.telecom.callfiltering.CallFilteringResult;
import com.android.server.telecom.callfiltering.CallFilteringResult.Builder;
import com.android.server.telecom.callfiltering.CallScreeningServiceController;
import com.android.server.telecom.callfiltering.DirectToVoicemailCallFilter;
import com.android.server.telecom.callfiltering.DirectToVoicemailFilter;
import com.android.server.telecom.callfiltering.IncomingCallFilter;
import com.android.server.telecom.callfiltering.IncomingCallFilterGraph;
import com.android.server.telecom.callfiltering.NewCallScreeningServiceFilter;
import com.android.server.telecom.callredirection.CallRedirectionProcessor;
import com.android.server.telecom.components.ErrorDialogActivity;
import com.android.server.telecom.settings.BlockedNumbersUtil;
@@ -92,13 +95,13 @@ import com.android.server.telecom.ui.CallRedirectionTimeoutDialogActivity;
import com.android.server.telecom.ui.ConfirmCallDialogActivity;
import com.android.server.telecom.ui.IncomingCallNotifier;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -358,6 +361,8 @@ public class CallsManager extends Call.ListenerBase

    private Runnable mStopTone;

    private LinkedList<HandlerThread> mGraphHandlerThreads;

    /**
     * Listener to PhoneAccountRegistrar events.
     */
@@ -548,6 +553,7 @@ public class CallsManager extends Call.ListenerBase
                CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        intentFilter.addAction(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED);
        context.registerReceiver(mReceiver, intentFilter);
        mGraphHandlerThreads = new LinkedList<>();
    }

    public void setIncomingCallNotifier(IncomingCallNotifier incomingCallNotifier) {
@@ -631,14 +637,16 @@ public class CallsManager extends Call.ListenerBase
            return;
        }

        IncomingCallFilterGraph graph = setUpCallFilterGraph(incomingCall);
        graph.performFiltering();
    }

    private IncomingCallFilterGraph setUpCallFilterGraph(Call incomingCall) {
        incomingCall.setIsUsingCallFiltering(true);
        List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
        filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
        filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(),
                mCallerInfoLookupHelper, null));
        filters.add(new CallScreeningServiceController(mContext, this, mPhoneAccountRegistrar,
                new ParcelableCallUtils.Converter(), mLock,
                new TelecomServiceImpl.SettingsSecureAdapterImpl(), mCallerInfoLookupHelper,
        String carrierPackageName = getCarrierPackageName();
        String defaultDialerPackageName = TelecomManager.from(mContext).getDefaultDialerPackage();
        String userChosenPackageName = getRoleManagerAdapter().getDefaultCallScreeningApp();
        CallScreeningServiceHelper.AppLabelProxy appLabelProxy =
                new CallScreeningServiceHelper.AppLabelProxy() {
                    @Override
                    public CharSequence getAppLabel(String packageName) {
@@ -652,9 +660,53 @@ public class CallsManager extends Call.ListenerBase

                        return null;
                    }
                }));
        mIncomingCallFilterFactory.create(mContext, this, incomingCall, mLock,
                mTimeoutsAdapter, filters).performFiltering();
                };
        ParcelableCallUtils.Converter converter = new ParcelableCallUtils.Converter();

        IncomingCallFilterGraph graph = new IncomingCallFilterGraph(incomingCall,
                this::onCallFilteringComplete, mContext, mTimeoutsAdapter, mLock);
        DirectToVoicemailFilter voicemailFilter = new DirectToVoicemailFilter(incomingCall,
                mCallerInfoLookupHelper);
        BlockCheckerFilter blockCheckerFilter = new BlockCheckerFilter(mContext, incomingCall,
                mCallerInfoLookupHelper, new BlockCheckerAdapter());
        NewCallScreeningServiceFilter carrierCallScreeningServiceFilter =
                new NewCallScreeningServiceFilter(incomingCall, carrierPackageName,
                        NewCallScreeningServiceFilter.PACKAGE_TYPE_CARRIER, mContext, this,
                        appLabelProxy, converter);
        NewCallScreeningServiceFilter defaultDialerCallScreeningServiceFilter =
                new NewCallScreeningServiceFilter(incomingCall, defaultDialerPackageName,
                        NewCallScreeningServiceFilter.PACKAGE_TYPE_DEFAULT_DIALER, mContext, this,
                        appLabelProxy, converter);
        NewCallScreeningServiceFilter userChosenCallScreeningServiceFilter =
                new NewCallScreeningServiceFilter(incomingCall, userChosenPackageName,
                        NewCallScreeningServiceFilter.PACKAGE_TYPE_USER_CHOSEN, mContext, this,
                        appLabelProxy, converter);
        graph.addFilter(voicemailFilter);
        graph.addFilter(blockCheckerFilter);
        graph.addFilter(carrierCallScreeningServiceFilter);
        graph.addFilter(defaultDialerCallScreeningServiceFilter);
        graph.addFilter(userChosenCallScreeningServiceFilter);
        IncomingCallFilterGraph.addEdge(voicemailFilter, carrierCallScreeningServiceFilter);
        IncomingCallFilterGraph.addEdge(blockCheckerFilter, carrierCallScreeningServiceFilter);
        IncomingCallFilterGraph.addEdge(carrierCallScreeningServiceFilter,
                defaultDialerCallScreeningServiceFilter);
        IncomingCallFilterGraph.addEdge(carrierCallScreeningServiceFilter,
                userChosenCallScreeningServiceFilter);
        mGraphHandlerThreads.add(graph.getHandlerThread());
        return graph;
    }

    private String getCarrierPackageName() {
        ComponentName componentName = null;
        CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService
                (Context.CARRIER_CONFIG_SERVICE);
        PersistableBundle configBundle = configManager.getConfig();
        if (configBundle != null) {
            componentName = ComponentName.unflattenFromString(configBundle.getString
                    (CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, ""));
        }

        return componentName != null ? componentName.getPackageName() : null;
    }

    @Override
@@ -662,6 +714,8 @@ public class CallsManager extends Call.ListenerBase
        // Only set the incoming call as ringing if it isn't already disconnected. It is possible
        // that the connection service disconnected the call before it was even added to Telecom, in
        // which case it makes no sense to set it back to a ringing state.
        mGraphHandlerThreads.clear();

        if (incomingCall.getState() != CallState.DISCONNECTED &&
                incomingCall.getState() != CallState.DISCONNECTING) {
            setCallState(incomingCall, CallState.RINGING,
@@ -4778,4 +4832,8 @@ public class CallsManager extends Call.ListenerBase
                .filter(c -> phoneAccount.getAccountHandle().equals(c.getTargetPhoneAccount()))
                .forEach(c -> c.setVideoCallingSupportedByPhoneAccount(isVideoNowSupported));
    }

    public LinkedList<HandlerThread> getGraphHandlerThreads() {
        return mGraphHandlerThreads;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ public class CallFilteringResult {
                .setShouldAddToCallLog(shouldAddToCallLog && other.shouldAddToCallLog)
                .setShouldShowNotification(shouldShowNotification && other.shouldShowNotification)
                .setShouldScreenViaAudio(shouldScreenViaAudio || other.shouldScreenViaAudio)
                .setContactExists(contactExists || other.contactExists)
                .build();
    }

+10 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.telecom.Logging.Runnable;

import com.android.server.telecom.Call;
import com.android.server.telecom.LoggedHandlerExecutor;
import com.android.server.telecom.LogUtils;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;

@@ -62,6 +63,7 @@ public class IncomingCallFilterGraph {
        }

        public CallFilteringResult whenDone(CallFilteringResult result) {
            Log.i(TAG, "Filter %s done, result: %s.", mFilter, result);
            mFilter.result = result;
            for (CallFilter filter : mFilter.getFollowings()) {
                if (filter.decrementAndGetIndegree() == 0) {
@@ -72,6 +74,7 @@ public class IncomingCallFilterGraph {
                synchronized (mLock) {
                    mFinished = true;
                    mListener.onCallFilteringComplete(mCall, result);
                    Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, result);
                }
                mHandlerThread.quit();
            }
@@ -100,7 +103,7 @@ public class IncomingCallFilterGraph {
    }

    public void performFiltering() {

        Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED);
        CallFilter dummyStart = new CallFilter();
        mDummyComplete = new CallFilter();

@@ -118,6 +121,7 @@ public class IncomingCallFilterGraph {
            public void loggedRun() {
                if (!mFinished) {
                    Log.i(this, "Graph timed out when performing filtering.");
                    Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT);
                    mListener.onCallFilteringComplete(mCall, mCurrentResult);
                    mFinished = true;
                    mHandlerThread.quit();
@@ -148,10 +152,15 @@ public class IncomingCallFilterGraph {
                new LoggedHandlerExecutor(mHandler, "ICFG.sF", null))
                .thenApplyAsync(postFilterTask::whenDone,
                        new LoggedHandlerExecutor(mHandler, "ICFG.sF", null));
        Log.i(TAG, "Filter %s scheduled.", filter);
    }

    public static void addEdge(CallFilter before, CallFilter after) {
        before.addFollowings(after);
        after.addDependency(before);
    }

    public HandlerThread getHandlerThread() {
        return mHandlerThread;
    }
}
+19 −17
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

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;
@@ -70,7 +68,7 @@ public class NewCallScreeningServiceFilter extends CallFilter {
            if (mCall == null || (!mCall.getId().equals(callId))) {
                Log.w(this, "allowCall, unknown call id: %s", callId);
            }
            mResultFuture.complete(DEFAULT_RESULT);
            mResultFuture.complete(mPriorStageResult);
            Binder.restoreCallingIdentity(token);
            unbindCallScreeningService();
        }
@@ -91,10 +89,11 @@ public class NewCallScreeningServiceFilter extends CallFilter {
                        .setCallBlockReason(CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE)
                        .setCallScreeningAppName(mAppName)
                        .setCallScreeningComponentName(componentName.flattenToString())
                        .setContactExists(mPriorStageResult.contactExists)
                        .build());
            } else {
                Log.w(this, "disallowCall, unknown call id: %s", callId);
                mResultFuture.complete(DEFAULT_RESULT);
                mResultFuture.complete(mPriorStageResult);
            }
            Binder.restoreCallingIdentity(token);
            unbindCallScreeningService();
@@ -110,10 +109,11 @@ public class NewCallScreeningServiceFilter extends CallFilter {
                        .setShouldSilence(true)
                        .setShouldAddToCallLog(true)
                        .setShouldShowNotification(true)
                        .setContactExists(mPriorStageResult.contactExists)
                        .build());
            } else {
                Log.w(this, "silenceCall, unknown call id: %s" , callId);
                mResultFuture.complete(DEFAULT_RESULT);
                mResultFuture.complete(mPriorStageResult);
            }
            Binder.restoreCallingIdentity(token);
            unbindCallScreeningService();
@@ -134,10 +134,11 @@ public class NewCallScreeningServiceFilter extends CallFilter {
                        .setShouldReject(false)
                        .setShouldSilence(false)
                        .setShouldScreenViaAudio(true)
                        .setContactExists(mPriorStageResult.contactExists)
                        .build());
            } else {
                Log.w(this, "screenCallFurther, unknown call id: %s", callId);
                mResultFuture.complete(DEFAULT_RESULT);
                mResultFuture.complete(mPriorStageResult);
            }
            Binder.restoreCallingIdentity(token);
            unbindCallScreeningService();
@@ -162,26 +163,26 @@ public class NewCallScreeningServiceFilter extends CallFilter {
                                toParcelableCallForScreening(mCall, isSystemDialer()));
            } catch (RemoteException e) {
                Log.e(this, e, "Failed to set the call screening adapter");
                mResultFuture.complete(DEFAULT_RESULT);
                mResultFuture.complete(mPriorStageResult);
            }
            Log.i(this, "Binding completed.");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mResultFuture.complete(DEFAULT_RESULT);
            mResultFuture.complete(mPriorStageResult);
            Log.i(this, "Service disconnected.");
        }

        @Override
        public void onBindingDied(ComponentName name) {
            mResultFuture.complete(DEFAULT_RESULT);
            mResultFuture.complete(mPriorStageResult);
            Log.i(this, "Binding died.");
        }

        @Override
        public void onNullBinding(ComponentName name) {
            mResultFuture.complete(DEFAULT_RESULT);
            mResultFuture.complete(mPriorStageResult);
            Log.i(this, "Null binding.");
        }
    }
@@ -206,20 +207,22 @@ public class NewCallScreeningServiceFilter extends CallFilter {
    }

    @Override
    public CompletionStage<CallFilteringResult> startFilterLookup(CallFilteringResult priorStageResult) {
    public CompletionStage<CallFilteringResult> startFilterLookup(
            CallFilteringResult priorStageResult) {
        mPriorStageResult = priorStageResult;
        if (mPackageName == null) {
            return CompletableFuture.completedFuture(DEFAULT_RESULT);
            return CompletableFuture.completedFuture(priorStageResult);
        }

        if (!priorStageResult.shouldAllowCall) {
            // Call already blocked by other filters, no need to bind to call screening service.
            return CompletableFuture.completedFuture(DEFAULT_RESULT);
            return CompletableFuture.completedFuture(priorStageResult);
        }

        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);
            return CompletableFuture.completedFuture(priorStageResult);
        }

        CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>();
@@ -245,7 +248,7 @@ public class NewCallScreeningServiceFilter extends CallFilter {
        if (!CallScreeningServiceHelper.bindCallScreeningService(mContext,
                mCallsManager.getCurrentUserHandle(), mPackageName, mConnection)) {
            Log.i(this, "Call screening service binding failed.");
            resultFuture.complete(DEFAULT_RESULT);
            resultFuture.complete(mPriorStageResult);
        }
    }

@@ -265,7 +268,6 @@ public class NewCallScreeningServiceFilter extends CallFilter {
    }

    private boolean packageTypeShouldAdd(int packageType) {
        return packageType == PACKAGE_TYPE_CARRIER;
        return packageType != PACKAGE_TYPE_CARRIER;
    }

}
+7 −4
Original line number Diff line number Diff line
@@ -21,14 +21,12 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -78,14 +76,12 @@ import com.android.server.telecom.CallsManagerListenerBase;
import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ContactsAsyncHelper;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.HeadsetMediaButton;
import com.android.server.telecom.HeadsetMediaButtonFactory;
import com.android.server.telecom.InCallWakeLockController;
import com.android.server.telecom.InCallWakeLockControllerFactory;
import com.android.server.telecom.MissedCallNotifier;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.PhoneNumberUtilsAdapter;
import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
import com.android.server.telecom.ProximitySensorManager;
import com.android.server.telecom.ProximitySensorManagerFactory;
@@ -111,6 +107,7 @@ import org.mockito.stubbing.Answer;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -377,6 +374,12 @@ public class TelecomSystemTest extends TelecomTestCase {
    @Override
    public void tearDown() throws Exception {
        mTelecomSystem.getCallsManager().waitOnHandlers();
        LinkedList<HandlerThread> handlerThreads = mTelecomSystem.getCallsManager()
                .getGraphHandlerThreads();
        for (HandlerThread handlerThread : handlerThreads) {
            handlerThread.quitSafely();
        }
        handlerThreads.clear();
        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
        waitForHandlerAction(mHandlerThread.getThreadHandler(), TEST_TIMEOUT);
        // Bring down the threads that are active.