Add PSTN incoming call support.
Change looks big but a lot of it is reshuffling and very minor deletes.
Changes:
- Removes the shouldDisableUpdates code
- Disables incoming call codepath in TeleService
(see CallNotifier.java change)
- Moved the static call map from BaseTelephoneCallService into its own
class: CallRegistrar.java
- Added a class between Cdma/GsmCallService and BaseTelephonyCallService
to hold code that is shared by CDMA and GSM but not SIP. In this case,
the incoming call flow.
- Added audio-mode switching in TelephonyCallConnection. This is there
to make incoming calls work until AudioManager lands in Telecomm.
Incoming call changes:
PstnCallService.java
- setIncomingCallId() - Basically, it looks for any new incoming call
and if it finds one, it tells Telecomm, "yup, here's the incoming
call." An incoming call is considered NEW if the call hasn't already
been associated with a call ID...we check that before confirming with
Telecomm.
- answer()/reject() - In both cases, we see if the incoming call still
exists for the call ID, and if it does, we perform the appropriate
action via the Phone object.
Change-Id: I5c748870453ea74f8306bb467b114995eb728484
diff --git a/src/com/android/phone/CallModeler.java b/src/com/android/phone/CallModeler.java
index 5258f88..3e37f29 100644
--- a/src/com/android/phone/CallModeler.java
+++ b/src/com/android/phone/CallModeler.java
@@ -95,8 +95,6 @@
private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
private Connection mCdmaIncomingConnection;
private Connection mCdmaOutgoingConnection;
- // TODO(sail): Temporary flag to disable sending telephony updates when Telecomm is being used.
- private boolean mShouldDisableUpdates;
public CallModeler(CallStateMonitor callStateMonitor, CallManager callManager,
CallGatewayManager callGatewayManager) {
@@ -107,12 +105,6 @@
mCallStateMonitor.addListener(this);
}
- public void setShouldDisableUpdates(boolean shouldDisableUpdates) {
- Log.i(TAG, "setShouldDisableUpdates " + mShouldDisableUpdates + " -> " +
- shouldDisableUpdates);
- mShouldDisableUpdates = shouldDisableUpdates;
- }
-
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
@@ -279,7 +271,7 @@
final Call call = getCallFromMap(mCallMap, c, false);
if (call == null) {
Log.i(TAG, "Call no longer exists. Skipping onPostDialWait().");
- } else if (!mShouldDisableUpdates) {
+ } else {
for (Listener mListener : mListeners) {
mListener.onPostDialAction(state, call.getCallId(),
c.getRemainingPostDialString(), ch);
@@ -289,10 +281,8 @@
default:
// This is primarily to cause the DTMFTonePlayer to play local tones.
// Other listeners simply perform no-ops.
- if (!mShouldDisableUpdates) {
- for (Listener mListener : mListeners) {
- mListener.onPostDialAction(state, 0, "", ch);
- }
+ for (Listener mListener : mListeners) {
+ mListener.onPostDialAction(state, 0, "", ch);
}
break;
}
@@ -306,10 +296,8 @@
if (call != null) {
updateCallFromConnection(call, conn, false);
- if (!mShouldDisableUpdates) {
- for (int i = 0; i < mListeners.size(); ++i) {
- mListeners.get(i).onIncoming(call);
- }
+ for (int i = 0; i < mListeners.size(); ++i) {
+ mListeners.get(i).onIncoming(call);
}
}
@@ -326,10 +314,8 @@
updateCallFromConnection(call, conn, false);
- if (!mShouldDisableUpdates) {
- for (int i = 0; i < mListeners.size(); ++i) {
- mListeners.get(i).onDisconnect(call);
- }
+ for (int i = 0; i < mListeners.size(); ++i) {
+ mListeners.get(i).onDisconnect(call);
}
// If it was a conferenced call, we need to run the entire update
@@ -353,7 +339,7 @@
final List<Call> updatedCalls = Lists.newArrayList();
doUpdate(false, updatedCalls);
- if (updatedCalls.size() > 0 && !mShouldDisableUpdates) {
+ if (updatedCalls.size() > 0) {
for (int i = 0; i < mListeners.size(); ++i) {
mListeners.get(i).onUpdate(updatedCalls);
}
diff --git a/src/com/android/phone/CallStateMonitor.java b/src/com/android/phone/CallStateMonitor.java
index 3e9ff5d..b93d7e1 100644
--- a/src/com/android/phone/CallStateMonitor.java
+++ b/src/com/android/phone/CallStateMonitor.java
@@ -97,7 +97,15 @@
if (DBG) {
Log.d(LOG_TAG, "Adding Handler: " + handler);
}
- registeredHandlers.add(handler);
+
+ // Commented out so that the two listeners do not get phone events:
+ // 1) CallModeler - drives in-call UI, DTMF sessions, Bluetooth.
+ // 2) CallNotifier - Incoming-call sequence (ringer, etc.)
+ //
+ // NOTE: This can be deleted, but is left here for documentation purposes until this
+ // entire file can be deleted (once we are sure we've addressed each of the events we
+ // were previously looking for.
+ // registeredHandlers.add(handler);
}
}
diff --git a/src/com/android/services/telephony/BaseTelephonyCallService.java b/src/com/android/services/telephony/BaseTelephonyCallService.java
index 7004fed..5c5e235 100644
--- a/src/com/android/services/telephony/BaseTelephonyCallService.java
+++ b/src/com/android/services/telephony/BaseTelephonyCallService.java
@@ -27,10 +27,6 @@
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.Phone;
-import com.android.phone.PhoneGlobals;
-import com.android.phone.CallModeler;
-
-import java.util.HashMap;
/**
* The parent class for telephony-based call services. Subclasses provide the specific phone (GSM,
@@ -41,20 +37,6 @@
protected CallServiceAdapter mCallServiceAdapter;
- /** Map of all call connections keyed by the call ID. */
- private static HashMap<String, TelephonyCallConnection> sCallConnections =
- new HashMap<String, TelephonyCallConnection>();
-
- /**
- * Clears the connection from the list of connections. Called when a phone call disconnects.
- */
- static void onCallConnectionClosing(TelephonyCallConnection callConnection) {
- sCallConnections.remove(callConnection.getCallId());
- if (sCallConnections.isEmpty()) {
- PhoneGlobals.getInstance().getCallModeler().setShouldDisableUpdates(false);
- }
- }
-
/** {@inheritDoc} */
@Override
public void setCallServiceAdapter(CallServiceAdapter callServiceAdapter) {
@@ -63,34 +45,19 @@
/** {@inheritDoc} */
@Override
- public void setIncomingCallId(String callId, Bundle extras) {
- // Incoming calls not implemented yet.
- }
-
- /** {@inheritDoc} */
- @Override
public void abort(String callId) {
- if (sCallConnections.containsKey(callId)) {
- sCallConnections.get(callId).disconnect(true);
+ TelephonyCallConnection callConnection = CallRegistrar.get(callId);
+ if (callConnection != null) {
+ callConnection.disconnect(true);
}
}
/** {@inheritDoc} */
@Override
- public void answer(String callId) {
- }
-
- /** {@inheritDoc} */
- @Override
- public void reject(String callId) {
- }
-
- /** {@inheritDoc} */
- @Override
public void disconnect(String callId) {
- // Maybe null if the connection has already disconnected.
- if (sCallConnections.containsKey(callId)) {
- sCallConnections.get(callId).disconnect(false);
+ TelephonyCallConnection callConnection = CallRegistrar.get(callId);
+ if (callConnection != null) {
+ callConnection.disconnect(false);
}
}
@@ -98,8 +65,9 @@
* Initiates the call, should be called by the subclass.
*/
protected void startCallWithPhone(Phone phone, CallInfo callInfo) {
+ String callId = callInfo.getId();
if (phone == null) {
- mCallServiceAdapter.handleFailedOutgoingCall(callInfo.getId(), "Phone is null");
+ mCallServiceAdapter.handleFailedOutgoingCall(callId, "Phone is null");
return;
}
@@ -109,27 +77,23 @@
number = uri.getSchemeSpecificPart();
}
if (TextUtils.isEmpty(number)) {
- mCallServiceAdapter.handleFailedOutgoingCall(callInfo.getId(),
- "Unable to parse number");
+ mCallServiceAdapter.handleFailedOutgoingCall(callId, "Unable to parse number");
return;
}
Connection connection;
try {
- PhoneGlobals.getInstance().getCallModeler().setShouldDisableUpdates(true);
connection = phone.dial(number);
} catch (CallStateException e) {
Log.e(TAG, "Call to Phone.dial failed with exception", e);
- mCallServiceAdapter.handleFailedOutgoingCall(callInfo.getId(), e.getMessage());
- if (sCallConnections.isEmpty()) {
- PhoneGlobals.getInstance().getCallModeler().setShouldDisableUpdates(false);
- }
+ mCallServiceAdapter.handleFailedOutgoingCall(callId, e.getMessage());
return;
}
TelephonyCallConnection callConnection =
- new TelephonyCallConnection(mCallServiceAdapter, callInfo.getId(), connection);
- sCallConnections.put(callInfo.getId(), callConnection);
- mCallServiceAdapter.handleSuccessfulOutgoingCall(callInfo.getId());
+ new TelephonyCallConnection(mCallServiceAdapter, callId, connection);
+ CallRegistrar.register(callId, callConnection);
+
+ mCallServiceAdapter.handleSuccessfulOutgoingCall(callId);
}
}
diff --git a/src/com/android/services/telephony/CallRegistrar.java b/src/com/android/services/telephony/CallRegistrar.java
new file mode 100644
index 0000000..caf95d0
--- /dev/null
+++ b/src/com/android/services/telephony/CallRegistrar.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 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.services.telephony;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+
+import android.util.Log;
+
+import com.android.internal.telephony.Connection;
+
+import java.util.Collection;
+import java.util.HashMap;
+
+/**
+ * Maintains global associations between a Telecomm-supplied call ID and a
+ * {@link TelephonyCallConnection} object.
+ */
+final class CallRegistrar {
+ private static final String TAG = CallRegistrar.class.getSimpleName();
+
+ /** Map of all call connections keyed by the call ID. */
+ private static HashMap<String, TelephonyCallConnection> sCallConnections = Maps.newHashMap();
+
+ /**
+ * Registers the specified call ID with the specified call connection.
+ *
+ * @param callId The call ID from Telecomm.
+ * @param callConnection The call connection.
+ */
+ static void register(String callId, TelephonyCallConnection callConnection) {
+ Preconditions.checkNotNull(callId);
+ Preconditions.checkNotNull(callConnection);
+
+ if (sCallConnections.containsKey(callId)) {
+ Log.wtf(TAG, "Reregistering the call " + callId);
+ } else {
+ sCallConnections.put(callId, callConnection);
+ }
+ }
+
+ /**
+ * Unregisters the specified call ID.
+ *
+ * @param callId The call ID from Telecomm.
+ */
+ static void unregister(String callId) {
+ Preconditions.checkNotNull(callId);
+ sCallConnections.remove(callId);
+ }
+
+ /**
+ * Returns true if the specified connection has already been registered with a call ID.
+ *
+ * @param connection The connection to test.
+ */
+ static boolean isConnectionRegistered(Connection connection) {
+ for (TelephonyCallConnection callConnection : CallRegistrar.getCallConnections()) {
+ if (callConnection.getOriginalConnection() == connection) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static TelephonyCallConnection get(String callId) {
+ return sCallConnections.get(callId);
+ }
+
+ static boolean isEmpty() {
+ return sCallConnections.isEmpty();
+ }
+
+ /**
+ * Returns all the registered call connections as a collection.
+ */
+ static Collection<TelephonyCallConnection> getCallConnections() {
+ return sCallConnections.values();
+ }
+}
diff --git a/src/com/android/services/telephony/CdmaCallService.java b/src/com/android/services/telephony/CdmaCallService.java
index 123c71d..395c149 100644
--- a/src/com/android/services/telephony/CdmaCallService.java
+++ b/src/com/android/services/telephony/CdmaCallService.java
@@ -27,7 +27,7 @@
/**
* Call service that uses the CDMA phone.
*/
-public class CdmaCallService extends BaseTelephonyCallService {
+public class CdmaCallService extends PstnCallService {
private static final String TAG = CdmaCallService.class.getSimpleName();
static boolean shouldSelect(Context context, CallInfo callInfo) {
@@ -44,7 +44,7 @@
/** {@inheritDoc} */
@Override
- public void call(CallInfo callInfo) {
- startCallWithPhone(CachedPhoneFactory.getCdmaPhone(), callInfo);
+ protected Phone getPhone() {
+ return CachedPhoneFactory.getCdmaPhone();
}
}
diff --git a/src/com/android/services/telephony/GsmCallService.java b/src/com/android/services/telephony/GsmCallService.java
index 8ca5e96..a19a813 100644
--- a/src/com/android/services/telephony/GsmCallService.java
+++ b/src/com/android/services/telephony/GsmCallService.java
@@ -27,7 +27,7 @@
/**
* Call service that uses the GSM phone.
*/
-public class GsmCallService extends BaseTelephonyCallService {
+public class GsmCallService extends PstnCallService {
private static final String TAG = GsmCallService.class.getSimpleName();
static boolean shouldSelect(Context context, CallInfo callInfo) {
@@ -44,7 +44,7 @@
/** {@inheritDoc} */
@Override
- public void call(CallInfo callInfo) {
- startCallWithPhone(CachedPhoneFactory.getGsmPhone(), callInfo);
+ protected Phone getPhone() {
+ return CachedPhoneFactory.getGsmPhone();
}
}
diff --git a/src/com/android/services/telephony/PstnCallService.java b/src/com/android/services/telephony/PstnCallService.java
new file mode 100644
index 0000000..7ccb5bf
--- /dev/null
+++ b/src/com/android/services/telephony/PstnCallService.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2014 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.services.telephony;
+
+import android.os.Bundle;
+import android.telecomm.CallInfo;
+import android.telecomm.CallState;
+import android.util.Log;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.Phone;
+
+/**
+ * The parent class for PSTN-based call services. Handles shared functionality between all PSTN
+ * call services.
+ */
+public abstract class PstnCallService extends BaseTelephonyCallService {
+ private static final String TAG = PstnCallService.class.getSimpleName();
+ private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+
+ /** {@inheritDoc} */
+ @Override
+ public final void call(CallInfo callInfo) {
+ startCallWithPhone(getPhone(), callInfo);
+ }
+
+ /**
+ * Looks for a new incoming call and if one is found, tells Telecomm to associate the incoming
+ * call with the specified call ID.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public final void setIncomingCallId(String callId, Bundle extras) {
+ if (DBG) {
+ Log.d(TAG, "setIncomingCallId: " + callId);
+ }
+ Phone phone = getPhone();
+ Call call = getPhone().getRingingCall();
+
+ // The ringing call is always not-null, check if it is truly ringing by checking its state.
+ if (call.getState().isRinging()) {
+ Connection connection = call.getEarliestConnection();
+
+ if (CallRegistrar.isConnectionRegistered(connection)) {
+ Log.e(TAG, "Cannot set incoming call ID, ringing connection already registered.");
+ } else {
+ // Create and register a new call connection.
+ TelephonyCallConnection callConnection =
+ new TelephonyCallConnection(mCallServiceAdapter, callId, connection);
+ CallRegistrar.register(callId, callConnection);
+
+ // Notify Telecomm of the incoming call.
+ CallInfo callInfo =
+ new CallInfo(callId, CallState.RINGING, connection.getAddress());
+ mCallServiceAdapter.notifyIncomingCall(callInfo);
+ }
+ } else {
+ Log.e(TAG, "Found no ringing call, call state: " + call.getState());
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void answer(String callId) {
+ // TODO(santoscordon): Tons of hairy logic is missing here around multiple active calls on
+ // CDMA devices. See {@link CallManager.acceptCall}.
+
+ Log.i(TAG, "answer: " + callId);
+ if (isValidRingingCall(callId)) {
+ try {
+ getPhone().acceptCall();
+ } catch (CallStateException e) {
+ Log.e(TAG, "Failed to accept call " + callId, e);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void reject(String callId) {
+ Log.i(TAG, "reject: " + callId);
+ if (isValidRingingCall(callId)) {
+ try {
+ getPhone().rejectCall();
+ } catch (CallStateException e) {
+ Log.e(TAG, "Failed to reject call " + callId, e);
+ }
+ }
+ }
+
+ /**
+ * @return The current phone object behind this call service.
+ */
+ protected abstract Phone getPhone();
+
+ /**
+ * Checks to see if the specified call ID corresponds to an active incoming call. Returns false
+ * if there is no association between the specified call ID and an actual call, or if the
+ * associated call is not incoming (See {@link Call.State#isRinging}).
+ *
+ * @param callId The ID of the call.
+ */
+ private boolean isValidRingingCall(String callId) {
+ TelephonyCallConnection callConnection = CallRegistrar.get(callId);
+
+ if (callConnection == null) {
+ if (DBG) {
+ Log.d(TAG, "Unknown call ID while testing for a ringing call.");
+ }
+ } else {
+ Phone phone = getPhone();
+ Call ringingCall = phone.getRingingCall();
+
+ // The ringingCall object is always not-null so we have to check its current state.
+ if (ringingCall.getState().isRinging()) {
+ Connection connection = callConnection.getOriginalConnection();
+ if (ringingCall.getEarliestConnection() == connection) {
+ // The ringing connection is the same one for this call. We have a match!
+ return true;
+ } else {
+ Log.w(TAG, "A ringing connection exists, but it is not the same connection.");
+ }
+ } else {
+ Log.i(TAG, "There is no longer a ringing call.");
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/src/com/android/services/telephony/SipCallService.java b/src/com/android/services/telephony/SipCallService.java
index c5efe32..d0335cb 100644
--- a/src/com/android/services/telephony/SipCallService.java
+++ b/src/com/android/services/telephony/SipCallService.java
@@ -22,6 +22,7 @@
import android.net.sip.SipProfile;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Bundle;
import android.provider.Settings;
import android.telecomm.CallInfo;
import android.telephony.PhoneNumberUtils;
@@ -93,6 +94,22 @@
new GetSipProfileTask(this, callInfo).execute();
}
+ /** {@inheritDoc} */
+ @Override
+ public void setIncomingCallId(String callId, Bundle extras) {
+ // TODO(santoscordon): fill in.
+ }
+
+ /** {@inheritDoc} */
+ public void answer(String callId) {
+ // TODO(santoscordon): fill in.
+ }
+
+ /** {@inheritDoc} */
+ public void reject(String callId) {
+ // TODO(santoscordon): fill in.
+ }
+
/**
* Asynchronously looks up the SIP profile to use for the given call.
*/
diff --git a/src/com/android/services/telephony/TelephonyCallConnection.java b/src/com/android/services/telephony/TelephonyCallConnection.java
index 2689e07..01debfa 100644
--- a/src/com/android/services/telephony/TelephonyCallConnection.java
+++ b/src/com/android/services/telephony/TelephonyCallConnection.java
@@ -16,6 +16,8 @@
package com.android.services.telephony;
+import android.content.Context;
+import android.media.AudioManager;
import android.os.Handler;
import android.os.Message;
import android.telecomm.CallServiceAdapter;
@@ -24,6 +26,7 @@
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
+import com.android.phone.PhoneGlobals;
/**
* Manages a single phone call. Listens to the call's state changes and updates the
@@ -38,15 +41,15 @@
private CallServiceAdapter mCallServiceAdapter;
- private Connection mConnection;
- private Call.State mOldState = Call.State.IDLE;
+ private Connection mOriginalConnection;
+ private Call.State mState = Call.State.IDLE;
TelephonyCallConnection(CallServiceAdapter callServiceAdapter, String callId,
Connection connection) {
mCallServiceAdapter = callServiceAdapter;
mCallId = callId;
- mConnection = connection;
- mConnection.getCall().getPhone().registerForPreciseCallStateChanged(mHandler,
+ mOriginalConnection = connection;
+ mOriginalConnection.getCall().getPhone().registerForPreciseCallStateChanged(mHandler,
EVENT_PRECISE_CALL_STATE_CHANGED, null);
updateState();
}
@@ -55,13 +58,18 @@
return mCallId;
}
+ Connection getOriginalConnection() {
+ return mOriginalConnection;
+ }
+
void disconnect(boolean shouldAbort) {
if (shouldAbort) {
mCallServiceAdapter = null;
+ close();
}
- if (mConnection != null) {
+ if (mOriginalConnection != null) {
try {
- mConnection.hangup();
+ mOriginalConnection.hangup();
} catch (CallStateException e) {
Log.e(TAG, "Call to Connection.hangup failed with exception", e);
}
@@ -69,16 +77,16 @@
}
private void updateState() {
- if (mConnection == null || mCallServiceAdapter == null) {
+ if (mOriginalConnection == null || mCallServiceAdapter == null) {
return;
}
- Call.State newState = mConnection.getState();
- if (mOldState == newState) {
+ Call.State newState = mOriginalConnection.getState();
+ if (mState == newState) {
return;
}
- mOldState = newState;
+ mState = newState;
switch (newState) {
case IDLE:
break;
@@ -88,15 +96,12 @@
case HOLDING:
break;
case DIALING:
- mCallServiceAdapter.setDialing(mCallId);
- break;
case ALERTING:
mCallServiceAdapter.setDialing(mCallId);
break;
case INCOMING:
- // Incoming calls not implemented.
- break;
case WAITING:
+ mCallServiceAdapter.setRinging(mCallId);
break;
case DISCONNECTED:
mCallServiceAdapter.setDisconnected(mCallId);
@@ -105,17 +110,49 @@
case DISCONNECTING:
break;
}
+
+ setAudioMode(Call.State.ACTIVE);
}
private void close() {
- if (mConnection != null) {
- Call call = mConnection.getCall();
+ if (mOriginalConnection != null) {
+ Call call = mOriginalConnection.getCall();
if (call != null) {
call.getPhone().unregisterForPreciseCallStateChanged(mHandler);
}
- mConnection = null;
+ mOriginalConnection = null;
}
- BaseTelephonyCallService.onCallConnectionClosing(this);
+ CallRegistrar.unregister(mCallId);
+ }
+
+ /**
+ * Sets the audio mode according to the specified state of the call.
+ * TODO(santoscordon): This will not be necessary once Telecomm manages audio focus. This does
+ * not handle multiple calls well, specifically when there are multiple active call services
+ * within services/Telephony.
+ *
+ * @param state The state of the call.
+ */
+ private static void setAudioMode(Call.State state) {
+ Context context = PhoneGlobals.getInstance();
+ AudioManager audioManager =
+ (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+
+ if (Call.State.ACTIVE == state) {
+ // Set the IN_CALL mode only when the call is active.
+ if (audioManager.getMode() != AudioManager.MODE_IN_CALL) {
+ audioManager.requestAudioFocusForCall(
+ AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ audioManager.setMode(AudioManager.MODE_IN_CALL);
+ }
+ } else {
+ // Non active calls go back to normal mode. This breaks down if there are multiple calls
+ // due to non-deterministic execution order across call services. But that will be fixed
+ // as soon as this moves to Telecomm where it is aware of all active calls.
+ if (audioManager.getMode() != AudioManager.MODE_NORMAL) {
+ audioManager.abandonAudioFocusForCall();
+ }
+ }
}
private class StateHandler extends Handler {
diff --git a/src/com/android/services/telephony/TelephonyGlobals.java b/src/com/android/services/telephony/TelephonyGlobals.java
index 722a880..3333784 100644
--- a/src/com/android/services/telephony/TelephonyGlobals.java
+++ b/src/com/android/services/telephony/TelephonyGlobals.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.telephony.TelephonyManager;
+import android.util.Log;
import com.android.internal.telephony.PhoneFactory;
@@ -31,6 +32,7 @@
* {@link #onCreate}.
*/
public class TelephonyGlobals {
+ private static final String TAG = TelephonyGlobals.class.getSimpleName();
/** The application context. */
private final Context mContext;
@@ -69,10 +71,12 @@
int phoneType = telephonyManager.getPhoneType();
if (TelephonyManager.PHONE_TYPE_GSM == phoneType) {
+ Log.d(TAG, "Phone type GSM found");
mGsmIncomingCallNotifier = new IncomingCallNotifier(
GsmCallService.class, CachedPhoneFactory.getGsmPhone());
} else if (TelephonyManager.PHONE_TYPE_CDMA == phoneType) {
+ Log.d(TAG, "Phone type CDMA found");
mCdmaIncomingCallNotifier = new IncomingCallNotifier(
CdmaCallService.class, CachedPhoneFactory.getCdmaPhone());
}