Merge "Update Telecom test app to support bluetooth for self-managed calls."
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index dbe0137..d379444 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -1440,6 +1440,7 @@
if ((mConnectionProperties & Connection.PROPERTY_IS_RTT) ==
Connection.PROPERTY_IS_RTT) {
createRttStreams();
+ mWasEverRtt = true;
if (isEmergencyCall()) {
mCallsManager.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null);
mCallsManager.mute(false);
@@ -2582,7 +2583,6 @@
if (!areRttStreamsInitialized()) {
Log.i(this, "Initializing RTT streams");
try {
- mWasEverRtt = true;
mInCallToConnectionServiceStreams = ParcelFileDescriptor.createReliablePipe();
mConnectionServiceToInCallStreams = ParcelFileDescriptor.createReliablePipe();
} catch (IOException e) {
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index b5c7e7a..297414b 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -29,6 +29,12 @@
import com.android.internal.util.StateMachine;
public class CallAudioModeStateMachine extends StateMachine {
+ public static class Factory {
+ public CallAudioModeStateMachine create(AudioManager am) {
+ return new CallAudioModeStateMachine(am);
+ }
+ }
+
public static class MessageArgs {
public boolean hasActiveOrDialingCalls;
public boolean hasRingingCalls;
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index fba17ae..a43f9aa 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -72,6 +72,24 @@
*/
public class CallAudioRouteStateMachine extends StateMachine {
+ public static class Factory {
+ public CallAudioRouteStateMachine create(
+ Context context,
+ CallsManager callsManager,
+ BluetoothRouteManager bluetoothManager,
+ WiredHeadsetManager wiredHeadsetManager,
+ StatusBarNotifier statusBarNotifier,
+ CallAudioManager.AudioServiceFactory audioServiceFactory,
+ int earpieceControl) {
+ return new CallAudioRouteStateMachine(context,
+ callsManager,
+ bluetoothManager,
+ wiredHeadsetManager,
+ statusBarNotifier,
+ audioServiceFactory,
+ earpieceControl);
+ }
+ }
/** Values for CallAudioRouteStateMachine constructor's earPieceRouting arg. */
public static final int EARPIECE_FORCE_DISABLED = 0;
public static final int EARPIECE_FORCE_ENABLED = 1;
diff --git a/src/com/android/server/telecom/CallerInfoLookupHelper.java b/src/com/android/server/telecom/CallerInfoLookupHelper.java
index f67a7f7..2dde241 100644
--- a/src/com/android/server/telecom/CallerInfoLookupHelper.java
+++ b/src/com/android/server/telecom/CallerInfoLookupHelper.java
@@ -117,7 +117,7 @@
}
}
- mHandler.post(new Runnable("CILH.sL", mLock) {
+ mHandler.post(new Runnable("CILH.sL", null) {
@Override
public void loggedRun() {
Session continuedSession = Log.createSubsession();
@@ -171,7 +171,7 @@
}
private void startPhotoLookup(final Uri handle, final Uri contactPhotoUri) {
- mHandler.post(new Runnable("CILH.sPL", mLock) {
+ mHandler.post(new Runnable("CILH.sPL", null) {
@Override
public void loggedRun() {
Session continuedSession = Log.createSubsession();
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 0f37fe4..9e7677b 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -17,12 +17,14 @@
package com.android.server.telecom;
import android.app.ActivityManager;
+import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.pm.UserInfo;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
+import android.media.AudioSystem;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -363,6 +365,8 @@
InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
ClockProxy clockProxy,
BluetoothStateReceiver bluetoothStateReceiver,
+ CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
+ CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
InCallControllerFactory inCallControllerFactory) {
mContext = context;
mLock = lock;
@@ -384,15 +388,16 @@
mDtmfLocalTonePlayer =
new DtmfLocalTonePlayer(new DtmfLocalTonePlayer.ToneGeneratorProxy());
- CallAudioRouteStateMachine callAudioRouteStateMachine = new CallAudioRouteStateMachine(
- context,
- this,
- bluetoothManager,
- wiredHeadsetManager,
- statusBarNotifier,
- audioServiceFactory,
- CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT
- );
+ CallAudioRouteStateMachine callAudioRouteStateMachine =
+ callAudioRouteStateMachineFactory.create(
+ context,
+ this,
+ bluetoothManager,
+ wiredHeadsetManager,
+ statusBarNotifier,
+ audioServiceFactory,
+ CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT
+ );
callAudioRouteStateMachine.initialize();
CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter =
@@ -416,13 +421,12 @@
mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext,
(AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE), mLock);
mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine,
- this,new CallAudioModeStateMachine((AudioManager)
+ this, callAudioModeStateMachineFactory.create((AudioManager)
mContext.getSystemService(Context.AUDIO_SERVICE)),
playerFactory, mRinger, new RingbackPlayer(playerFactory),
bluetoothStateReceiver, mDtmfLocalTonePlayer);
- mConnectionSvrFocusMgr = connectionServiceFocusManagerFactory.create(
- mRequester, Looper.getMainLooper());
+ mConnectionSvrFocusMgr = connectionServiceFocusManagerFactory.create(mRequester);
mHeadsetMediaButton = headsetMediaButtonFactory.create(context, this, mLock);
mTtyManager = new TtyManager(context, mWiredHeadsetManager);
mProximitySensorManager = proximitySensorManagerFactory.create(context, this);
@@ -516,20 +520,6 @@
return;
}
- // Check DISALLOW_OUTGOING_CALLS restriction.
- // Only ecbm calls are allowed through when users with the DISALLOW_OUTGOING_CALLS
- // restriction are the current user.
- final UserManager userManager = (UserManager) mContext.getSystemService(
- Context.USER_SERVICE);
- if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
- mCurrentUserHandle)) {
- Log.w(this, "Rejecting non-ecbm phone call due to DISALLOW_INCOMING_CALLS "
- + "restriction");
- incomingCall.reject(false, null);
- mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE, false /* showNotification */);
- return;
- }
-
List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(),
@@ -1480,21 +1470,7 @@
// Hold or disconnect the active call and request call focus for the incoming call.
Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
Log.d(this, "Incoming call = %s Ongoing call %s", call, activeCall);
- if (activeCall != null && activeCall != call) {
- // Hold the telephony call even if it doesn't have the hold capability.
- if (canHold(activeCall)) {
- Log.d(this, "Answer %s, hold %s", call, activeCall);
- activeCall.hold();
- } else {
- // This call does not support hold. If it is from a different connection
- // service, then disconnect it, otherwise allow the connection service to
- // figure out the right states.
- if (activeCall.getConnectionService() != call.getConnectionService()) {
- activeCall.disconnect("Can't hold when answering " + call.getId());
- }
- }
- }
-
+ holdActiveCallForNewCall(call);
mConnectionSvrFocusMgr.requestFocus(
call,
new RequestCallback(new ActionAnswerCall(call, videoState)));
@@ -1841,8 +1817,8 @@
}
private boolean isRttSettingOn() {
- return Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.RTT_CALLING_MODE, 0) != 0;
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.RTT_CALLING_MODE, 0) != 0;
}
void phoneAccountSelected(Call call, PhoneAccountHandle account, boolean setDefault) {
@@ -1923,6 +1899,7 @@
setCallState(call, CallState.DIALING, "dialing set explicitly");
maybeMoveToSpeakerPhone(call);
maybeTurnOffMute(call);
+ ensureCallAudible();
}
void markCallAsPulling(Call call) {
@@ -1930,11 +1907,43 @@
maybeMoveToSpeakerPhone(call);
}
- void markCallAsActive(Call call) {
+ /**
+ * Returns true if the active call is held.
+ */
+ boolean holdActiveCallForNewCall(Call call) {
+ Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
+ if (activeCall != null && activeCall != call) {
+ if (canHold(activeCall)) {
+ activeCall.hold();
+ return true;
+ } else if (supportsHold(call)) {
+ Call heldCall = getHeldCallByConnectionService(call.getConnectionService());
+ if (heldCall != null) {
+ heldCall.disconnect();
+ Log.i(this, "Disconnecting held call %s before holding active call.", heldCall);
+ }
+ activeCall.hold();
+ return true;
+ } else {
+ // This call does not support hold. If it is from a different connection
+ // service, then disconnect it, otherwise allow the connection service to
+ // figure out the right states.
+ if (activeCall.getConnectionService() != call.getConnectionService()) {
+ activeCall.disconnect();
+ }
+ }
+ }
+ return false;
+ }
+
+ @VisibleForTesting
+ public void markCallAsActive(Call call) {
if (call.isSelfManaged()) {
// backward compatibility, the self-managed connection service will set the call state
- // to active directly. We should request the call focus for self-managed call before
- // the state change
+ // to active directly. We should hold or disconnect the current active call based on the
+ // holdability, and request the call focus for the self-managed call before the state
+ // change.
+ holdActiveCallForNewCall(call);
mConnectionSvrFocusMgr.requestFocus(
call,
new RequestCallback(new ActionSetCallState(
@@ -1944,6 +1953,7 @@
} else {
setCallState(call, CallState.ACTIVE, "active set explicitly");
maybeMoveToSpeakerPhone(call);
+ ensureCallAudible();
}
}
@@ -2166,6 +2176,14 @@
return getFirstCallWithState(CallState.ON_HOLD);
}
+ public Call getHeldCallByConnectionService(ConnectionServiceWrapper connSvr) {
+ Optional<Call> heldCall = mCalls.stream()
+ .filter(call -> call.getConnectionService() == connSvr
+ && call.getState() == CallState.ON_HOLD)
+ .findFirst();
+ return heldCall.isPresent() ? heldCall.get() : null;
+ }
+
@VisibleForTesting
public int getNumHeldCalls() {
int count = 0;
@@ -2932,6 +2950,19 @@
}
}
+ private void ensureCallAudible() {
+ AudioManager am = mContext.getSystemService(AudioManager.class);
+ if (am == null) {
+ Log.w(this, "ensureCallAudible: audio manager is null");
+ return;
+ }
+ if (am.getStreamVolume(AudioManager.STREAM_VOICE_CALL) == 0) {
+ Log.i(this, "ensureCallAudible: voice call stream has volume 0. Adjusting to default.");
+ am.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
+ AudioSystem.getDefaultStreamVolume(AudioManager.STREAM_VOICE_CALL), 0);
+ }
+ }
+
/**
* Creates a new call for an existing connection.
*
@@ -3144,6 +3175,21 @@
}
}
+ public boolean isReplyWithSmsAllowed(int uid) {
+ UserHandle callingUser = UserHandle.of(UserHandle.getUserId(uid));
+ UserManager userManager = mContext.getSystemService(UserManager.class);
+ KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
+
+ boolean isUserRestricted = userManager != null
+ && userManager.hasUserRestriction(UserManager.DISALLOW_SMS, callingUser);
+ boolean isLockscreenRestricted = keyguardManager != null
+ && keyguardManager.isDeviceLocked();
+ Log.d(this, "isReplyWithSmsAllowed: isUserRestricted: %s, isLockscreenRestricted: %s",
+ isUserRestricted, isLockscreenRestricted);
+
+ // TODO(hallliu): actually check the lockscreen once b/77731473 is fixed
+ return !isUserRestricted;
+ }
/**
* Blocks execution until all Telecom handlers have completed their current work.
*/
@@ -3749,7 +3795,7 @@
call.startCreateConnection(mPhoneAccountRegistrar);
}
- ConnectionServiceFocusManager getConnectionServiceFocusManager() {
+ public ConnectionServiceFocusManager getConnectionServiceFocusManager() {
return mConnectionSvrFocusMgr;
}
@@ -3757,6 +3803,10 @@
return call.can(Connection.CAPABILITY_HOLD);
}
+ private boolean supportsHold(Call call) {
+ return call.can(Connection.CAPABILITY_SUPPORT_HOLD);
+ }
+
private final class ActionSetCallState implements PendingAction {
private final Call mCall;
diff --git a/src/com/android/server/telecom/ConnectionServiceFocusManager.java b/src/com/android/server/telecom/ConnectionServiceFocusManager.java
index 4bcc1ae..ede0ef6 100644
--- a/src/com/android/server/telecom/ConnectionServiceFocusManager.java
+++ b/src/com/android/server/telecom/ConnectionServiceFocusManager.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.telecom.Log;
@@ -30,14 +31,19 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class ConnectionServiceFocusManager {
private static final String TAG = "ConnectionSvrFocusMgr";
+ private static final int GET_CURRENT_FOCUS_TIMEOUT_MILLIS = 1000;
/** Factory interface used to create the {@link ConnectionServiceFocusManager} instance. */
public interface ConnectionServiceFocusManagerFactory {
- ConnectionServiceFocusManager create(CallsManagerRequester requester, Looper looper);
+ ConnectionServiceFocusManager create(CallsManagerRequester requester);
}
/**
@@ -271,10 +277,12 @@
private FocusManagerHandler mEventHandler;
public ConnectionServiceFocusManager(
- CallsManagerRequester callsManagerRequester, Looper looper) {
+ CallsManagerRequester callsManagerRequester) {
mCallsManagerRequester = callsManagerRequester;
mCallsManagerRequester.setCallsManagerListener(mCallsManagerListener);
- mEventHandler = new FocusManagerHandler(looper);
+ HandlerThread handlerThread = new HandlerThread(TAG);
+ handlerThread.start();
+ mEventHandler = new FocusManagerHandler(handlerThread.getLooper());
mCalls = new ArrayList<>();
}
@@ -298,8 +306,32 @@
* call is the current connection service focus. Also the state of the focus call must be one
* of {@link #PRIORITY_FOCUS_CALL_STATE}.
*/
- public CallFocus getCurrentFocusCall() {
- return mCurrentFocusCall;
+ public @Nullable CallFocus getCurrentFocusCall() {
+ if (mEventHandler.getLooper().isCurrentThread()) {
+ // return synchronously if we're on the same thread.
+ return mCurrentFocusCall;
+ }
+ final BlockingQueue<Optional<CallFocus>> currentFocusedCallQueue =
+ new LinkedBlockingQueue<>(1);
+ mEventHandler.post(() -> {
+ currentFocusedCallQueue.offer(
+ mCurrentFocusCall == null ? Optional.empty() : Optional.of(mCurrentFocusCall));
+ });
+ try {
+ Optional<CallFocus> syncCallFocus = currentFocusedCallQueue.poll(
+ GET_CURRENT_FOCUS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ if (syncCallFocus != null) {
+ return syncCallFocus.orElse(null);
+ } else {
+ Log.w(TAG, "Timed out waiting for synchronous current focus. Returning possibly"
+ + " inaccurate result");
+ return mCurrentFocusCall;
+ }
+ } catch (InterruptedException e) {
+ Log.w(TAG, "Interrupted when waiting for synchronous current focus."
+ + " Returning possibly inaccurate result.");
+ return mCurrentFocusCall;
+ }
}
/** Returns the current connection service focus. */
diff --git a/src/com/android/server/telecom/InCallAdapter.java b/src/com/android/server/telecom/InCallAdapter.java
index 02692c5..f3afc9a 100644
--- a/src/com/android/server/telecom/InCallAdapter.java
+++ b/src/com/android/server/telecom/InCallAdapter.java
@@ -16,12 +16,9 @@
package com.android.server.telecom;
-import android.content.Context;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;
@@ -35,16 +32,14 @@
* binding to it. This adapter can receive commands and updates until the in-call app is unbound.
*/
class InCallAdapter extends IInCallAdapter.Stub {
- private final Context mContext;
private final CallsManager mCallsManager;
private final CallIdMapper mCallIdMapper;
private final TelecomSystem.SyncRoot mLock;
private final String mOwnerComponentName;
/** Persists the specified parameters. */
- public InCallAdapter(Context context, CallsManager callsManager, CallIdMapper callIdMapper,
+ public InCallAdapter(CallsManager callsManager, CallIdMapper callIdMapper,
TelecomSystem.SyncRoot lock, String ownerComponentName) {
- mContext = context;
mCallsManager = callsManager;
mCallIdMapper = callIdMapper;
mLock = lock;
@@ -101,17 +96,12 @@
public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) {
try {
Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerComponentName);
- UserHandle callingUser = UserHandle.of(UserHandle.getUserId(Binder.getCallingUid()));
- UserManager userManager = mContext.getSystemService(UserManager.class);
-
// Check to make sure the in-call app's user isn't restricted from sending SMS. If so,
- // silently drop the outgoing message.
- if (rejectWithMessage && userManager.hasUserRestriction(
- UserManager.DISALLOW_SMS, callingUser)) {
+ // silently drop the outgoing message. Also drop message if the screen is locked.
+ if (!mCallsManager.isReplyWithSmsAllowed(Binder.getCallingUid())) {
rejectWithMessage = false;
textMessage = null;
}
-
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 7aaa770..9d20d4a 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -1309,7 +1309,6 @@
try {
inCallService.setInCallAdapter(
new InCallAdapter(
- mContext,
mCallsManager,
mCallIdMapper,
mLock,
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index d84fca5..d9398e5 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -135,7 +135,7 @@
CharSequence getAppLabel(String packageName);
}
- private static final String FILE_NAME = "phone-account-registrar-state.xml";
+ public static final String FILE_NAME = "phone-account-registrar-state.xml";
@VisibleForTesting
public static final int EXPECTED_STATE_VERSION = 9;
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 9ecdde2..bb7f3fb 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -195,6 +195,7 @@
PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
IncomingCallNotifier incomingCallNotifier,
InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
+ CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
ClockProxy clockProxy) {
mContext = context.getApplicationContext();
LogUtils.initLogging(mContext);
@@ -229,7 +230,7 @@
}
});
BluetoothDeviceManager bluetoothDeviceManager = new BluetoothDeviceManager(mContext,
- new BluetoothAdapterProxy(), mLock);
+ new BluetoothAdapterProxy());
BluetoothRouteManager bluetoothRouteManager = new BluetoothRouteManager(mContext, mLock,
bluetoothDeviceManager, new Timeouts.Adapter());
BluetoothStateReceiver bluetoothStateReceiver = new BluetoothStateReceiver(
@@ -279,6 +280,8 @@
toneGeneratorFactory,
clockProxy,
bluetoothStateReceiver,
+ callAudioRouteStateMachineFactory,
+ new CallAudioModeStateMachine.Factory(),
inCallControllerFactory);
mIncomingCallNotifier = incomingCallNotifier;
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index ff81b4d..2f42fe6 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -82,14 +82,14 @@
private final LinkedHashMap<String, BluetoothDevice> mConnectedDevicesByAddress =
new LinkedHashMap<>();
- private final TelecomSystem.SyncRoot mLock;
+
+ // This lock only protects internal state -- it doesn't lock on anything going into Telecom.
+ private final Object mLock = new Object();
private BluetoothRouteManager mBluetoothRouteManager;
private BluetoothHeadsetProxy mBluetoothHeadsetService;
- public BluetoothDeviceManager(Context context, BluetoothAdapterProxy bluetoothAdapter,
- TelecomSystem.SyncRoot lock) {
- mLock = lock;
+ public BluetoothDeviceManager(Context context, BluetoothAdapterProxy bluetoothAdapter) {
if (bluetoothAdapter != null) {
bluetoothAdapter.getProfileProxy(context, mBluetoothProfileServiceListener,
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index a1c70fa..dbae50d 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -33,6 +33,7 @@
import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.BluetoothAdapterProxy;
import com.android.server.telecom.BluetoothPhoneServiceImpl;
+import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.CallerInfoAsyncQueryFactory;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.ClockProxy;
@@ -163,20 +164,13 @@
phoneAccountRegistrar);
}
},
- new ConnectionServiceFocusManager
- .ConnectionServiceFocusManagerFactory() {
- @Override
- public ConnectionServiceFocusManager create(
- ConnectionServiceFocusManager.CallsManagerRequester requester,
- Looper looper) {
- return new ConnectionServiceFocusManager(requester, looper);
- }
- },
+ ConnectionServiceFocusManager::new,
new Timeouts.Adapter(),
new AsyncRingtonePlayer(),
new PhoneNumberUtilsAdapterImpl(),
new IncomingCallNotifier(context),
ToneGenerator::new,
+ new CallAudioRouteStateMachine.Factory(),
new ClockProxy() {
@Override
public long currentTimeMillis() {
diff --git a/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java b/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
index 9b2b3fb..4d548a1 100644
--- a/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
@@ -49,7 +49,6 @@
@RunWith(JUnit4.class)
public class AsyncBlockCheckFilterTest extends TelecomTestCase {
- @Mock private Context mContext;
@Mock private BlockCheckerAdapter mBlockCheckerAdapter;
@Mock private Call mCall;
@Mock private CallFilterResultCallback mCallback;
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index e304d34..9240199 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -20,11 +20,13 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
@@ -548,8 +550,10 @@
// TODO: We have to use the same PhoneAccount for both; see http://b/18461539
IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
verify(mConnectionServiceFixtureA.getTestDouble())
.hold(eq(outgoing.mConnectionId), any());
mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
@@ -585,10 +589,15 @@
.setMicrophoneMute(eq(false), any(String.class), any(Integer.class));
mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null);
+ waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
+ .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
verify(audioManager, timeout(TEST_TIMEOUT))
.setSpeakerphoneOn(true);
mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE, null);
- verify(audioManager, timeout(TEST_TIMEOUT))
+ waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
+ .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
+ // setSpeakerPhoneOn(false) gets called once during the call initiation phase
+ verify(audioManager, timeout(TEST_TIMEOUT).atLeast(2))
.setSpeakerphoneOn(false);
mConnectionServiceFixtureA.
@@ -784,7 +793,7 @@
anyString(),
eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER),
eq(phoneNumber),
- isNull(Bundle.class))).thenAnswer(answer);
+ nullable(Bundle.class))).thenAnswer(answer);
}
private void verifyNoBlockChecks() {
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index 4a48f1b..157d11a 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -68,8 +68,7 @@
device3 = makeBluetoothDevice("00:00:00:00:00:03");
mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
- mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapterProxy,
- new TelecomSystem.SyncRoot() { });
+ mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapterProxy);
mBluetoothDeviceManager.setBluetoothRouteManager(mRouteManager);
ArgumentCaptor<BluetoothProfile.ServiceListener> serviceCaptor =
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 6bba7af..3fc3824 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -23,8 +23,6 @@
import static org.mockito.ArgumentMatchers.anyChar;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
@@ -45,6 +43,8 @@
import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.CallAudioModeStateMachine;
+import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.CallState;
import com.android.server.telecom.CallerInfoAsyncQueryFactory;
import com.android.server.telecom.CallsManager;
@@ -141,6 +141,10 @@
@Mock private InCallControllerFactory mInCallControllerFactory;
@Mock private InCallController mInCallController;
@Mock private ConnectionServiceFocusManager mConnectionSvrFocusMgr;
+ @Mock private CallAudioRouteStateMachine mCallAudioRouteStateMachine;
+ @Mock private CallAudioRouteStateMachine.Factory mCallAudioRouteStateMachineFactory;
+ @Mock private CallAudioModeStateMachine mCallAudioModeStateMachine;
+ @Mock private CallAudioModeStateMachine.Factory mCallAudioModeStateMachineFactory;
@Mock private BluetoothStateReceiver mBluetoothStateReceiver;
private CallsManager mCallsManager;
@@ -158,9 +162,13 @@
mProximitySensorManager);
when(mInCallControllerFactory.create(any(), any(), any(), any(), any(), any(),
any())).thenReturn(mInCallController);
+ when(mCallAudioRouteStateMachineFactory.create(any(), any(), any(), any(), any(), any(),
+ anyInt())).thenReturn(mCallAudioRouteStateMachine);
+ when(mCallAudioModeStateMachineFactory.create(any()))
+ .thenReturn(mCallAudioModeStateMachine);
when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis());
when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
- when(mConnSvrFocusManagerFactory.create(any(), any())).thenReturn(mConnectionSvrFocusMgr);
+ when(mConnSvrFocusManagerFactory.create(any())).thenReturn(mConnectionSvrFocusMgr);
mCallsManager = new CallsManager(
mComponentContextFixture.getTestDouble().getApplicationContext(),
mLock,
@@ -184,6 +192,8 @@
mToneGeneratorFactory,
mClockProxy,
mBluetoothStateReceiver,
+ mCallAudioRouteStateMachineFactory,
+ mCallAudioModeStateMachineFactory,
mInCallControllerFactory);
when(mPhoneAccountRegistrar.getPhoneAccount(
@@ -421,6 +431,7 @@
// GIVEN a CallsManager with ongoing call, and this call can be held
Call ongoingCall = addSpyCall();
doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
// and a held call
@@ -430,11 +441,11 @@
mCallsManager.unholdCall(heldCall);
// THEN the ongoing call is held, and the focus request for incoming call is sent
- verify(ongoingCall).hold();
+ verify(ongoingCall).hold(any());
verifyFocusRequestAndExecuteCallback(heldCall);
// and held call is unhold now
- verify(heldCall).unhold();
+ verify(heldCall).unhold(any());
}
@SmallTest
@@ -446,6 +457,7 @@
// GIVEN a CallsManager with ongoing call, and this call can not be held
Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
// and a held call which has different ConnectionService
@@ -455,13 +467,14 @@
mCallsManager.unholdCall(heldCall);
// THEN the ongoing call is disconnected, and the focus request for incoming call is sent
- verify(ongoingCall).disconnect();
+ verify(ongoingCall).disconnect(any());
verifyFocusRequestAndExecuteCallback(heldCall);
// and held call is unhold now
- verify(heldCall).unhold();
+ verify(heldCall).unhold(any());
}
+ @SmallTest
@Test
public void testUnholdCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
@@ -469,6 +482,7 @@
// GIVEN a CallsManager with ongoing call, and this call can not be held
Call ongoingCall = addSpyCallWithConnectionService(connSvr);
doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
// and a held call which has different ConnectionService
@@ -478,11 +492,11 @@
mCallsManager.unholdCall(heldCall);
// THEN the ongoing call is held
- verify(ongoingCall).hold();
+ verify(ongoingCall).hold(any());
verifyFocusRequestAndExecuteCallback(heldCall);
// and held call is unhold now
- verify(heldCall).unhold();
+ verify(heldCall).unhold(any());
}
@SmallTest
@@ -491,6 +505,7 @@
// GIVEN a CallsManager with ongoing call, and this call can be held
Call ongoingCall = addSpyCall();
doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
// WHEN answer an incoming call
@@ -528,13 +543,14 @@
@SmallTest
@Test
- public void testANswerCallWhenOngoingHasDifferentConnectionService() {
+ public void testAnswerCallWhenOngoingHasDifferentConnectionService() {
ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
// GIVEN a CallsManager with ongoing call, and this call can not be held
Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
// WHEN answer an incoming call
@@ -551,6 +567,48 @@
@SmallTest
@Test
+ public void testAnswerCallWhenMultipleHeldCallsExisted() {
+ ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
+ ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
+
+ // Given an ongoing call and held call with the ConnectionService connSvr1. The
+ // ConnectionService connSvr1 can handle one held call
+ Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
+ doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+ doReturn(CallState.ACTIVE).when(ongoingCall).getState();
+ when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
+
+ Call heldCall = addSpyCallWithConnectionService(connSvr1);
+ doReturn(CallState.ON_HOLD).when(heldCall).getState();
+
+ // and other held call has difference ConnectionService
+ Call heldCall2 = addSpyCallWithConnectionService(connSvr2);
+ doReturn(CallState.ON_HOLD).when(heldCall2).getState();
+
+ // WHEN answer an incoming call which ConnectionService is connSvr1
+ Call incomingCall = addSpyCallWithConnectionService(connSvr1);
+ doReturn(true).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+ mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
+
+ // THEN the previous held call is disconnected
+ verify(heldCall).disconnect();
+
+ // and the ongoing call is held
+ verify(ongoingCall).hold();
+
+ // and the heldCall2 is not disconnected
+ verify(heldCall2, never()).disconnect();
+
+ // and the focus request is sent
+ verifyFocusRequestAndExecuteCallback(incomingCall);
+
+ // and the incoming call is answered
+ verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
+ }
+
+ @SmallTest
+ @Test
public void testAnswerCallWhenNoOngoingCallExisted() {
// GIVEN a CallsManager with no ongoing call.
@@ -565,6 +623,83 @@
verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
}
+ @SmallTest
+ @Test
+ public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
+ ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
+ ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
+
+ // GIVEN a CallsManager with ongoing call, and this call can not be held
+ Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
+ doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+ doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();
+
+ // and a new self-managed call which has different ConnectionService
+ Call newCall = addSpyCallWithConnectionService(connSvr2);
+ doReturn(true).when(newCall).isSelfManaged();
+
+ // WHEN active the new call
+ mCallsManager.markCallAsActive(newCall);
+
+ // THEN the ongoing call is disconnected, and the focus request for the new call is sent
+ verify(ongoingCall).disconnect();
+ verifyFocusRequestAndExecuteCallback(newCall);
+
+ // and the new call is active
+ assertEquals(CallState.ACTIVE, newCall.getState());
+ }
+
+ @SmallTest
+ @Test
+ public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
+ ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
+
+ // GIVEN a CallsManager with ongoing call, and this call can not be held
+ Call ongoingCall = addSpyCallWithConnectionService(connSvr);
+ doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+ when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
+
+ // and a new self-managed call which has the same ConnectionService
+ Call newCall = addSpyCallWithConnectionService(connSvr);
+ doReturn(true).when(newCall).isSelfManaged();
+
+ // WHEN active the new call
+ mCallsManager.markCallAsActive(newCall);
+
+ // THEN the ongoing call isn't disconnected
+ verify(ongoingCall, never()).disconnect();
+ verifyFocusRequestAndExecuteCallback(newCall);
+
+ // and the new call is active
+ assertEquals(CallState.ACTIVE, newCall.getState());
+ }
+
+ @SmallTest
+ @Test
+ public void testSetActiveCallWhenOngoingCallCanBeHeld() {
+ // GIVEN a CallsManager with ongoing call, and this call can be held
+ Call ongoingCall = addSpyCall();
+ doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
+ doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
+ doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();
+
+ // and a new self-managed call
+ Call newCall = addSpyCall();
+ doReturn(true).when(newCall).isSelfManaged();
+
+ // WHEN active the new call
+ mCallsManager.markCallAsActive(newCall);
+
+ // THEN the ongoing call is held
+ verify(ongoingCall).hold();
+ verifyFocusRequestAndExecuteCallback(newCall);
+
+ // and the new call is active
+ assertEquals(CallState.ACTIVE, newCall.getState());
+ }
+
private Call addSpyCallWithConnectionService(ConnectionServiceWrapper connSvr) {
Call call = addSpyCall();
doReturn(connSvr).when(call).getConnectionService();
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index 9cc2b87..704bcd5 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -190,6 +190,8 @@
public String getSystemServiceName(Class<?> svcClass) {
if (svcClass == UserManager.class) {
return Context.USER_SERVICE;
+ } else if (svcClass == AudioManager.class) {
+ return Context.AUDIO_SERVICE;
}
throw new UnsupportedOperationException();
}
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 3154b7d..6c4e2e0 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -286,7 +286,9 @@
@Override
public void rejectWithMessage(String callId, String message,
- Session.Info info) throws RemoteException { }
+ Session.Info info) throws RemoteException {
+ rejectedCallIds.add(callId);
+ }
@Override
public void disconnect(String callId, Session.Info info) throws RemoteException { }
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFocusManagerTest.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFocusManagerTest.java
index 3c2cc61..77a9c0d 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFocusManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFocusManagerTest.java
@@ -16,7 +16,6 @@
package com.android.server.telecom.tests;
-import android.os.Looper;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallState;
@@ -63,8 +62,7 @@
@Before
public void setUp() throws Exception {
super.setUp();
- mFocusManagerUT = new ConnectionServiceFocusManager(
- mockCallsManagerRequester, Looper.getMainLooper());
+ mFocusManagerUT = new ConnectionServiceFocusManager(mockCallsManagerRequester);
mNewCall = createFakeCall(mNewConnectionService, CallState.NEW);
mActiveCall = createFakeCall(mActiveConnectionService, CallState.ACTIVE);
ArgumentCaptor<CallsManager.CallsManagerListener> captor =
diff --git a/tests/src/com/android/server/telecom/tests/EventManagerTest.java b/tests/src/com/android/server/telecom/tests/EventManagerTest.java
index 24394ec..8bf8d1d 100644
--- a/tests/src/com/android/server/telecom/tests/EventManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/EventManagerTest.java
@@ -16,6 +16,9 @@
package com.android.server.telecom.tests;
+import android.net.Uri;
+import android.os.Build;
+import android.telecom.Log;
import android.telecom.Logging.EventManager;
import android.test.suitebuilder.annotation.SmallTest;
@@ -217,4 +220,23 @@
assertEquals(0, timings1.size());
assertEquals(0, timings2.size());
}
+
+ /**
+ * Ensure PII logging will log the last 2 digits of a phone number.
+ */
+ @SmallTest
+ @Test
+ public void testLogLast2DigitsPhone() {
+ if (Build.IS_USER) {
+ return;
+ }
+ assertEquals("tel:**********12",
+ Log.piiHandle(Uri.fromParts("tel", "+16505551212", null)));
+ assertEquals("tel:*****12",
+ Log.piiHandle(Uri.fromParts("tel", "5551212", null)));
+ assertEquals("tel:*11",
+ Log.piiHandle(Uri.fromParts("tel", "411", null)));
+ assertEquals("tel:1",
+ Log.piiHandle(Uri.fromParts("tel", "1", null)));
+ }
}
\ No newline at end of file
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 4cf7644..780b0b1 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -69,6 +69,7 @@
import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.BluetoothPhoneServiceImpl;
import com.android.server.telecom.CallAudioManager;
+import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.CallsManagerListenerBase;
@@ -85,8 +86,11 @@
import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
import com.android.server.telecom.ProximitySensorManager;
import com.android.server.telecom.ProximitySensorManagerFactory;
+import com.android.server.telecom.StatusBarNotifier;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
+import com.android.server.telecom.WiredHeadsetManager;
+import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.components.UserCallIntentProcessor;
import com.android.server.telecom.ui.IncomingCallNotifier;
import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
@@ -98,6 +102,7 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -402,6 +407,15 @@
}
private void setupTelecomSystem() throws Exception {
+ // Remove any cached PhoneAccount xml
+ File phoneAccountFile =
+ new File(mComponentContextFixture.getTestDouble()
+ .getApplicationContext().getFilesDir(),
+ PhoneAccountRegistrar.FILE_NAME);
+ if (phoneAccountFile.exists()) {
+ phoneAccountFile.delete();
+ }
+
// Use actual implementations instead of mocking the interface out.
HeadsetMediaButtonFactory headsetMediaButtonFactory =
spy(new HeadsetMediaButtonFactoryF());
@@ -422,45 +436,39 @@
when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME);
mTelecomSystem = new TelecomSystem(
mComponentContextFixture.getTestDouble(),
- new MissedCallNotifierImplFactory() {
- @Override
- public MissedCallNotifier makeMissedCallNotifierImpl(Context context,
- PhoneAccountRegistrar phoneAccountRegistrar,
- DefaultDialerCache defaultDialerCache) {
- return mMissedCallNotifier;
- }
- },
+ (context, phoneAccountRegistrar, defaultDialerCache) -> mMissedCallNotifier,
mCallerInfoAsyncQueryFactoryFixture.getTestDouble(),
headsetMediaButtonFactory,
proximitySensorManagerFactory,
inCallWakeLockControllerFactory,
- new CallAudioManager.AudioServiceFactory() {
- @Override
- public IAudioService getAudioService() {
- return mAudioService;
- }
- },
- new BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory() {
- @Override
- public BluetoothPhoneServiceImpl makeBluetoothPhoneServiceImpl(Context context,
- TelecomSystem.SyncRoot lock, CallsManager callsManager,
- PhoneAccountRegistrar phoneAccountRegistrar) {
- return mBluetoothPhoneServiceImpl;
- }
- },
- new ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory() {
- @Override
- public ConnectionServiceFocusManager create(
- ConnectionServiceFocusManager.CallsManagerRequester requester,
- Looper looper) {
- return new ConnectionServiceFocusManager(requester, looper);
- }
- },
+ () -> mAudioService,
+ (context, lock, callsManager, phoneAccountRegistrar) -> mBluetoothPhoneServiceImpl,
+ ConnectionServiceFocusManager::new,
mTimeoutsAdapter,
mAsyncRingtonePlayer,
mPhoneNumberUtilsAdapter,
mIncomingCallNotifier,
(streamType, volume) -> mock(ToneGenerator.class),
+ new CallAudioRouteStateMachine.Factory() {
+ @Override
+ public CallAudioRouteStateMachine create(
+ Context context,
+ CallsManager callsManager,
+ BluetoothRouteManager bluetoothManager,
+ WiredHeadsetManager wiredHeadsetManager,
+ StatusBarNotifier statusBarNotifier,
+ CallAudioManager.AudioServiceFactory audioServiceFactory,
+ int earpieceControl) {
+ return new CallAudioRouteStateMachine(context,
+ callsManager,
+ bluetoothManager,
+ wiredHeadsetManager,
+ statusBarNotifier,
+ audioServiceFactory,
+ // Force enable an earpiece for the end-to-end tests
+ CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED);
+ }
+ },
mClockProxy);
mComponentContextFixture.setTelecomManager(new TelecomManager(
@@ -763,14 +771,16 @@
ConnectionServiceFixture connectionServiceFixture) throws Exception {
// Wait for the focus tracker.
- waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
+ waitForHandlerAction(mTelecomSystem.getCallsManager()
+ .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
verify(connectionServiceFixture.getTestDouble())
.createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class),
eq(false)/*isIncoming*/, anyBoolean(), any());
// Wait for handleCreateConnectionComplete
waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
- assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
+ assertEquals(startingNumConnections + 1,
+ connectionServiceFixture.mConnectionById.size());
// Wait for the callback in ConnectionService#onAdapterAttached to execute.
waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
@@ -972,6 +982,8 @@
mInCallServiceFixtureX.mInCallAdapter
.answerCall(ids.mCallId, videoState);
+ // Wait on the main looper (due to the CS focus manager)
+ waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
if (!VideoProfile.isVideo(videoState)) {
verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))