Merge changes I4ad55f38,Ie8fb633c

* changes:
  Adding method to check if call waiting tone should be played
  Refactored dialer Ringtone code in prep for call waiting
diff --git a/InCallUI/src/com/android/incallui/StatusBarNotifier.java b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
index e0bca44..985c885 100644
--- a/InCallUI/src/com/android/incallui/StatusBarNotifier.java
+++ b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
@@ -45,13 +45,13 @@
 
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.ContactsUtils.UserType;
-import com.android.contacts.common.compat.CompatUtils;
 import com.android.contacts.common.preference.ContactsPreferences;
 import com.android.contacts.common.util.BitmapUtil;
 import com.android.contacts.common.util.ContactDisplayUtils;
 import com.android.incallui.ContactInfoCache.ContactCacheEntry;
 import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
 import com.android.incallui.InCallPresenter.InCallState;
+import com.android.incallui.ringtone.DialerRingtoneManager;
 
 import java.util.Objects;
 
@@ -61,11 +61,6 @@
 public class StatusBarNotifier implements InCallPresenter.InCallStateListener,
         CallList.CallUpdateListener {
 
-    /*
-     * Flag used to determine if the Dialer is responsible for playing ringtones for incoming calls.
-     */
-    private static final boolean IS_DIALER_RINGING_ENABLED = false;
-
     // Notification types
     // Indicates that no notification is currently showing.
     private static final int NOTIFICATION_NONE = 0;
@@ -80,6 +75,7 @@
     private final ContactsPreferences mContactsPreferences;
     private final ContactInfoCache mContactInfoCache;
     private final NotificationManager mNotificationManager;
+    private final DialerRingtoneManager mDialerRingtoneManager;
     private int mCurrentNotification = NOTIFICATION_NONE;
     private int mCallState = Call.State.INVALID;
     private int mSavedIcon = 0;
@@ -97,6 +93,7 @@
         mContactInfoCache = contactInfoCache;
         mNotificationManager =
                 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        mDialerRingtoneManager = new DialerRingtoneManager();
         mCurrentNotification = NOTIFICATION_NONE;
     }
 
@@ -233,7 +230,7 @@
             return;
         }
 
-        final int state = call.getState();
+        final int callState = call.getState();
 
         // Check if data has changed; if nothing is different, don't issue another notification.
         final int iconResId = getIconToDisplay(call);
@@ -243,13 +240,13 @@
         final String contentTitle = getContentTitle(contactInfo, call);
 
         final int notificationType;
-        if (state == Call.State.INCOMING || state == Call.State.CALL_WAITING) {
+        if (callState == Call.State.INCOMING || callState == Call.State.CALL_WAITING) {
             notificationType = NOTIFICATION_INCOMING_CALL;
         } else {
             notificationType = NOTIFICATION_IN_CALL;
         }
 
-        if (!checkForChangeAndSaveData(iconResId, content, largeIcon, contentTitle, state,
+        if (!checkForChangeAndSaveData(iconResId, content, largeIcon, contentTitle, callState,
                 notificationType, contactInfo.contactRingtoneUri)) {
             return;
         }
@@ -289,7 +286,7 @@
             addDismissUpgradeRequestAction(builder);
             addAcceptUpgradeRequestAction(builder);
         } else {
-            createIncomingCallNotification(call, state, builder);
+            createIncomingCallNotification(call, callState, builder);
         }
 
         addPersonReference(builder, contactInfo, call);
@@ -299,7 +296,7 @@
          */
         Notification notification = builder.build();
 
-        if (shouldNotificationPlayRingtone(notificationType, contactInfo.contactRingtoneUri)) {
+        if (mDialerRingtoneManager.shouldPlayRingtone(callState, contactInfo.contactRingtoneUri)) {
             notification.flags |= Notification.FLAG_INSISTENT;
             notification.sound = contactInfo.contactRingtoneUri;
             AudioAttributes.Builder audioAttributes = new AudioAttributes.Builder();
@@ -308,6 +305,9 @@
             notification.audioAttributes = audioAttributes.build();
             notification.vibrate = VIBRATE_PATTERN;
         }
+        if (mDialerRingtoneManager.shouldPlayCallWaitingTone(callState)) {
+            // TODO (maxwelb) play call waiting
+        }
         if (mCurrentNotification != notificationType && mCurrentNotification != NOTIFICATION_NONE) {
             Log.i(this, "Previous notification already showing - cancelling "
                     + mCurrentNotification);
@@ -318,16 +318,6 @@
         mCurrentNotification = notificationType;
     }
 
-    /*
-     * The Notification should only play the ringtone once it's had a chance to look up the contact.
-     * Until the lookup is complete, the ringtone Uri is null
-     */
-    private boolean shouldNotificationPlayRingtone(int notificationType, Uri ringtoneUri) {
-        return CompatUtils.isNCompatible() && IS_DIALER_RINGING_ENABLED
-                && notificationType == NOTIFICATION_INCOMING_CALL
-                && ringtoneUri != null;
-    }
-
     private void createIncomingCallNotification(
             Call call, int state, Notification.Builder builder) {
         if (state == Call.State.ACTIVE) {
diff --git a/InCallUI/src/com/android/incallui/ringtone/DialerRingtoneManager.java b/InCallUI/src/com/android/incallui/ringtone/DialerRingtoneManager.java
new file mode 100644
index 0000000..8d4d068
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/ringtone/DialerRingtoneManager.java
@@ -0,0 +1,73 @@
+/*
+ * 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.incallui.ringtone;
+
+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.State;
+
+/**
+ * Class that determines when ringtones should be played and can play the call waiting tone when
+ * necessary.
+ */
+public class DialerRingtoneManager {
+
+    /*
+     * Flag used to determine if the Dialer is responsible for playing ringtones for incoming calls.
+     */
+    private static final boolean IS_DIALER_RINGING_ENABLED = false;
+    private boolean mForceDialerRingingEnabled = false;
+
+    /**
+     * Determines if a ringtone should be played for the given call state (see {@link State}) and
+     * {@link Uri}.
+     *
+     * @param callState the call state for the call being checked.
+     * @param ringtoneUri the ringtone to potentially play.
+     * @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
+                && ringtoneUri != null;
+    }
+
+    private boolean isDialerRingingEnabled() {
+        return mForceDialerRingingEnabled || IS_DIALER_RINGING_ENABLED;
+    }
+
+    /**
+     * Determines if a call waiting tone should be played for the the given call state
+     * (see {@link State}).
+     *
+     * @param callState the call state for the call being checked.
+     * @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;
+    }
+
+    @NeededForTesting
+    void forceDialerRingingEnabled() {
+        mForceDialerRingingEnabled = true;
+    }
+}
diff --git a/InCallUI/tests/src/com/android/incallui/ringtone/RingtoneManagerTest.java b/InCallUI/tests/src/com/android/incallui/ringtone/RingtoneManagerTest.java
new file mode 100644
index 0000000..f94f71d
--- /dev/null
+++ b/InCallUI/tests/src/com/android/incallui/ringtone/RingtoneManagerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.incallui.ringtone;
+
+import android.media.RingtoneManager;
+import android.test.AndroidTestCase;
+
+import com.android.contacts.common.compat.CompatUtils;
+import com.android.incallui.Call.State;
+
+public class RingtoneManagerTest extends AndroidTestCase {
+
+    private DialerRingtoneManager mRingtoneManager;
+
+    @Override
+    public void setUp() {
+        mRingtoneManager = new DialerRingtoneManager();
+        mRingtoneManager.forceDialerRingingEnabled();
+    }
+
+    @Override
+    public void tearDown() {
+        mRingtoneManager = null;
+    }
+
+    public void testShouldPlayRingtone_M() {
+        if (CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertFalse(mRingtoneManager.shouldPlayRingtone(0, null));
+    }
+
+    public void testShouldPlayRingtone_N_NullUri() {
+        if (!CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertFalse(mRingtoneManager.shouldPlayRingtone(State.INCOMING, null));
+    }
+
+    public void testShouldPlayRingtone_N_NotIncoming() {
+        if (!CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertFalse(mRingtoneManager.shouldPlayRingtone(State.ACTIVE, null));
+    }
+
+    // Specific case for call waiting since that needs its own sound
+    public void testShouldPlayRingtone_N_CallWaiting() {
+        if (!CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertFalse(mRingtoneManager.shouldPlayRingtone(State.CALL_WAITING, null));
+    }
+
+    public void testShouldPlayRingtone_N() {
+        if (!CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertTrue(mRingtoneManager.shouldPlayRingtone(State.INCOMING,
+                RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)));
+    }
+
+    public void testShouldPlayCallWaitingTone_M() {
+        if (CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertFalse(mRingtoneManager.shouldPlayCallWaitingTone(0));
+    }
+
+    public void testShouldPlayCallWaitingTone_N_NotCallWaiting() {
+        if (!CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertFalse(mRingtoneManager.shouldPlayCallWaitingTone(State.ACTIVE));
+    }
+
+    // Specific case for incoming since it plays its own sound
+    public void testShouldPlayCallWaitingTone_N_Incoming() {
+        if (!CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertFalse(mRingtoneManager.shouldPlayCallWaitingTone(State.INCOMING));
+    }
+
+    public void testShouldPlayCallWaitingTone_N() {
+        if (!CompatUtils.isNCompatible()) {
+            return;
+        }
+        assertTrue(mRingtoneManager.shouldPlayCallWaitingTone(State.CALL_WAITING));
+    }
+}