diff options
4 files changed, 213 insertions, 37 deletions
diff --git a/InCallUI/src/com/android/incallui/StatusBarNotifier.java b/InCallUI/src/com/android/incallui/StatusBarNotifier.java index 623cbb667..6c00164b9 100644 --- a/InCallUI/src/com/android/incallui/StatusBarNotifier.java +++ b/InCallUI/src/com/android/incallui/StatusBarNotifier.java @@ -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(); + } } /** diff --git a/InCallUI/src/com/android/incallui/ringtone/DialerRingtoneManager.java b/InCallUI/src/com/android/incallui/ringtone/DialerRingtoneManager.java index 8d4d068e1..29d3d9de3 100644 --- a/InCallUI/src/com/android/incallui/ringtone/DialerRingtoneManager.java +++ b/InCallUI/src/com/android/incallui/ringtone/DialerRingtoneManager.java @@ -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; } } diff --git a/InCallUI/src/com/android/incallui/ringtone/InCallTonePlayer.java b/InCallUI/src/com/android/incallui/ringtone/InCallTonePlayer.java index 2a94f226f..be7fffbcb 100644 --- a/InCallUI/src/com/android/incallui/ringtone/InCallTonePlayer.java +++ b/InCallUI/src/com/android/incallui/ringtone/InCallTonePlayer.java @@ -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(); diff --git a/InCallUI/tests/src/com/android/incallui/ringtone/DialerRingtoneManagerTest.java b/InCallUI/tests/src/com/android/incallui/ringtone/DialerRingtoneManagerTest.java index e116a19fb..01db20272 100644 --- a/InCallUI/tests/src/com/android/incallui/ringtone/DialerRingtoneManagerTest.java +++ b/InCallUI/tests/src/com/android/incallui/ringtone/DialerRingtoneManagerTest.java @@ -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(); } } |