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

Commit c7b13dbb authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Delete deprecated call filters."

parents b60f7988 d9d969bc
Loading
Loading
Loading
Loading
+0 −180
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.BlockedNumberContract;
import android.provider.CallLog;
import android.telecom.Log;
import android.telecom.Logging.Session;
import android.telecom.TelecomManager;

import android.telecom.CallerInfo;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.LogUtils;
import com.android.server.telecom.callfiltering.CallFilteringResult.Builder;
import com.android.server.telecom.settings.BlockedNumbersUtil;

/**
 * An {@link AsyncTask} that checks if a call needs to be blocked.
 * <p> An {@link AsyncTask} is used to perform the block check to avoid blocking the main thread.
 * The block check itself is performed in the {@link AsyncTask#doInBackground(Object[])}.
 */
public class AsyncBlockCheckFilter extends AsyncTask<String, Void, Boolean>
        implements IncomingCallFilter.CallFilter {
    private final Context mContext;
    private final BlockCheckerAdapter mBlockCheckerAdapter;
    private final CallBlockListener mCallBlockListener;
    private Call mIncomingCall;
    private Session mBackgroundTaskSubsession;
    private Session mPostExecuteSubsession;
    private CallFilterResultCallback mCallback;
    private CallerInfoLookupHelper mCallerInfoLookupHelper;
    private int mBlockStatus = BlockedNumberContract.STATUS_NOT_BLOCKED;

    public AsyncBlockCheckFilter(Context context, BlockCheckerAdapter blockCheckerAdapter,
            CallerInfoLookupHelper callerInfoLookupHelper, CallBlockListener callBlockListener) {
        mContext = context;
        mBlockCheckerAdapter = blockCheckerAdapter;
        mCallerInfoLookupHelper = callerInfoLookupHelper;
        mCallBlockListener = callBlockListener;
    }

    @Override
    public void startFilterLookup(Call call, CallFilterResultCallback callback) {
        mCallback = callback;
        mIncomingCall = call;
        String number = call.getHandle() == null ?
                null : call.getHandle().getSchemeSpecificPart();
        if (BlockedNumbersUtil.isEnhancedCallBlockingEnabledByPlatform(mContext)) {
            int presentation = mIncomingCall.getHandlePresentation();
            if (presentation == TelecomManager.PRESENTATION_ALLOWED) {
                mCallerInfoLookupHelper.startLookup(call.getHandle(),
                        new CallerInfoLookupHelper.OnQueryCompleteListener() {
                            @Override
                            public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
                                boolean contactExists = info == null ? false : info.contactExists;
                                execute(number, String.valueOf(presentation),
                                        String.valueOf(contactExists));
                            }

                            @Override
                            public void onContactPhotoQueryComplete(Uri handle, CallerInfo info) {
                                // ignore
                            }
                        });
            } else {
                this.execute(number, String.valueOf(presentation));
            }
        } else {
            this.execute(number);
        }
    }

    @Override
    protected void onPreExecute() {
        mBackgroundTaskSubsession = Log.createSubsession();
        mPostExecuteSubsession = Log.createSubsession();
    }

    @Override
    protected Boolean doInBackground(String... params) {
        try {
            Log.continueSession(mBackgroundTaskSubsession, "ABCF.dIB");
            Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_INITIATED);
            Bundle extras = new Bundle();
            if (params.length > 1) {
                extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION,
                        Integer.valueOf(params[1]));
            }
            if (params.length > 2) {
                extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST,
                        Boolean.valueOf(params[2]));
            }
            mBlockStatus = mBlockCheckerAdapter.getBlockStatus(mContext, params[0], extras);
            return mBlockStatus != BlockedNumberContract.STATUS_NOT_BLOCKED;
        } finally {
            Log.endSession();
        }
    }

    @Override
    protected void onPostExecute(Boolean isBlocked) {
        Log.continueSession(mPostExecuteSubsession, "ABCF.oPE");
        try {
            CallFilteringResult result;
            if (isBlocked) {
                result = new Builder()
                        .setShouldAllowCall(false)
                        .setShouldReject(true)
                        .setShouldAddToCallLog(true)
                        .setShouldShowNotification(false)
                        .setCallBlockReason(convertBlockStatusToReason())
                        .setCallScreeningAppName(null)
                        .setCallScreeningComponentName(null)
                        .build();
                if (mCallBlockListener != null) {
                    String number = mIncomingCall.getHandle() == null ? null
                            : mIncomingCall.getHandle().getSchemeSpecificPart();
                    mCallBlockListener.onCallBlocked(mBlockStatus, number,
                            mIncomingCall.getInitiatingUser());
                }
            } else {
                result = new Builder()
                        .setShouldAllowCall(true)
                        .setShouldReject(false)
                        .setShouldAddToCallLog(true)
                        .setShouldShowNotification(true)
                        .build();
            }
            Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_FINISHED,
                    BlockedNumberContract.SystemContract.blockStatusToString(mBlockStatus) + " "
                            + result);
            mCallback.onCallFilteringComplete(mIncomingCall, result);
        } finally {
            Log.endSession();
        }
    }

    private int convertBlockStatusToReason() {
        switch (mBlockStatus) {
            case BlockedNumberContract.STATUS_BLOCKED_IN_LIST:
                return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER;

            case BlockedNumberContract.STATUS_BLOCKED_UNKNOWN_NUMBER:
                return CallLog.Calls.BLOCK_REASON_UNKNOWN_NUMBER;

            case BlockedNumberContract.STATUS_BLOCKED_RESTRICTED:
                return CallLog.Calls.BLOCK_REASON_RESTRICTED_NUMBER;

            case BlockedNumberContract.STATUS_BLOCKED_PAYPHONE:
                return CallLog.Calls.BLOCK_REASON_PAY_PHONE;

            case BlockedNumberContract.STATUS_BLOCKED_NOT_IN_CONTACTS:
                return CallLog.Calls.BLOCK_REASON_NOT_IN_CONTACTS;

            default:
                Log.w(AsyncBlockCheckFilter.class.getSimpleName(),
                    "There's no call log block reason can be converted");
                return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER;
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -135,8 +135,8 @@ public class CallFilteringResult {
    /**
     * Combine this CallFilteringResult with another, returning a CallFilteringResult with the more
     * restrictive properties of the two. Where there are multiple call filtering components which
     * block a call, the first filter from {@link AsyncBlockCheckFilter},
     * {@link DirectToVoicemailCallFilter}, {@link CallScreeningServiceFilter} which blocked a call
     * block a call, the first filter from {@link BlockCheckerFilter},
     * {@link DirectToVoicemailFilter}, {@link NewCallScreeningServiceFilter} which blocked a call
     * shall be used to populate the call block reason, component name, etc.
     */
    public CallFilteringResult combine(CallFilteringResult other) {
+0 −283
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.provider.CallLog;
import android.telecom.Log;
import android.telecom.Logging.Runnable;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.text.TextUtils;

import android.telecom.CallerInfo;

import com.android.server.telecom.AppLabelProxy;
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;
import com.android.server.telecom.callfiltering.CallFilteringResult.Builder;

/**
 * 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 AppLabelProxy mAppLabelProxy;

    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 Builder()
            .setShouldAllowCall(true)
            .setShouldReject(false)
            .setShouldAddToCallLog(true)
            .setShouldShowNotification(true)
            .build();

    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,
            AppLabelProxy appLabelProxy) {
        mContext = context;
        mCallsManager = callsManager;
        mPhoneAccountRegistrar = phoneAccountRegistrar;
        mParcelableCallUtilsConverter = parcelableCallUtilsConverter;
        mTelecomLock = lock;
        mSettingsSecureAdapter = settingsSecureAdapter;
        mCallerInfoLookupHelper = callerInfoLookupHelper;
        mAppLabelProxy = appLabelProxy;
    }

    @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())) {
                // Default dialer defined CallScreeningService cannot skip the call log.
                mResult.shouldAddToCallLog = true;
                mIsDefaultDialerFinished = true;
                if (result.mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE ||
                        mIsUserChosenFinished) {
                    finishCallScreening();
                }
            } else if (!TextUtils.isEmpty(packageName) &&
                    packageName.equals(getUserChosenPackageName())) {
                // User defined CallScreeningService cannot skip the call log.
                mResult.shouldAddToCallLog = true;
                mIsUserChosenFinished = true;
                if (mIsDefaultDialerFinished) {
                    finishCallScreening();
                }
            }
        }
    }

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

        // 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();
            String systemDialerPackageName = getSystemDialerPackageName();
            if (TextUtils.isEmpty(dialerPackageName)) {
                mIsDefaultDialerFinished = true;
            } else {
                int dialerType = dialerPackageName.equals(systemDialerPackageName) ?
                        CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_SYSTEM_DIALER :
                        CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_DEFAULT_DIALER;
                createCallScreeningServiceFilter().startCallScreeningFilter(mCall,
                        CallScreeningServiceController.this, dialerPackageName,
                        mAppLabelProxy.getAppLabel(dialerPackageName), dialerType);
            }

            String userChosenPackageName = getUserChosenPackageName();
            if (TextUtils.isEmpty(userChosenPackageName)) {
                mIsUserChosenFinished = true;
            } else {
                // If the user chosen call screening service is the same as the default dialer, then
                // we have already bound to it above and don't need to do so again here.
                if (userChosenPackageName.equals(dialerPackageName)) {
                    Log.addEvent(mCall, LogUtils.Events.SCREENING_SKIPPED,
                            "user pkg same as dialer: " + userChosenPackageName);
                    mIsUserChosenFinished = true;
                } else {
                    createCallScreeningServiceFilter().startCallScreeningFilter(mCall,
                            CallScreeningServiceController.this, userChosenPackageName,
                            mAppLabelProxy.getAppLabel(userChosenPackageName),
                            CallScreeningServiceFilter.CALL_SCREENING_FILTER_TYPE_USER_SELECTED);
                }
            }

            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 getSystemDialerPackageName() {
        return TelecomManager.from(mContext).getSystemDialerPackage();
    }

    private String getUserChosenPackageName() {
        return mCallsManager.getRoleManagerAdapter().getDefaultCallScreeningApp();
    }
}
+0 −367

File deleted.

Preview size limit exceeded, changes collapsed.

+0 −89
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.net.Uri;
import android.provider.CallLog.Calls;
import android.telecom.Log;

import android.telecom.CallerInfo;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.LogUtils;
import com.android.server.telecom.callfiltering.CallFilteringResult.Builder;

import java.util.Objects;

public class DirectToVoicemailCallFilter implements IncomingCallFilter.CallFilter {
    private final CallerInfoLookupHelper mCallerInfoLookupHelper;

    public DirectToVoicemailCallFilter(CallerInfoLookupHelper callerInfoLookupHelper) {
        mCallerInfoLookupHelper = callerInfoLookupHelper;
    }

    @Override
    public void startFilterLookup(final Call call, CallFilterResultCallback callback) {
        Log.addEvent(call, LogUtils.Events.DIRECT_TO_VM_INITIATED);
        final Uri callHandle = call.getHandle();

        mCallerInfoLookupHelper.startLookup(callHandle,
                new CallerInfoLookupHelper.OnQueryCompleteListener() {
                    @Override
                    public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
                        CallFilteringResult result;
                        if ((handle != null) && Objects.equals(callHandle, handle)) {
                            if (info != null && info.shouldSendToVoicemail) {
                                result = new Builder()
                                        .setShouldAllowCall(false)
                                        .setShouldReject(true)
                                        .setShouldAddToCallLog(true)
                                        .setShouldShowNotification(true)
                                        .setCallBlockReason(Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL)
                                        .setCallScreeningAppName(null)
                                        .setCallScreeningComponentName(null)
                                        .build();
                            } else {
                                result = new Builder()
                                        .setShouldAllowCall(true)
                                        .setShouldReject(false)
                                        .setShouldAddToCallLog(true)
                                        .setShouldShowNotification(true)
                                        .build();
                            }
                            Log.addEvent(call, LogUtils.Events.DIRECT_TO_VM_FINISHED, result);
                            callback.onCallFilteringComplete(call, result);
                        } else {
                            result = new Builder()
                                    .setShouldAllowCall(true)
                                    .setShouldReject(false)
                                    .setShouldAddToCallLog(true)
                                    .setShouldShowNotification(true)
                                    .build();
                            Log.addEvent(call, LogUtils.Events.DIRECT_TO_VM_FINISHED, result);
                            Log.w(this, "CallerInfo lookup returned with a different handle than " +
                                    "what was passed in. Was %s, should be %s", handle, callHandle);
                            callback.onCallFilteringComplete(call, result);
                        }
                    }

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