Add custom ringtone support.
Bug: 15313520
Change-Id: Ib4a553139b5b9d7852bdeb57ad5e33dfa35f9be8
diff --git a/src/com/android/telecomm/AsyncRingtonePlayer.java b/src/com/android/telecomm/AsyncRingtonePlayer.java
index 1c5cafe..7bec55f 100644
--- a/src/com/android/telecomm/AsyncRingtonePlayer.java
+++ b/src/com/android/telecomm/AsyncRingtonePlayer.java
@@ -19,6 +19,7 @@
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
+import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@@ -42,15 +43,15 @@
private Ringtone mRingtone;
/** Plays the ringtone. */
- void play() {
+ void play(Uri ringtone) {
Log.d(this, "Posting play.");
- postMessage(EVENT_PLAY, true /* shouldCreateHandler */);
+ postMessage(EVENT_PLAY, true /* shouldCreateHandler */, ringtone);
}
/** Stops playing the ringtone. */
void stop() {
Log.d(this, "Posting stop.");
- postMessage(EVENT_STOP, false /* shouldCreateHandler */);
+ postMessage(EVENT_STOP, false /* shouldCreateHandler */, null);
}
/**
@@ -60,7 +61,7 @@
* @param messageCode The message to post.
* @param shouldCreateHandler True when a handler should be created to handle this message.
*/
- private void postMessage(int messageCode, boolean shouldCreateHandler) {
+ private void postMessage(int messageCode, boolean shouldCreateHandler, Uri ringtone) {
synchronized(this) {
if (mHandler == null && shouldCreateHandler) {
mHandler = getNewHandler();
@@ -69,7 +70,7 @@
if (mHandler == null) {
Log.d(this, "Message %d skipped because there is no handler.", messageCode);
} else {
- mHandler.sendEmptyMessage(messageCode);
+ mHandler.obtainMessage(messageCode, ringtone).sendToTarget();
}
}
}
@@ -88,7 +89,7 @@
public void handleMessage(Message msg) {
switch(msg.what) {
case EVENT_PLAY:
- handlePlay();
+ handlePlay((Uri) msg.obj);
break;
case EVENT_STOP:
handleStop();
@@ -101,12 +102,12 @@
/**
* Starts the actual playback of the ringtone. Executes on ringtone-thread.
*/
- private void handlePlay() {
+ private void handlePlay(Uri ringtoneUri) {
ThreadUtil.checkNotOnMainThread();
Log.i(this, "Play ringtone.");
if (mRingtone == null) {
- mRingtone = getCurrentRingtone();
+ mRingtone = getRingtone(ringtoneUri);
// Cancel everything if there is no ringtone.
if (mRingtone == null) {
@@ -148,10 +149,12 @@
}
}
- private Ringtone getCurrentRingtone() {
- // TODO: Needs support for custom ringtones.
- Ringtone ringtone = RingtoneManager.getRingtone(
- TelecommApp.getInstance(), Settings.System.DEFAULT_RINGTONE_URI);
+ private Ringtone getRingtone(Uri ringtoneUri) {
+ if (ringtoneUri == null) {
+ ringtoneUri = Settings.System.DEFAULT_RINGTONE_URI;
+ }
+
+ Ringtone ringtone = RingtoneManager.getRingtone(TelecommApp.getInstance(), ringtoneUri);
ringtone.setStreamType(AudioManager.STREAM_RING);
return ringtone;
}
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index c51632c..2bcc978 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -709,6 +709,10 @@
mHandoffCallServiceDescriptor = descriptor;
}
+ Uri getRingtone() {
+ return mCallerInfo == null ? null : mCallerInfo.contactRingtoneUri;
+ }
+
/**
* @return True if the call is ringing, else logs the action name.
*/
@@ -737,6 +741,7 @@
mQueryToken++; // Updated so that previous queries can no longer set the information.
mCallerInfo = null;
if (!TextUtils.isEmpty(number)) {
+ Log.v(this, "Looking up information for: %s.", Log.piiHandle(number));
CallerInfoAsyncQuery.startQuery(
mQueryToken,
TelecommApp.getInstance(),
@@ -758,6 +763,7 @@
if (mQueryToken == token) {
mCallerInfo = callerInfo;
+ Log.i(this, "CallerInfo received for %s: %s", Log.piiHandle(mHandle), callerInfo);
if (mCallerInfo.person_id != 0) {
Uri personUri =
diff --git a/src/com/android/telecomm/CallAudioManager.java b/src/com/android/telecomm/CallAudioManager.java
index fb8ed9e..43b102b 100644
--- a/src/com/android/telecomm/CallAudioManager.java
+++ b/src/com/android/telecomm/CallAudioManager.java
@@ -173,7 +173,7 @@
if (newIsPluggedIn) {
newRoute = CallAudioState.ROUTE_WIRED_HEADSET;
} else if (mWasSpeakerOn) {
- Call call = CallsManager.getInstance().getForegroundCall();
+ Call call = getForegroundCall();
if (call != null && call.isAlive()) {
// Restore the speaker state.
newRoute = CallAudioState.ROUTE_SPEAKER;
@@ -263,7 +263,7 @@
if (mIsRinging) {
requestAudioFocusAndSetMode(AudioManager.STREAM_RING, AudioManager.MODE_RINGTONE);
} else {
- Call call = CallsManager.getInstance().getForegroundCall();
+ Call call = getForegroundCall();
if (call != null) {
int mode = TelephonyUtil.isCurrentlyPSTNCall(call) ?
AudioManager.MODE_IN_CALL : AudioManager.MODE_IN_COMMUNICATION;
@@ -282,10 +282,9 @@
Log.v(this, "setSystemAudioStreamAndMode, stream: %d -> %d", mAudioFocusStreamType, stream);
Preconditions.checkState(stream != STREAM_NONE);
- // Only request audio focus once. If the stream type changes there's no need to abandon
- // and re-request audio focus. The system doesn't really care about the stream we requested
- // focus for so just silently switch.
- if (mAudioFocusStreamType == STREAM_NONE) {
+ // Even if we already have focus, if the stream is different we update audio manager to give
+ // it a hint about the purpose of our focus.
+ if (mAudioFocusStreamType != stream) {
Log.v(this, "requesting audio focus for stream: %d", stream);
mAudioManager.requestAudioFocusForCall(stream,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
@@ -389,4 +388,18 @@
call.getCallService().onAudioStateChanged(call, mAudioState);
}
}
+
+ /**
+ * Returns the current foreground call in order to properly set the audio mode.
+ */
+ private Call getForegroundCall() {
+ Call call = CallsManager.getInstance().getForegroundCall();
+
+ // We ignore any foreground call that is in the ringing state because we deal with ringing
+ // calls exclusively through the mIsRinging variable set by {@link Ringer}.
+ if (call != null && call.getState() == CallState.RINGING) {
+ call = null;
+ }
+ return call;
+ }
}
diff --git a/src/com/android/telecomm/Ringer.java b/src/com/android/telecomm/Ringer.java
index fee0a63..5b5beff 100644
--- a/src/com/android/telecomm/Ringer.java
+++ b/src/com/android/telecomm/Ringer.java
@@ -23,8 +23,7 @@
import android.provider.Settings;
import android.telecomm.CallState;
-import com.google.common.collect.Lists;
-
+import java.util.LinkedList;
import java.util.List;
/**
@@ -46,7 +45,7 @@
* Used to keep ordering of unanswered incoming calls. There can easily exist multiple incoming
* calls and explicit ordering is useful for maintaining the proper state of the ringer.
*/
- private final List<Call> mRingingCalls = Lists.newLinkedList();
+ private final List<Call> mRingingCalls = new LinkedList<>();
private final CallAudioManager mCallAudioManager;
private final CallsManager mCallsManager;
@@ -78,7 +77,7 @@
}
@Override
- public void onCallAdded(Call call) {
+ public void onCallAdded(final Call call) {
if (call.isIncoming() && call.getState() == CallState.RINGING) {
if (mRingingCalls.contains(call)) {
Log.wtf(this, "New ringing call is already in list of unanswered calls");
@@ -88,7 +87,6 @@
}
}
-
@Override
public void onCallRemoved(Call call) {
removeFromUnansweredCall(call);
@@ -180,7 +178,11 @@
// is available, then we send it a signal to do its own ringtone and we dont need
// to play the ringtone on the device.
if (!mCallAudioManager.isBluetoothDeviceAvailable()) {
- mRingtonePlayer.play();
+ // Because we wait until a contact info query to complete before processing a
+ // call (for the purposes of direct-to-voicemail), the information about custom
+ // ringtones should be available by the time this code executes. We can safely
+ // request the custom ringtone from the call and expect it to be current.
+ mRingtonePlayer.play(foregroundCall.getRingtone());
}
} else {
Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0");
diff --git a/src/com/android/telecomm/Timeouts.java b/src/com/android/telecomm/Timeouts.java
index afd6d29..d13091f 100644
--- a/src/com/android/telecomm/Timeouts.java
+++ b/src/com/android/telecomm/Timeouts.java
@@ -18,7 +18,6 @@
import android.provider.Settings;
import android.telecomm.CallServiceProvider;
-import android.telecomm.CallServiceSelector;
/**
* A helper class which serves only to make it easier to lookup timeout values. This class should