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

Commit 42f96bfd authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Fix issue where async code in Telecom wasn't ACTUALLY async.

Telecom used an AsyncTask (which is deprecated) to update the emergency
call notification when carrier config changes or block suppression state
changes are reported from the blocked numbers provider.  EXCEPT the way
the AsyncTask code was used, it was NOT actually doing this work async.
The code should have called
`new UpdateEmergencyCallNotificationTask().execute`, not doInBackground.

Since AsyncTask is deprecated and Telecom has an async executor for this
kind of thing now, changing to use the async task executor.

Also doing some minor refactoring on static dependencies to make it
possible to unit test these changes.

Test: Add new unit tests for broadcast handling.
Test: Run existing telecom tests to verify no regression.
Test: Make test emergency call with unknown number blocking enabled
and verify notification is posted.
Test: From blocked number settings screen, reenable blocked number
functionality and verify notification is removed.
Fixes: 274540300

Change-Id: Id836df7cbe71b57f4d318cd588a8a0965b95c06c
parent cb20ad6e
Loading
Loading
Loading
Loading
+25 −23
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@ import android.media.AudioSystem;
import android.media.MediaPlayer;
import android.media.ToneGenerator;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -123,6 +122,7 @@ import com.android.server.telecom.callfiltering.CallScreeningServiceFilter;
import com.android.server.telecom.callfiltering.DirectToVoicemailFilter;
import com.android.server.telecom.callfiltering.DndCallFilter;
import com.android.server.telecom.callfiltering.IncomingCallFilterGraph;
import com.android.server.telecom.callfiltering.BlockedNumbersAdapter;
import com.android.server.telecom.callredirection.CallRedirectionProcessor;
import com.android.server.telecom.components.ErrorDialogActivity;
import com.android.server.telecom.components.TelecomBroadcastReceiver;
@@ -438,6 +438,7 @@ public class CallsManager extends Call.ListenerBase
    private final CallEndpointController mCallEndpointController;
    private final CallAnomalyWatchdog mCallAnomalyWatchdog;
    private final CallStreamingController mCallStreamingController;
    private final BlockedNumbersAdapter mBlockedNumbersAdapter;

    private final ConnectionServiceFocusManager.CallsManagerRequester mRequester =
            new ConnectionServiceFocusManager.CallsManagerRequester() {
@@ -499,34 +500,14 @@ public class CallsManager extends Call.ListenerBase
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.startSession("CM.CCCR");
            String action = intent.getAction();
            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)
                    || SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED.equals(action)) {
                new UpdateEmergencyCallNotificationTask().doInBackground(
                        Pair.create(context, Log.createSubsession()));
                updateEmergencyCallNotificationAsync(context);
            }
        }
    };

    private static class UpdateEmergencyCallNotificationTask
            extends AsyncTask<Pair<Context, Session>, Void, Void> {
        @SafeVarargs
        @Override
        protected final Void doInBackground(Pair<Context, Session>... args) {
            if (args == null || args.length != 1 || args[0] == null) {
                Log.e(this, new IllegalArgumentException(), "Incorrect invocation");
                return null;
            }
            Log.continueSession(args[0].second, "CM.UECNT");
            Context context = args[0].first;
            BlockedNumbersUtil.updateEmergencyCallNotification(context,
                    SystemContract.shouldShowEmergencyCallNotification(context));
            Log.endSession();
            return null;
        }
    }

    /**
     * Initializes the required Telecom components.
     */
@@ -565,7 +546,8 @@ public class CallsManager extends Call.ListenerBase
            CallEndpointControllerFactory callEndpointControllerFactory,
            CallAnomalyWatchdog callAnomalyWatchdog,
            Ringer.AccessibilityManagerAdapter accessibilityManagerAdapter,
            Executor asyncTaskExecutor) {
            Executor asyncTaskExecutor,
            BlockedNumbersAdapter blockedNumbersAdapter) {
        mContext = context;
        mLock = lock;
        mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
@@ -649,6 +631,7 @@ public class CallsManager extends Call.ListenerBase
        mToastFactory = toastFactory;
        mRoleManagerAdapter = roleManagerAdapter;
        mCallStreamingController = new CallStreamingController(mContext);
        mBlockedNumbersAdapter = blockedNumbersAdapter;

        mListeners.add(mInCallWakeLockController);
        mListeners.add(statusBarNotifier);
@@ -4975,6 +4958,25 @@ public class CallsManager extends Call.ListenerBase
        });
    }

    /**
     * Asynchronously updates the emergency call notification.
     * @param context the context for the update.
     */
    private void updateEmergencyCallNotificationAsync(Context context) {
        mAsyncTaskExecutor.execute(() -> {
            Log.startSession("CM.UEMCNA");
            try {
                boolean shouldShow = mBlockedNumbersAdapter.shouldShowEmergencyCallNotification(
                        context);
                Log.i(CallsManager.this, "updateEmergencyCallNotificationAsync; show=%b",
                        shouldShow);
                mBlockedNumbersAdapter.updateEmergencyCallNotification(context, shouldShow);
            } finally {
                Log.endSession();
            }
        });
    }

    /**
     * Creates a new call for an existing connection.
     *
+5 −3
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import android.os.UserManager;
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;
import android.telephony.AnomalyReporter;
import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;

import androidx.annotation.NonNull;
@@ -42,6 +41,7 @@ import com.android.server.telecom.DefaultDialerCache.DefaultDialerManagerAdapter
import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
import com.android.server.telecom.callfiltering.BlockedNumbersAdapter;
import com.android.server.telecom.components.UserCallIntentProcessor;
import com.android.server.telecom.components.UserCallIntentProcessorFactory;
import com.android.server.telecom.ui.AudioProcessingNotification;
@@ -212,7 +212,8 @@ public class TelecomSystem {
            ContactsAsyncHelper.Factory contactsAsyncHelperFactory,
            DeviceIdleControllerAdapter deviceIdleControllerAdapter,
            Ringer.AccessibilityManagerAdapter accessibilityManagerAdapter,
            Executor asyncTaskExecutor) {
            Executor asyncTaskExecutor,
            BlockedNumbersAdapter blockedNumbersAdapter) {
        mContext = context.getApplicationContext();
        LogUtils.initLogging(mContext);
        AnomalyReporter.initialize(mContext);
@@ -370,7 +371,8 @@ public class TelecomSystem {
                    callEndpointControllerFactory,
                    callAnomalyWatchdog,
                    accessibilityManagerAdapter,
                    asyncTaskExecutor);
                    asyncTaskExecutor,
                    blockedNumbersAdapter);

            mIncomingCallNotifier = incomingCallNotifier;
            incomingCallNotifier.setCallsManagerProxy(new IncomingCallNotifier.CallsManagerProxy() {
+29 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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;

/**
 * Adapter interface that wraps methods from
 * {@link android.provider.BlockedNumberContract.SystemContract} and
 * {@link com.android.server.telecom.settings.BlockedNumbersUtil} to make things testable.
 */
public interface BlockedNumbersAdapter {
    boolean shouldShowEmergencyCallNotification (Context context);
    void updateEmergencyCallNotification(Context context, boolean showNotification);
}
+20 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.IBinder;
import android.os.PowerManager;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.BlockedNumberContract;
import android.telecom.Log;

import android.telecom.CallerInfoAsyncQuery;
@@ -59,6 +60,8 @@ import com.android.server.telecom.RoleManagerAdapterImpl;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.TelecomWakeLock;
import com.android.server.telecom.Timeouts;
import com.android.server.telecom.callfiltering.BlockedNumbersAdapter;
import com.android.server.telecom.settings.BlockedNumbersUtil;
import com.android.server.telecom.ui.IncomingCallNotifier;
import com.android.server.telecom.ui.MissedCallNotifierImpl;
import com.android.server.telecom.ui.NotificationChannelManager;
@@ -211,7 +214,22 @@ public class TelecomService extends Service implements TelecomSystem.Component {
                                            .stopFlashNotificationSequence(context);
                                }
                            },
                            Executors.newSingleThreadExecutor()));
                            Executors.newSingleThreadExecutor(),
                            new BlockedNumbersAdapter() {
                                @Override
                                public boolean shouldShowEmergencyCallNotification(Context
                                        context) {
                                    return BlockedNumberContract.SystemContract
                                            .shouldShowEmergencyCallNotification(context);
                                }

                                @Override
                                public void updateEmergencyCallNotification(Context context,
                                        boolean showNotification) {
                                    BlockedNumbersUtil.updateEmergencyCallNotification(context,
                                            showNotification);
                                }
                            }));
        }
    }

+61 −1
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import android.os.Process;
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.BlockedNumberContract;
import android.telecom.CallerInfo;
import android.telecom.CallScreeningService;
import android.telecom.Connection;
@@ -68,6 +69,7 @@ import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.CallException;
import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
@@ -115,6 +117,7 @@ import com.android.server.telecom.WiredHeadsetManager;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
import com.android.server.telecom.callfiltering.CallFilteringResult;
import com.android.server.telecom.callfiltering.BlockedNumbersAdapter;
import com.android.server.telecom.ui.AudioProcessingNotification;
import com.android.server.telecom.ui.DisconnectedCallNotifier;
import com.android.server.telecom.ui.ToastFactory;
@@ -235,6 +238,7 @@ public class CallsManagerTest extends TelecomTestCase {
    @Mock private CallAnomalyWatchdog mCallAnomalyWatchdog;
    @Mock private AnomalyReporterAdapter mAnomalyReporterAdapter;
    @Mock private Ringer.AccessibilityManagerAdapter mAccessibilityManagerAdapter;
    @Mock private BlockedNumbersAdapter mBlockedNumbersAdapter;

    private CallsManager mCallsManager;

@@ -299,7 +303,8 @@ public class CallsManagerTest extends TelecomTestCase {
                mCallAnomalyWatchdog,
                mAccessibilityManagerAdapter,
                // Just do async tasks synchronously to support testing.
                command -> command.run());
                command -> command.run(),
                mBlockedNumbersAdapter);

        when(mPhoneAccountRegistrar.getPhoneAccount(
                eq(SELF_MANAGED_HANDLE), any())).thenReturn(SELF_MANAGED_ACCOUNT);
@@ -2708,6 +2713,61 @@ public class CallsManagerTest extends TelecomTestCase {
        assertTrue(mCallsManager.hasSelfManagedCalls());
    }

    /**
     * Verifies when {@link CallsManager} receives a carrier config change it will trigger an
     * update of the emergency call notification.
     * Note: this test mocks out {@link BlockedNumbersAdapter} so does not actually test posting of
     * the notification.  Notification posting in the actual implementation is covered by
     * {@link BlockedNumbersUtilTests}.
     */
    @SmallTest
    @Test
    public void testUpdateEmergencyCallNotificationOnCarrierConfigChange() {
        when(mBlockedNumbersAdapter.shouldShowEmergencyCallNotification(any(Context.class)))
                .thenReturn(true);
        mComponentContextFixture.getBroadcastReceivers().forEach(c -> c.onReceive(mContext,
                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)));
        verify(mBlockedNumbersAdapter).updateEmergencyCallNotification(any(Context.class),
                eq(true));

        when(mBlockedNumbersAdapter.shouldShowEmergencyCallNotification(any(Context.class)))
                .thenReturn(false);
        mComponentContextFixture.getBroadcastReceivers().forEach(c -> c.onReceive(mContext,
                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)));
        verify(mBlockedNumbersAdapter).updateEmergencyCallNotification(any(Context.class),
                eq(false));
    }

    /**
     * Verifies when {@link CallsManager} receives a signal from the blocked number provider that
     * the call blocking enabled state changes, it will trigger an update of the emergency call
     * notification.
     * Note: this test mocks out {@link BlockedNumbersAdapter} so does not actually test posting of
     * the notification.  Notification posting in the actual implementation is covered by
     * {@link BlockedNumbersUtilTests}.
     */
    @SmallTest
    @Test
    public void testUpdateEmergencyCallNotificationOnNotificationVisibilityChange() {
        when(mBlockedNumbersAdapter.shouldShowEmergencyCallNotification(any(Context.class)))
                .thenReturn(true);
        mComponentContextFixture.getBroadcastReceivers().forEach(c -> c.onReceive(mContext,
                new Intent(
                        BlockedNumberContract.SystemContract
                                .ACTION_BLOCK_SUPPRESSION_STATE_CHANGED)));
        verify(mBlockedNumbersAdapter).updateEmergencyCallNotification(any(Context.class),
                eq(true));

        when(mBlockedNumbersAdapter.shouldShowEmergencyCallNotification(any(Context.class)))
                .thenReturn(false);
        mComponentContextFixture.getBroadcastReceivers().forEach(c -> c.onReceive(mContext,
                new Intent(
                        BlockedNumberContract.SystemContract
                                .ACTION_BLOCK_SUPPRESSION_STATE_CHANGED)));
        verify(mBlockedNumbersAdapter).updateEmergencyCallNotification(any(Context.class),
                eq(false));
    }

    private Call addSpyCall() {
        return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
    }
Loading