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

Commit e07ed4a0 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 10985023 from 05c0c644 to 24Q1-release

Change-Id: I937af94e9a7cb884667c8b2d416ccb94bca9a046
parents 31565d1c 05c0c644
Loading
Loading
Loading
Loading
+72 −14
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.telecom;

import android.media.AudioAttributes;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.os.Looper;
import android.os.Message;
@@ -29,6 +31,7 @@ import com.android.internal.util.IState;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.server.telecom.flags.FeatureFlags;

public class CallAudioModeStateMachine extends StateMachine {
    /**
@@ -38,11 +41,27 @@ public class CallAudioModeStateMachine extends StateMachine {
    private LocalLog mLocalLog = new LocalLog(20);
    public static class Factory {
        public CallAudioModeStateMachine create(SystemStateHelper systemStateHelper,
                AudioManager am) {
            return new CallAudioModeStateMachine(systemStateHelper, am);
                                                AudioManager am, FeatureFlags featureFlags) {
            return new CallAudioModeStateMachine(systemStateHelper, am, featureFlags);
        }
    }

    private static final AudioAttributes RING_AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
            .setLegacyStreamType(AudioManager.STREAM_RING)
            .build();
    public static final AudioFocusRequest RING_AUDIO_FOCUS_REQUEST = new AudioFocusRequest
            .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
            .setAudioAttributes(RING_AUDIO_ATTRIBUTES).build();

    private static final AudioAttributes CALL_AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
            .setLegacyStreamType(AudioManager.STREAM_VOICE_CALL)
            .build();
    public static final AudioFocusRequest CALL_AUDIO_FOCUS_REQUEST = new AudioFocusRequest
            .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
            .setAudioAttributes(CALL_AUDIO_ATTRIBUTES).build();

    public static class MessageArgs {
        public boolean hasActiveOrDialingCalls;
        public boolean hasRingingCalls;
@@ -212,6 +231,8 @@ public class CallAudioModeStateMachine extends StateMachine {
    public static final String STREAMING_STATE_NAME = StreamingFocusState.class.getSimpleName();
    public static final String COMMS_STATE_NAME = VoipCallFocusState.class.getSimpleName();

    private AudioFocusRequest mCurrentAudioFocusRequest = null;

    private class BaseState extends State {
        @Override
        public boolean processMessage(Message msg) {
@@ -310,7 +331,14 @@ public class CallAudioModeStateMachine extends StateMachine {
                    return HANDLED;
                case AUDIO_OPERATIONS_COMPLETE:
                    Log.i(LOG_TAG, "Abandoning audio focus: now UNFOCUSED");
                    if (mFeatureFlags.telecomResolveHiddenDependencies()) {
                        if (mCurrentAudioFocusRequest != null) {
                            mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest);
                            mCurrentAudioFocusRequest = null;
                        }
                    } else {
                        mAudioManager.abandonAudioFocusForCall();
                    }
                    return HANDLED;
                default:
                    // The forced focus switch commands are handled by BaseState.
@@ -381,7 +409,14 @@ public class CallAudioModeStateMachine extends StateMachine {
                    return HANDLED;
                case AUDIO_OPERATIONS_COMPLETE:
                    Log.i(LOG_TAG, "Abandoning audio focus: now AUDIO_PROCESSING");
                    if (mFeatureFlags.telecomResolveHiddenDependencies()) {
                        if (mCurrentAudioFocusRequest != null) {
                            mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest);
                            mCurrentAudioFocusRequest = null;
                        }
                    } else {
                        mAudioManager.abandonAudioFocusForCall();
                    }
                    return HANDLED;
                default:
                    // The forced focus switch commands are handled by BaseState.
@@ -406,8 +441,13 @@ public class CallAudioModeStateMachine extends StateMachine {
                }

                if (mCallAudioManager.startRinging()) {
                    if (mFeatureFlags.telecomResolveHiddenDependencies()) {
                        mCurrentAudioFocusRequest = RING_AUDIO_FOCUS_REQUEST;
                        mAudioManager.requestAudioFocus(RING_AUDIO_FOCUS_REQUEST);
                    } else {
                        mAudioManager.requestAudioFocusForCall(
                                AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
                    }
                    // Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode --
                    // this trips up the audio system.
                    if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) {
@@ -504,8 +544,13 @@ public class CallAudioModeStateMachine extends StateMachine {
        public void enter() {
            Log.i(LOG_TAG, "Audio focus entering SIM CALL state");
            mLocalLog.log("Enter SIM_CALL");
            if (mFeatureFlags.telecomResolveHiddenDependencies()) {
                mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST;
                mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST);
            } else {
                mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
            }
            mAudioManager.setMode(AudioManager.MODE_IN_CALL);
            mLocalLog.log("Mode MODE_IN_CALL");
            mMostRecentMode = AudioManager.MODE_IN_CALL;
@@ -587,8 +632,13 @@ public class CallAudioModeStateMachine extends StateMachine {
        public void enter() {
            Log.i(LOG_TAG, "Audio focus entering VOIP CALL state");
            mLocalLog.log("Enter VOIP_CALL");
            if (mFeatureFlags.telecomResolveHiddenDependencies()) {
                mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST;
                mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST);
            } else {
                mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
            }
            mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
            mLocalLog.log("Mode MODE_IN_COMMUNICATION");
            mMostRecentMode = AudioManager.MODE_IN_COMMUNICATION;
@@ -742,8 +792,13 @@ public class CallAudioModeStateMachine extends StateMachine {
        public void enter() {
            Log.i(LOG_TAG, "Audio focus entering TONE/HOLDING state");
            mLocalLog.log("Enter TONE/HOLDING");
            if (mFeatureFlags.telecomResolveHiddenDependencies()) {
                mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST;
                mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST);
            } else {
                mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
            }
            mAudioManager.setMode(mMostRecentMode);
            mLocalLog.log("Mode " + mMostRecentMode);
            mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS);
@@ -815,16 +870,18 @@ public class CallAudioModeStateMachine extends StateMachine {
    private final AudioManager mAudioManager;
    private final SystemStateHelper mSystemStateHelper;
    private CallAudioManager mCallAudioManager;
    private FeatureFlags mFeatureFlags;

    private int mMostRecentMode;
    private boolean mIsInitialized = false;

    public CallAudioModeStateMachine(SystemStateHelper systemStateHelper,
            AudioManager audioManager) {
            AudioManager audioManager, FeatureFlags featureFlags) {
        super(CallAudioModeStateMachine.class.getSimpleName());
        mAudioManager = audioManager;
        mSystemStateHelper = systemStateHelper;
        mMostRecentMode = AudioManager.MODE_NORMAL;
        mFeatureFlags = featureFlags;

        createStates();
    }
@@ -833,11 +890,12 @@ public class CallAudioModeStateMachine extends StateMachine {
     * Used for testing
     */
    public CallAudioModeStateMachine(SystemStateHelper systemStateHelper,
            AudioManager audioManager, Looper looper) {
            AudioManager audioManager, Looper looper, FeatureFlags featureFlags) {
        super(CallAudioModeStateMachine.class.getSimpleName(), looper);
        mAudioManager = audioManager;
        mSystemStateHelper = systemStateHelper;
        mMostRecentMode = AudioManager.MODE_NORMAL;
        mFeatureFlags = featureFlags;

        createStates();
    }
+19 −18
Original line number Diff line number Diff line
@@ -77,18 +77,18 @@ public final class CallLogManager extends CallsManagerListenerBase {
    private static class AddCallArgs {
        public AddCallArgs(Context context, CallLog.AddCallParams params,
                @Nullable LogCallCompletedListener logCallCompletedListener,
                @NonNull String callId) {
                @NonNull Call call) {
            this.context = context;
            this.params = params;
            this.logCallCompletedListener = logCallCompletedListener;
            this.callId = callId;
            this.call = call;

        }
        // Since the members are accessed directly, we don't use the
        // mXxxx notation.
        public final Context context;
        public final CallLog.AddCallParams params;
        public final String callId;
        public final Call call;
        @Nullable
        public final LogCallCompletedListener logCallCompletedListener;
    }
@@ -100,9 +100,9 @@ public final class CallLogManager extends CallsManagerListenerBase {
    // a conference was merged successfully
    private static final String REASON_IMS_MERGED_SUCCESSFULLY = "IMS_MERGED_SUCCESSFULLY";
    private static final UUID LOG_CALL_FAILED_ANOMALY_ID =
            UUID.fromString("1c4c15f3-ab4f-459c-b9ef-43d2988bae82");
            UUID.fromString("d9b38771-ff36-417b-8723-2363a870c702");
    private static final String LOG_CALL_FAILED_ANOMALY_DESC =
            "Failed to record a call to the call log.";
            "Based on the current user, Telecom detected failure to record a call to the call log.";

    private final Context mContext;
    private final CarrierConfigManager mCarrierConfigManager;
@@ -408,7 +408,7 @@ public final class CallLogManager extends CallsManagerListenerBase {
                okayToLogCall(accountHandle, logNumber, call.isEmergencyCall());
        if (okayToLog) {
            AddCallArgs args = new AddCallArgs(mContext, paramBuilder.build(),
                    logCallCompletedListener, call.getId());
                    logCallCompletedListener, call);
            Log.addEvent(call, LogUtils.Events.LOG_CALL, "number=" + Log.piiHandle(logNumber)
                    + ",postDial=" + Log.piiHandle(call.getPostDialDigits()) + ",pres="
                    + call.getHandlePresentation());
@@ -539,18 +539,16 @@ public final class CallLogManager extends CallsManagerListenerBase {
                AddCallArgs c = callList[i];
                mListeners[i] = c.logCallCompletedListener;
                try {
                    // May block.
                    ContentResolver resolver = c.context.getContentResolver();
                    Pair<Integer, Integer> startStats = getCallLogStats(resolver);
                    Pair<Integer, Integer> startStats = getCallLogStats(c.call);
                    Log.i(TAG, "LogCall; about to log callId=%s, "
                                    + "startCount=%d, startMaxId=%d",
                            c.callId, startStats.first, startStats.second);
                            c.call.getId(), startStats.first, startStats.second);

                    result[i] = Calls.addCall(c.context, c.params);
                    Pair<Integer, Integer> endStats = getCallLogStats(resolver);
                    Pair<Integer, Integer> endStats = getCallLogStats(c.call);
                    Log.i(TAG, "LogCall; logged callId=%s, uri=%s, "
                                    + "endCount=%d, endMaxId=%s",
                            c.callId, result, endStats.first, endStats.second);
                            c.call.getId(), result, endStats.first, endStats.second);
                    if ((endStats.second - startStats.second) <= 0) {
                        // No call was added or even worse we lost a call in the log.  Trigger an
                        // anomaly report.  Note: it technically possible that an app modified the
@@ -568,7 +566,7 @@ public final class CallLogManager extends CallsManagerListenerBase {
                    //
                    // We don't want to crash the whole process just because of that, so just log
                    // it instead.
                    Log.e(TAG, e, "LogCall: Exception raised adding callId=%s", c.callId);
                    Log.e(TAG, e, "LogCall: Exception raised adding callId=%s", c.call.getId());
                    result[i] = null;
                    mAnomalyReporterAdapter.reportAnomaly(LOG_CALL_FAILED_ANOMALY_ID,
                            LOG_CALL_FAILED_ANOMALY_DESC);
@@ -653,14 +651,17 @@ public final class CallLogManager extends CallsManagerListenerBase {
     * ID.  There is a limit of 500 entries in the call log for a phone account, so once we hit 500
     * we can reasonably expect that number to not change before and after logging a call.
     * We determine the maximum ID in the call log since this is a way we can objectively check if
     * the provider did record a call log entry or not.  Ideally there should me more call log
     * the provider did record a call log entry or not.  Ideally there should be more call log
     * entries after logging than before, and certainly not less.
     * @param resolver content resolver
     * @return pair with number of rows in the call log and max id.
     */
    private Pair<Integer, Integer> getCallLogStats(@NonNull ContentResolver resolver) {
    private Pair<Integer, Integer> getCallLogStats(@NonNull Call call) {
        try {
            final UserManager userManager = mContext.getSystemService(UserManager.class);
            // Ensure we query the call log based on the current user.
            final Context currentUserContext = mContext.createContextAsUser(
                    call.getAssociatedUser(), /* flags= */ 0);
            final ContentResolver currentUserResolver = currentUserContext.getContentResolver();
            final UserManager userManager = currentUserContext.getSystemService(UserManager.class);
            final int currentUserId = userManager.getProcessUserId();

            // Use shadow provider based on current user unlock state.
@@ -672,7 +673,7 @@ public final class CallLogManager extends CallsManagerListenerBase {
            }
            int maxCallId = -1;
            int numFound;
            try (Cursor countCursor = resolver.query(providerUri,
            try (Cursor countCursor = currentUserResolver.query(providerUri,
                    new String[]{Calls._ID},
                    null,
                    null,
+1 −1
Original line number Diff line number Diff line
@@ -655,7 +655,7 @@ public class CallsManager extends Call.ListenerBase
                mTimeoutsAdapter, mLock);
        mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine,
                this, callAudioModeStateMachineFactory.create(systemStateHelper,
                (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)),
                (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE), featureFlags),
                playerFactory, mRinger, new RingbackPlayer(playerFactory),
                bluetoothStateReceiver, mDtmfLocalTonePlayer);

+2 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Icon;
import android.media.AudioDeviceInfo;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Binder;
@@ -110,6 +111,7 @@ public class BasicCallTests extends TelecomSystemTest {
        doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt());
        mPackageManager = mContext.getPackageManager();
        when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(Binder.getCallingUid());
        when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false);
    }

    @Override
+64 −18
Original line number Diff line number Diff line
@@ -16,14 +16,29 @@

package com.android.server.telecom.tests;

import static com.android.server.telecom.CallAudioModeStateMachine.CALL_AUDIO_FOCUS_REQUEST;
import static com.android.server.telecom.CallAudioModeStateMachine.RING_AUDIO_FOCUS_REQUEST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.os.HandlerThread;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.server.telecom.CallAudioManager;
import com.android.server.telecom.CallAudioModeStateMachine;
import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.CallAudioModeStateMachine.MessageArgs.Builder;
import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.SystemStateHelper;

import org.junit.After;
@@ -31,18 +46,9 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(JUnit4.class)
public class CallAudioModeStateMachineTest extends TelecomTestCase {
    private static final int TEST_TIMEOUT = 1000;
@@ -62,6 +68,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
        super.setUp();
        when(mCallAudioManager.getCallAudioRouteStateMachine())
                .thenReturn(mCallAudioRouteStateMachine);
        when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false);
    }

    @Override
@@ -76,7 +83,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
    @Test
    public void testNoFocusWhenRingerSilenced() throws Throwable {
        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
                mAudioManager, mTestThread.getLooper());
                mAudioManager, mTestThread.getLooper(), mFeatureFlags);
        sm.setCallAudioManager(mCallAudioManager);
        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -108,7 +115,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
    @Test
    public void testSwitchToStreamingMode() {
        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
                mAudioManager, mTestThread.getLooper());
                mAudioManager, mTestThread.getLooper(), mFeatureFlags);
        sm.setCallAudioManager(mCallAudioManager);
        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -138,7 +145,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
    @Test
    public void testExitStreamingMode() {
        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
                mAudioManager, mTestThread.getLooper());
                mAudioManager, mTestThread.getLooper(), mFeatureFlags);
        sm.setCallAudioManager(mCallAudioManager);
        sm.sendMessage(CallAudioModeStateMachine.ENTER_STREAMING_FOCUS_FOR_TESTING);
        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -166,7 +173,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
    @Test
    public void testNoRingWhenDeviceIsAtEar() {
        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
                mAudioManager, mTestThread.getLooper());
                mAudioManager, mTestThread.getLooper(), mFeatureFlags);
        sm.setCallAudioManager(mCallAudioManager);
        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
        sm.sendMessage(CallAudioModeStateMachine.NEW_HOLDING_CALL, new Builder()
@@ -202,7 +209,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
    @Test
    public void testRegainFocusWhenHfpIsConnectedSilenced() throws Throwable {
        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
                mAudioManager, mTestThread.getLooper());
                mAudioManager, mTestThread.getLooper(), mFeatureFlags);
        sm.setCallAudioManager(mCallAudioManager);
        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -246,7 +253,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
    @Test
    public void testDoNotRingTwiceWhenHfpConnected() {
        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
                mAudioManager, mTestThread.getLooper());
                mAudioManager, mTestThread.getLooper(), mFeatureFlags);
        sm.setCallAudioManager(mCallAudioManager);
        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -284,7 +291,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
    @Test
    public void testStartRingingAfterHfpConnectedIfNotAlreadyPlaying() {
        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
                mAudioManager, mTestThread.getLooper());
                mAudioManager, mTestThread.getLooper(), mFeatureFlags);
        sm.setCallAudioManager(mCallAudioManager);
        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
@@ -318,7 +325,46 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase {
        verify(mCallAudioManager, times(2)).startRinging();
    }

    @SmallTest
    @Test
    public void testAudioFocusRequestWithResolveHiddenDependencies() {
        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper,
                mAudioManager, mTestThread.getLooper(), mFeatureFlags);
        when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(true);
        ArgumentCaptor<AudioFocusRequest> captor = ArgumentCaptor.forClass(AudioFocusRequest.class);
        sm.setCallAudioManager(mCallAudioManager);

        resetMocks();
        when(mCallAudioManager.startRinging()).thenReturn(true);
        when(mCallAudioManager.isRingtonePlaying()).thenReturn(false);

        sm.sendMessage(CallAudioModeStateMachine.ENTER_RING_FOCUS_FOR_TESTING);
        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
        verify(mAudioManager).requestAudioFocus(captor.capture());
        assertTrue(areAudioFocusRequestsMatch(captor.getValue(), RING_AUDIO_FOCUS_REQUEST));

        sm.sendMessage(CallAudioModeStateMachine.ENTER_CALL_FOCUS_FOR_TESTING);
        waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
        verify(mAudioManager, atLeast(1)).requestAudioFocus(captor.capture());
        AudioFocusRequest request = captor.getValue();
        assertTrue(areAudioFocusRequestsMatch(request, CALL_AUDIO_FOCUS_REQUEST));

        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
    }

    private void resetMocks() {
        clearInvocations(mCallAudioManager, mAudioManager);
    }

    private boolean areAudioFocusRequestsMatch(AudioFocusRequest r1, AudioFocusRequest r2) {
        if ((r1 == null) || (r2 == null)) {
            return false;
        }

        if (r1.getFocusGain() != r2.getFocusGain()) {
            return false;
        }

        return r1.getAudioAttributes().equals(r2.getAudioAttributes());
    }
}
Loading