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

Commit 054559b6 authored by Brandon Maxwell's avatar Brandon Maxwell
Browse files

Integrating DialerRingtoneManager and InCallTonePlayer

This change makes the Call Waiting tone actually play during the
Call Waiting use case.

+ Plugging InCallTonePlayer into the DialerRingtoneManager in the
StatusBarNotifier
+ Test fixes
 + Added tests for when Dialer ringing is disabled
 + Added tests for DialerRingtoneManager#playCallWaitingTone
- Removed unneeded @NeededForTesting annotations from InCallTonePlayer
  since they won't be stipped out by proguard.
Change-Id: I49a83d2a7fe6edf5f9ec88db973a5f37e307f23a
parent 37274fed
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -50,10 +50,14 @@ import com.android.contacts.common.preference.ContactsPreferences;
import com.android.contacts.common.testing.NeededForTesting;
import com.android.contacts.common.util.BitmapUtil;
import com.android.contacts.common.util.ContactDisplayUtils;
import com.android.incallui.Call.State;
import com.android.incallui.ContactInfoCache.ContactCacheEntry;
import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
import com.android.incallui.InCallPresenter.InCallState;
import com.android.incallui.async.PausableExecutorImpl;
import com.android.incallui.ringtone.DialerRingtoneManager;
import com.android.incallui.ringtone.InCallTonePlayer;
import com.android.incallui.ringtone.ToneGeneratorFactory;

import java.util.Objects;

@@ -95,7 +99,12 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener,
        mContactInfoCache = contactInfoCache;
        mNotificationManager =
                (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        mDialerRingtoneManager = new DialerRingtoneManager();
        mDialerRingtoneManager = new DialerRingtoneManager(
                new InCallTonePlayer(
                        AudioModeProvider.getInstance(),
                        new ToneGeneratorFactory(),
                        new PausableExecutorImpl()),
                CallList.getInstance());
        mCurrentNotification = NOTIFICATION_NONE;
    }

@@ -308,7 +317,8 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener,
            notification.vibrate = VIBRATE_PATTERN;
        }
        if (mDialerRingtoneManager.shouldPlayCallWaitingTone(callState)) {
            // TODO (maxwelb) play call waiting
            Log.v(this, "Playing call waiting tone");
            mDialerRingtoneManager.playCallWaitingTone();
        }
        if (mCurrentNotification != notificationType && mCurrentNotification != NOTIFICATION_NONE) {
            Log.i(this, "Previous notification already showing - cancelling "
@@ -699,7 +709,9 @@ public class StatusBarNotifier implements InCallPresenter.InCallStateListener,

    @Override
    public void onCallChanged(Call call) {
        // no-op
        if (CallList.getInstance().getIncomingCall() == null) {
            mDialerRingtoneManager.stopCallWaitingTone();
        }
    }

    /**
+64 −10
Original line number Diff line number Diff line
@@ -13,14 +13,19 @@
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.incallui.ringtone;

import com.google.common.base.Preconditions;

import android.net.Uri;
import android.support.annotation.Nullable;

import com.android.contacts.common.compat.CompatUtils;
import com.android.contacts.common.testing.NeededForTesting;
import com.android.incallui.Call;
import com.android.incallui.Call.State;
import com.android.incallui.CallList;

/**
 * Class that determines when ringtones should be played and can play the call waiting tone when
@@ -30,9 +35,25 @@ public class DialerRingtoneManager {

    /*
     * Flag used to determine if the Dialer is responsible for playing ringtones for incoming calls.
     * Once we're ready to enable Dialer Ringing, these flags should be removed.
     */
    private static final boolean IS_DIALER_RINGING_ENABLED = false;
    private boolean mForceDialerRingingEnabled = false;
    private Boolean mIsDialerRingingEnabledForTesting;

    private final InCallTonePlayer mInCallTonePlayer;
    private final CallList mCallList;

    /**
     * Creates the DialerRingtoneManager with the given {@link InCallTonePlayer}.
     *
     * @param inCallTonePlayer the tone player used to play in-call tones.
     * @param callList the CallList used to check for {@link State#CALL_WAITING}
     * @throws NullPointerException if inCallTonePlayer or callList are null
     */
    public DialerRingtoneManager(InCallTonePlayer inCallTonePlayer, CallList callList) {
        mInCallTonePlayer = Preconditions.checkNotNull(inCallTonePlayer);
        mCallList = Preconditions.checkNotNull(callList);
    }

    /**
     * Determines if a ringtone should be played for the given call state (see {@link State}) and
@@ -43,14 +64,27 @@ public class DialerRingtoneManager {
     * @return {@code true} if the ringtone should be played, {@code false} otherwise.
     */
    public boolean shouldPlayRingtone(int callState, @Nullable Uri ringtoneUri) {
        return CompatUtils.isNCompatible()
                && isDialerRingingEnabled()
                && callState == State.INCOMING
        return isDialerRingingEnabled()
                && translateCallStateForCallWaiting(callState) == State.INCOMING
                && ringtoneUri != null;
    }

    /**
     * The incoming callState is never set as {@link State#CALL_WAITING} because
     * {@link Call#translateState(int)} doesn't account for that case, check for it here
     */
    private int translateCallStateForCallWaiting(int callState) {
        if (callState != State.INCOMING) {
            return callState;
        }
        return mCallList.getActiveCall() == null ? State.INCOMING : State.CALL_WAITING;
    }

    private boolean isDialerRingingEnabled() {
        return mForceDialerRingingEnabled || IS_DIALER_RINGING_ENABLED;
        if (mIsDialerRingingEnabledForTesting != null) {
            return mIsDialerRingingEnabledForTesting;
        }
        return CompatUtils.isNCompatible() && IS_DIALER_RINGING_ENABLED;
    }

    /**
@@ -61,13 +95,33 @@ public class DialerRingtoneManager {
     * @return {@code true} if the call waiting tone should be played, {@code false} otherwise.
     */
    public boolean shouldPlayCallWaitingTone(int callState) {
        return CompatUtils.isNCompatible()
                && isDialerRingingEnabled()
                && callState == State.CALL_WAITING;
        return isDialerRingingEnabled()
                && translateCallStateForCallWaiting(callState) == State.CALL_WAITING
                && !mInCallTonePlayer.isPlayingTone();
    }

    /**
     * Plays the call waiting tone.
     */
    public void playCallWaitingTone() {
        if (!isDialerRingingEnabled()) {
            return;
        }
        mInCallTonePlayer.play(InCallTonePlayer.TONE_CALL_WAITING);
    }

    /**
     * Stops playing the call waiting tone.
     */
    public void stopCallWaitingTone() {
        if (!isDialerRingingEnabled()) {
            return;
        }
        mInCallTonePlayer.stop();
    }

    @NeededForTesting
    void forceDialerRingingEnabled() {
        mForceDialerRingingEnabled = true;
    void setDialerRingingEnabledForTesting(boolean status) {
        mIsDialerRingingEnabledForTesting = status;
    }
}
+0 −5
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import javax.annotation.concurrent.NotThreadSafe;
 * Class responsible for playing in-call related tones in a background thread. This class only
 * allows one tone to be played at a time.
 */
@NeededForTesting
public class InCallTonePlayer {

    public static final int TONE_CALL_WAITING = 4;
@@ -62,7 +61,6 @@ public class InCallTonePlayer {
     * @throws NullPointerException if audioModeProvider, toneGeneratorFactory, or executor are
     * {@code null}.
     */
    @NeededForTesting
    public InCallTonePlayer(AudioModeProvider audioModeProvider,
            ToneGeneratorFactory toneGeneratorFactory, PausableExecutor executor) {
        mAudioModeProvider = Preconditions.checkNotNull(audioModeProvider);
@@ -73,7 +71,6 @@ public class InCallTonePlayer {
    /**
     * @return {@code true} if a tone is currently playing, {@code false} otherwise
     */
    @NeededForTesting
    public boolean isPlayingTone() {
        return mNumPlayingTones != null && mNumPlayingTones.getCount() > 0;
    }
@@ -85,7 +82,6 @@ public class InCallTonePlayer {
     * @throws IllegalStateException if a tone is already playing
     * @throws IllegalArgumentException if the tone is invalid
     */
    @NeededForTesting
    public void play(int tone) {
        if (isPlayingTone()) {
            throw new IllegalStateException("Tone already playing");
@@ -155,7 +151,6 @@ public class InCallTonePlayer {
    /**
     * Stops playback of the current tone.
     */
    @NeededForTesting
    public void stop() {
        if (mNumPlayingTones != null) {
            mNumPlayingTones.countDown();
+134 −19
Original line number Diff line number Diff line
@@ -13,78 +13,129 @@
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.incallui.ringtone;

import android.media.RingtoneManager;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.contacts.common.compat.CompatUtils;
import com.android.incallui.Call;
import com.android.incallui.Call.State;
import com.android.incallui.CallList;

import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

@SmallTest
public class DialerRingtoneManagerTest extends AndroidTestCase {

    private DialerRingtoneManager mRingtoneManager;
    private static final Uri RINGTONE_URI = RingtoneManager
            .getDefaultUri(RingtoneManager.TYPE_RINGTONE);

    @Mock private InCallTonePlayer mInCallTonePlayer;
    @Mock private CallList mCallList;
    @Mock private Call mCall;
    private DialerRingtoneManager mRingtoneManagerEnabled;
    private DialerRingtoneManager mRingtoneManagerDisabled;

    @Override
    public void setUp() {
        mRingtoneManager = new DialerRingtoneManager();
        mRingtoneManager.forceDialerRingingEnabled();
    public void setUp() throws Exception {
        super.setUp();
        MockitoAnnotations.initMocks(this);
        mRingtoneManagerEnabled = new DialerRingtoneManager(mInCallTonePlayer, mCallList);
        mRingtoneManagerEnabled.setDialerRingingEnabledForTesting(true);
        mRingtoneManagerDisabled = new DialerRingtoneManager(mInCallTonePlayer, mCallList);
        mRingtoneManagerDisabled.setDialerRingingEnabledForTesting(false);
    }

    @Override
    public void tearDown() {
        mRingtoneManager = null;
    public void testNullInCallTonePlayer() {
        try {
            new DialerRingtoneManager(null, mCallList);
            fail();
        } catch (NullPointerException e) {}
    }

    public void testNullCallList() {
        try {
            new DialerRingtoneManager(mInCallTonePlayer, null);
            fail();
        } catch (NullPointerException e) {}
    }

    public void testShouldPlayRingtone_M() {
        if (CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManager.shouldPlayRingtone(0, null));
        assertFalse(mRingtoneManagerEnabled.shouldPlayRingtone(0, RINGTONE_URI));
    }

    public void testShouldPlayRingtone_N_NullUri() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManager.shouldPlayRingtone(State.INCOMING, null));
        assertFalse(mRingtoneManagerEnabled.shouldPlayRingtone(State.INCOMING, null));
    }

    public void testShouldPlayRingtone_N_Disabled() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManagerDisabled.shouldPlayRingtone(State.INCOMING, RINGTONE_URI));
    }

    public void testShouldPlayRingtone_N_NotIncoming() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManager.shouldPlayRingtone(State.ACTIVE, null));
        assertFalse(mRingtoneManagerEnabled.shouldPlayRingtone(State.ACTIVE, RINGTONE_URI));
    }

    // Specific case for call waiting since that needs its own sound
    public void testShouldPlayRingtone_N_CallWaiting() {
    public void testShouldPlayRingtone_N_CallWaitingByState() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManagerEnabled.shouldPlayRingtone(State.CALL_WAITING, RINGTONE_URI));
    }

    public void testShouldPlayRingtone_N_CallWaitingByActiveCall() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManager.shouldPlayRingtone(State.CALL_WAITING, null));
        Mockito.when(mCallList.getActiveCall()).thenReturn(mCall);
        assertFalse(mRingtoneManagerEnabled.shouldPlayRingtone(State.INCOMING, RINGTONE_URI));
    }

    public void testShouldPlayRingtone_N() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertTrue(mRingtoneManager.shouldPlayRingtone(State.INCOMING,
                RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)));
        assertTrue(mRingtoneManagerEnabled.shouldPlayRingtone(State.INCOMING, RINGTONE_URI));
    }

    public void testShouldPlayCallWaitingTone_M() {
        if (CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManager.shouldPlayCallWaitingTone(0));
        assertFalse(mRingtoneManagerEnabled.shouldPlayCallWaitingTone(0));
    }

    public void testShouldPlayCallWaitingTone_N_Disabled() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManagerDisabled.shouldPlayCallWaitingTone(State.CALL_WAITING));
    }

    public void testShouldPlayCallWaitingTone_N_NotCallWaiting() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManager.shouldPlayCallWaitingTone(State.ACTIVE));
        assertFalse(mRingtoneManagerEnabled.shouldPlayCallWaitingTone(State.ACTIVE));
    }

    // Specific case for incoming since it plays its own sound
@@ -92,13 +143,77 @@ public class DialerRingtoneManagerTest extends AndroidTestCase {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertFalse(mRingtoneManager.shouldPlayCallWaitingTone(State.INCOMING));
        assertFalse(mRingtoneManagerEnabled.shouldPlayCallWaitingTone(State.INCOMING));
    }

    public void testShouldPlayCallWaitingTone_N_AlreadyPlaying() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        Mockito.when(mInCallTonePlayer.isPlayingTone()).thenReturn(true);
        assertFalse(mRingtoneManagerEnabled.shouldPlayCallWaitingTone(State.CALL_WAITING));
    }

    public void testShouldPlayCallWaitingTone_N_ByState() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertTrue(mRingtoneManagerEnabled.shouldPlayCallWaitingTone(State.CALL_WAITING));
    }

    public void testShouldPlayCallWaitingTone_N_ByActiveCall() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        Mockito.when(mCallList.getActiveCall()).thenReturn(mCall);
        assertTrue(mRingtoneManagerEnabled.shouldPlayCallWaitingTone(State.INCOMING));
    }

    public void testPlayCallWaitingTone_M() {
        if (CompatUtils.isNCompatible()) {
            return;
        }
        mRingtoneManagerEnabled.playCallWaitingTone();
        Mockito.verify(mInCallTonePlayer, Mockito.never()).play(Mockito.anyInt());
    }

    public void testPlayCallWaitingTone_N_NotEnabled() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        mRingtoneManagerDisabled.playCallWaitingTone();
        Mockito.verify(mInCallTonePlayer, Mockito.never()).play(Mockito.anyInt());
    }

    public void testPlayCallWaitingTone_N() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        mRingtoneManagerEnabled.playCallWaitingTone();
        Mockito.verify(mInCallTonePlayer).play(Mockito.anyInt());
    }

    public void testStopCallWaitingTone_M() {
        if (CompatUtils.isNCompatible()) {
            return;
        }
        mRingtoneManagerEnabled.stopCallWaitingTone();
        Mockito.verify(mInCallTonePlayer, Mockito.never()).stop();
    }

    public void testStopCallWaitingTone_N_NotEnabled() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        mRingtoneManagerDisabled.stopCallWaitingTone();
        Mockito.verify(mInCallTonePlayer, Mockito.never()).stop();
    }

    public void testShouldPlayCallWaitingTone_N() {
    public void testStopCallWaitingTone_N() {
        if (!CompatUtils.isNCompatible()) {
            return;
        }
        assertTrue(mRingtoneManager.shouldPlayCallWaitingTone(State.CALL_WAITING));
        mRingtoneManagerEnabled.stopCallWaitingTone();
        Mockito.verify(mInCallTonePlayer).stop();
    }
}