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

Commit 45d49626 authored by Tony Zhu's avatar Tony Zhu Committed by Gerrit Code Review
Browse files

Merge "[Call Screening]Binding to call screening apps"

parents 73bc2723 291ccdd4
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter;
import com.android.server.telecom.callfiltering.BlockCheckerAdapter;
import com.android.server.telecom.callfiltering.CallFilterResultCallback;
import com.android.server.telecom.callfiltering.CallFilteringResult;
import com.android.server.telecom.callfiltering.CallScreeningServiceFilter;
import com.android.server.telecom.callfiltering.CallScreeningServiceController;
import com.android.server.telecom.callfiltering.DirectToVoicemailCallFilter;
import com.android.server.telecom.callfiltering.IncomingCallFilter;
import com.android.server.telecom.components.ErrorDialogActivity;
@@ -568,9 +568,9 @@ public class CallsManager extends Call.ListenerBase
        filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
        filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(),
                mCallerInfoLookupHelper, null));
        filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
            mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock,
            new TelecomServiceImpl.SettingsSecureAdapterImpl()));
        filters.add(new CallScreeningServiceController(mContext, this, mPhoneAccountRegistrar,
                new ParcelableCallUtils.Converter(), mLock,
                new TelecomServiceImpl.SettingsSecureAdapterImpl(), mCallerInfoLookupHelper));
        new IncomingCallFilter(mContext, this, incomingCall, mLock,
                mTimeoutsAdapter, filters).performFiltering();
    }
+2 −0
Original line number Diff line number Diff line
@@ -108,6 +108,8 @@ public class LogUtils {
        public static final String BIND_SCREENING = "BIND_SCREENING";
        public static final String SCREENING_BOUND = "SCREENING_BOUND";
        public static final String SCREENING_SENT = "SCREENING_SENT";
        public static final String CONTROLLER_SCREENING_COMPLETED =
                "CONTROLLER_SCREENING_COMPLETED";
        public static final String SCREENING_COMPLETED = "SCREENING_COMPLETED";
        public static final String BLOCK_CHECK_INITIATED = "BLOCK_CHECK_INITIATED";
        public static final String BLOCK_CHECK_FINISHED = "BLOCK_CHECK_FINISHED";
+264 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.provider.CallLog;
import android.provider.Settings;
import android.telecom.Log;
import android.telecom.Logging.Runnable;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.text.TextUtils;

import com.android.internal.telephony.CallerInfo;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.LogUtils;
import com.android.server.telecom.ParcelableCallUtils;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.TelecomServiceImpl;
import com.android.server.telecom.TelecomSystem;

/**
 * This class supports binding to the various {@link android.telecom.CallScreeningService}:
 * carrier, default dialer and user chosen. Carrier's CallScreeningService implementation will be
 * bound first, and then default dialer's and user chosen's. If Carrier's CallScreeningService
 * blocks a call, no further CallScreeningService after it will be bound.
 */
public class CallScreeningServiceController implements IncomingCallFilter.CallFilter,
        CallScreeningServiceFilter.CallScreeningFilterResultCallback {

    private final Context mContext;
    private final CallsManager mCallsManager;
    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
    private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter;
    private final TelecomSystem.SyncRoot mTelecomLock;
    private final TelecomServiceImpl.SettingsSecureAdapter mSettingsSecureAdapter;
    private final CallerInfoLookupHelper mCallerInfoLookupHelper;

    private final int CARRIER_CALL_FILTERING_TIMED_OUT = 2000; // 2 seconds
    private final int CALL_FILTERING_TIMED_OUT = 4500; // 4.5 seconds

    private final Handler mHandler = new Handler(Looper.getMainLooper());

    private Call mCall;
    private CallFilterResultCallback mCallback;

    private CallFilteringResult mResult = new CallFilteringResult(
            true, // shouldAllowCall
            false, // shouldReject
            true, // shouldAddToCallLog
            true // shouldShowNotification
    );

    private boolean mIsFinished;
    private boolean mIsCarrierFinished;
    private boolean mIsDefaultDialerFinished;
    private boolean mIsUserChosenFinished;

    public CallScreeningServiceController(
            Context context,
            CallsManager callsManager,
            PhoneAccountRegistrar phoneAccountRegistrar,
            ParcelableCallUtils.Converter parcelableCallUtilsConverter,
            TelecomSystem.SyncRoot lock,
            TelecomServiceImpl.SettingsSecureAdapter settingsSecureAdapter,
            CallerInfoLookupHelper callerInfoLookupHelper) {
        mContext = context;
        mCallsManager = callsManager;
        mPhoneAccountRegistrar = phoneAccountRegistrar;
        mParcelableCallUtilsConverter = parcelableCallUtilsConverter;
        mTelecomLock = lock;
        mSettingsSecureAdapter = settingsSecureAdapter;
        mCallerInfoLookupHelper = callerInfoLookupHelper;
    }

    @Override
    public void startFilterLookup(Call call, CallFilterResultCallback callBack) {
        mCall = call;
        mCallback = callBack;
        mIsFinished = false;
        mIsCarrierFinished = false;
        mIsDefaultDialerFinished = false;
        mIsUserChosenFinished = false;

        bindCarrierService();

        // Call screening filtering timed out
        mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) {
            @Override
            public void loggedRun() {
                if (!mIsFinished) {
                    Log.i(CallScreeningServiceController.this, "Call screening has timed out.");
                    finishCallScreening();
                }
            }
        }.prepare(), CALL_FILTERING_TIMED_OUT);
    }

    @Override
    public void onCallScreeningFilterComplete(Call call, CallFilteringResult result, String
            packageName) {
        synchronized (mTelecomLock) {
            mResult = result.combine(mResult);
            if (!TextUtils.isEmpty(packageName) && packageName.equals(getCarrierPackageName())) {
                mIsCarrierFinished = true;
                if (result.mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) {
                    finishCallScreening();
                } else {
                    checkContactExistsAndBindService();
                }
            } else if (!TextUtils.isEmpty(packageName) &&
                    packageName.equals(getDefaultDialerPackageName())) {
                mIsDefaultDialerFinished = true;
                if (result.mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE ||
                        mIsUserChosenFinished) {
                    finishCallScreening();
                }
            } else if (!TextUtils.isEmpty(packageName) &&
                    packageName.equals(getUserChosenPackageName())) {
                mIsUserChosenFinished = true;
                if (mIsDefaultDialerFinished) {
                    finishCallScreening();
                }
            }
        }
    }

    private void bindCarrierService() {
        String carrierPackageName = getCarrierPackageName();
        if (TextUtils.isEmpty(carrierPackageName)) {
            mIsCarrierFinished = true;
            bindDefaultDialerAndUserChosenService();
        } else {
            createCallScreeningServiceFilter().startCallScreeningFilter(mCall, this,
                    carrierPackageName);
        }

        // Carrier filtering timed out
        mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) {
            @Override
            public void loggedRun() {
                if (!mIsCarrierFinished) {
                    mIsCarrierFinished = true;
                    checkContactExistsAndBindService();
                }
            }
        }.prepare(), CARRIER_CALL_FILTERING_TIMED_OUT);
    }

    private void bindDefaultDialerAndUserChosenService() {
        if (mIsCarrierFinished) {
            String dialerPackageName = getDefaultDialerPackageName();
            if (TextUtils.isEmpty(dialerPackageName)) {
                mIsDefaultDialerFinished = true;
            } else {
                createCallScreeningServiceFilter().startCallScreeningFilter(mCall,
                        CallScreeningServiceController.this, dialerPackageName);
            }

            String userChosenPackageName = getUserChosenPackageName();
            if (TextUtils.isEmpty(userChosenPackageName)) {
                mIsUserChosenFinished = true;
            } else {
                createCallScreeningServiceFilter().startCallScreeningFilter(mCall,
                        CallScreeningServiceController.this, userChosenPackageName);
            }

            if (mIsDefaultDialerFinished && mIsUserChosenFinished) {
                finishCallScreening();
            }
        }
    }

    private CallScreeningServiceFilter createCallScreeningServiceFilter() {
        return new CallScreeningServiceFilter(
                mContext,
                mCallsManager,
                mPhoneAccountRegistrar,
                mParcelableCallUtilsConverter,
                mTelecomLock,
                mSettingsSecureAdapter);
    }

    private void checkContactExistsAndBindService() {
        mCallerInfoLookupHelper.startLookup(mCall.getHandle(),
                new CallerInfoLookupHelper.OnQueryCompleteListener() {
                    @Override
                    public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
                        boolean contactExists = info != null && info.contactExists;
                        Log.i(CallScreeningServiceController.this, "Contact exists: " +
                                contactExists);
                        if (!contactExists) {
                            bindDefaultDialerAndUserChosenService();
                        } else {
                            finishCallScreening();
                        }
                    }

                    @Override
                    public void onContactPhotoQueryComplete(Uri handle, CallerInfo
                            info) {
                        // ignore
                    }
                });
    }

    private void finishCallScreening() {
        Log.addEvent(mCall, LogUtils.Events.CONTROLLER_SCREENING_COMPLETED, mResult);
        mCallback.onCallFilteringComplete(mCall, mResult);
        mIsFinished = true;
    }

    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;
    }

    private String getDefaultDialerPackageName() {
        return TelecomManager.from(mContext).getDefaultDialerPackage();
    }

    private String getUserChosenPackageName() {
        ComponentName componentName = null;
        String defaultCallScreeningApplication = mSettingsSecureAdapter.getStringForUser(mContext
                .getContentResolver(), Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT,
                UserHandle.USER_CURRENT);

        if (!TextUtils.isEmpty(defaultCallScreeningApplication)) {
            componentName = ComponentName.unflattenFromString(defaultCallScreeningApplication);
        }

        return componentName != null ? componentName.getPackageName() : null;
    }
}
+38 −36
Original line number Diff line number Diff line
@@ -39,11 +39,9 @@ import com.android.internal.telecom.ICallScreeningAdapter;
import com.android.internal.telecom.ICallScreeningService;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.LogUtils;
import com.android.server.telecom.ParcelableCallUtils;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.TelecomServiceImpl;
import com.android.server.telecom.TelecomServiceImpl.SettingsSecureAdapter;
import com.android.server.telecom.TelecomSystem;

@@ -53,7 +51,13 @@ import java.util.List;
 * Binds to {@link ICallScreeningService} to allow call blocking. A single instance of this class
 * handles a single call.
 */
public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter {
public class CallScreeningServiceFilter {

    public interface CallScreeningFilterResultCallback {
        void onCallScreeningFilterComplete(Call call, CallFilteringResult result, String
                packageName);
    }

    private class CallScreeningServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
@@ -150,17 +154,17 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter
    private final Context mContext;
    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
    private final CallsManager mCallsManager;
    private final DefaultDialerCache mDefaultDialerCache;
    private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter;
    private final TelecomSystem.SyncRoot mTelecomLock;
    private final SettingsSecureAdapter mSettingsSecureAdapter;

    private Call mCall;
    private CallFilterResultCallback mCallback;
    private CallScreeningFilterResultCallback mCallback;
    private ICallScreeningService mService;
    private ServiceConnection mConnection;

    private String mPackageName;
    private boolean mHasFinished = false;

    private CallFilteringResult mResult = new CallFilteringResult(
            true, // shouldAllowCall
            false, //shouldReject
@@ -172,28 +176,28 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter
            Context context,
            CallsManager callsManager,
            PhoneAccountRegistrar phoneAccountRegistrar,
            DefaultDialerCache defaultDialerCache,
            ParcelableCallUtils.Converter parcelableCallUtilsConverter,
            TelecomSystem.SyncRoot lock,
            SettingsSecureAdapter settingsSecureAdapter) {
        mContext = context;
        mPhoneAccountRegistrar = phoneAccountRegistrar;
        mCallsManager = callsManager;
        mDefaultDialerCache = defaultDialerCache;
        mParcelableCallUtilsConverter = parcelableCallUtilsConverter;
        mTelecomLock = lock;
        mSettingsSecureAdapter = settingsSecureAdapter;
    }

    @Override
    public void startFilterLookup(Call call, CallFilterResultCallback callback) {
    public void startCallScreeningFilter(Call call,
                                         CallScreeningFilterResultCallback callback,
                                         String packageName) {
        if (mHasFinished) {
            Log.w(this, "Attempting to reuse CallScreeningServiceFilter. Ignoring.");
            return;
        }
        Log.addEvent(call, LogUtils.Events.SCREENING_SENT);
        Log.addEvent(call, LogUtils.Events.SCREENING_SENT, packageName);
        mCall = call;
        mCallback = callback;
        mPackageName = packageName;
        if (!bindService()) {
            Log.i(this, "Could not bind to call screening service");
            finishCallScreening();
@@ -203,7 +207,7 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter
    private void finishCallScreening() {
        if (!mHasFinished) {
            Log.addEvent(mCall, LogUtils.Events.SCREENING_COMPLETED, mResult);
            mCallback.onCallFilteringComplete(mCall, mResult);
            mCallback.onCallScreeningFilterComplete(mCall, mResult, mPackageName);

            if (mConnection != null) {
                // We still need to call unbind even if the service disconnected.
@@ -216,25 +220,23 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter
    }

    private boolean bindService() {
        String dialerPackage = mDefaultDialerCache
                .getDefaultDialerApplication(UserHandle.USER_CURRENT);
        if (TextUtils.isEmpty(dialerPackage)) {
            Log.i(this, "Default dialer is empty. Not performing call screening.");
        if (TextUtils.isEmpty(mPackageName)) {
            Log.i(this, "PackageName is empty. Not performing call screening.");
            return false;
        }

        Intent intent = new Intent(CallScreeningService.SERVICE_INTERFACE)
            .setPackage(dialerPackage);
                .setPackage(mPackageName);
        List<ResolveInfo> entries = mContext.getPackageManager().queryIntentServicesAsUser(
                intent, 0, mCallsManager.getCurrentUserHandle().getIdentifier());
        if (entries.isEmpty()) {
            Log.i(this, "There are no call screening services installed on this device.");
            Log.i(this, mPackageName + "is no call screening services installed on this device.");
            return false;
        }

        ResolveInfo entry = entries.get(0);
        if (entry.serviceInfo == null) {
            Log.w(this, "The call screening service has invalid service info");
            Log.w(this, mPackageName + " call screening service has invalid service info");
            return false;
        }

+351 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading