Merge changes from topic "hookup-callscreening-api-2"
* changes:
Make background call screening compatible with BT
Add audio processing notification and testapp code
Add the rest of the background audio screen API
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e4e588c..92a7808 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -48,6 +48,18 @@
[CHAR LIMIT=18] -->
<string name="notification_missedCall_message">Message</string>
+ <!-- Title for the persistent notification presented when an app has requested that a call
+ be put into the background so that the app can access the audio from the call
+ [CHAR LIMIT=20] -->
+ <string name="notification_audioProcessing_title">Background call</string>
+ <!-- Body of the persistent notification presented when an app requests
+ that a call be put into the background so that the app can access the audio from the call.
+ [CHAR LIMIT=NONE] -->
+ <string name="notification_audioProcessing_body">
+ <xliff:g id="audio_processing_app_name">%s</xliff:g> has placed a call into the
+ background. This app may be accessing and playing audio over the call.
+ </string>
+
<!-- Content description of the call muted notification icon for
accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_call_muted">Call muted.</string>
@@ -276,6 +288,8 @@
<string name="notification_channel_missed_call">Missed calls</string>
<!-- Notification channel name for a channel containing call blocking notifications. -->
<string name="notification_channel_call_blocking">Call Blocking</string>
+ <!-- Notification channel name for a channel containing background call notifications. -->
+ <string name="notification_channel_background_calls">Background calls</string>
<!-- Alert dialog content used to inform the user that placing a new outgoing call will end the
ongoing call in the app "other_app". -->
diff --git a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
index 33dddbd..e80eeba 100644
--- a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
+++ b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
@@ -78,12 +78,15 @@
// Add all held calls to a conference
private static final int CHLD_TYPE_ADDHELDTOCONF = 3;
+ // Indicates that no call is ringing
+ private static final int DEFAULT_RINGING_ADDRESS_TYPE = 128;
+
private int mNumActiveCalls = 0;
private int mNumHeldCalls = 0;
private int mNumChildrenOfActiveCall = 0;
private int mBluetoothCallState = CALL_STATE_IDLE;
- private String mRingingAddress = null;
- private int mRingingAddressType = 0;
+ private String mRingingAddress = "";
+ private int mRingingAddressType = DEFAULT_RINGING_ADDRESS_TYPE;
private Call mOldHeldCall = null;
private boolean mIsDisconnectedTonePlaying = false;
@@ -101,7 +104,7 @@
long token = Binder.clearCallingIdentity();
try {
Log.i(TAG, "BT - answering call");
- Call call = mCallsManager.getRingingCall();
+ Call call = mCallsManager.getRingingOrSimulatedRingingCall();
if (call != null) {
mCallsManager.answerCall(call, VideoProfile.STATE_AUDIO_ONLY);
return true;
@@ -493,7 +496,7 @@
private boolean processChld(int chld) {
Call activeCall = mCallsManager.getActiveCall();
- Call ringingCall = mCallsManager.getRingingCall();
+ Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
Call heldCall = mCallsManager.getHeldCall();
// TODO: Keeping as Log.i for now. Move to Log.d after L release if BT proves stable.
@@ -699,13 +702,13 @@
*/
private void updateHeadsetWithCallState(boolean force) {
Call activeCall = mCallsManager.getActiveCall();
- Call ringingCall = mCallsManager.getRingingCall();
+ Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
Call heldCall = mCallsManager.getHeldCall();
int bluetoothCallState = getBluetoothCallStateForUpdate();
String ringingAddress = null;
- int ringingAddressType = 128;
+ int ringingAddressType = DEFAULT_RINGING_ADDRESS_TYPE;
String ringingName = null;
if (ringingCall != null && ringingCall.getHandle() != null
&& !ringingCall.isSilentRingingRequested()) {
@@ -832,7 +835,7 @@
}
private int getBluetoothCallStateForUpdate() {
- Call ringingCall = mCallsManager.getRingingCall();
+ Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
Call dialingCall = mCallsManager.getOutgoingCall();
boolean hasOnlyDisconnectedCalls = mCallsManager.hasOnlyDisconnectedCalls();
@@ -862,6 +865,7 @@
case CallState.NEW:
case CallState.ABORTED:
case CallState.DISCONNECTED:
+ case CallState.AUDIO_PROCESSING:
return CALL_STATE_IDLE;
case CallState.ACTIVE:
@@ -885,6 +889,7 @@
case CallState.RINGING:
case CallState.ANSWERED:
+ case CallState.SIMULATED_RINGING:
if (call.isSilentRingingRequested()) {
return CALL_STATE_IDLE;
} else if (isForeground) {
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 7b157d4..68e71fb 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -545,6 +545,12 @@
private Call mHandoverSourceCall = null;
/**
+ * The user-visible app name of the app that requested for this call to be put into the
+ * AUDIO_PROCESSING state. Used to display a notification to the user.
+ */
+ private CharSequence mAudioProcessingRequestingApp = null;
+
+ /**
* Indicates the current state of this call if it is in the process of a handover.
*/
private int mHandoverState = HandoverState.HANDOVER_NONE;
@@ -2043,6 +2049,14 @@
Log.addEvent(this, LogUtils.Events.REQUEST_PICKUP_FOR_AUDIO_PROCESSING);
}
+ public void setAudioProcessingRequestingApp(CharSequence appName) {
+ mAudioProcessingRequestingApp = appName;
+ }
+
+ public CharSequence getAudioProcessingRequestingApp() {
+ return mAudioProcessingRequestingApp;
+ }
+
/**
* Deflects the call if it is ringing.
*
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index c01c9aa..1e0af5d 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -115,6 +115,7 @@
if (newBinForCall != null) {
newBinForCall.add(call);
}
+ sendCallStatusToBluetoothStateReceiver();
updateForegroundCall();
if (shouldPlayDisconnectTone(oldState, newState)) {
@@ -158,9 +159,7 @@
}
updateForegroundCall();
mCalls.add(call);
- if (mCalls.size() == 1) {
- mBluetoothStateReceiver.setIsInCall(true);
- }
+ sendCallStatusToBluetoothStateReceiver();
onCallEnteringState(call, call.getState());
}
@@ -177,13 +176,17 @@
updateForegroundCall();
mCalls.remove(call);
- if (mCalls.size() == 0) {
- mBluetoothStateReceiver.setIsInCall(false);
- }
+ sendCallStatusToBluetoothStateReceiver();
onCallLeavingState(call, call.getState());
}
+ private void sendCallStatusToBluetoothStateReceiver() {
+ // We're in a call if there are calls in mCalls that are not in mAudioProcessingCalls.
+ boolean isInCall = !mAudioProcessingCalls.containsAll(mCalls);
+ mBluetoothStateReceiver.setIsInCall(isInCall);
+ }
+
/**
* Handles changes to the external state of a call. External calls which become regular calls
* should be tracked, and regular calls which become external should no longer be tracked.
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index 06be216..1d3752b 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -329,8 +329,7 @@
transitionTo(mOtherFocusState);
return HANDLED;
case NEW_AUDIO_PROCESSING_CALL:
- Log.w(LOG_TAG, "Unexpected behavior! New audio processing call appeared while"
- + " in audio processing state.");
+ // Can happen as a duplicate message
return HANDLED;
case TONE_STARTED_PLAYING:
// This shouldn't happen either, but perform the action anyway.
@@ -404,8 +403,7 @@
+ "ringing");
}
case NEW_RINGING_CALL:
- Log.w(LOG_TAG, "Unexpected behavior! New ringing call appeared while in " +
- "ringing state.");
+ // Can happen as a duplicate message
return HANDLED;
case NEW_HOLDING_CALL:
// This really shouldn't happen, but transition to the focused state anyway.
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index ce9f877..824ae9f 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -86,6 +86,7 @@
import com.android.server.telecom.callredirection.CallRedirectionProcessor;
import com.android.server.telecom.components.ErrorDialogActivity;
import com.android.server.telecom.settings.BlockedNumbersUtil;
+import com.android.server.telecom.ui.AudioProcessingNotification;
import com.android.server.telecom.ui.CallRedirectionConfirmDialogActivity;
import com.android.server.telecom.ui.CallRedirectionTimeoutDialogActivity;
import com.android.server.telecom.ui.ConfirmCallDialogActivity;
@@ -440,6 +441,7 @@
EmergencyCallHelper emergencyCallHelper,
InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
ClockProxy clockProxy,
+ AudioProcessingNotification audioProcessingNotification,
BluetoothStateReceiver bluetoothStateReceiver,
CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
@@ -532,6 +534,7 @@
mListeners.add(missedCallNotifier);
mListeners.add(mHeadsetMediaButton);
mListeners.add(mProximitySensorManager);
+ mListeners.add(audioProcessingNotification);
// There is no USER_SWITCHED broadcast for user 0, handle it here explicitly.
final UserManager userManager = UserManager.get(mContext);
@@ -692,6 +695,7 @@
} else if (result.shouldScreenViaAudio) {
Log.i(this, "onCallFilteringCompleted: starting background audio processing");
answerCallForAudioProcessing(incomingCall);
+ incomingCall.setAudioProcessingRequestingApp(result.mCallScreeningAppName);
} else {
addCall(incomingCall);
}
@@ -2020,6 +2024,51 @@
}
/**
+ * Instructs Telecom to bring a call into the AUDIO_PROCESSING state.
+ *
+ * Used by the background audio call screener (also the default dialer) to signal that
+ * they want to manually enter the AUDIO_PROCESSING state. The user will be aware that there is
+ * an ongoing call at this time.
+ *
+ * @param call The call to manipulate
+ */
+ public void enterBackgroundAudioProcessing(Call call, String requestingPackageName) {
+ if (!mCalls.contains(call)) {
+ Log.w(this, "Trying to exit audio processing on an untracked call");
+ return;
+ }
+
+ Call activeCall = getActiveCall();
+ if (activeCall != call) {
+ Log.w(this, "Ignoring enter audio processing because there's already a call active");
+ return;
+ }
+
+ CharSequence requestingAppName;
+
+ PackageManager pm = mContext.getPackageManager();
+ try {
+ ApplicationInfo info = pm.getApplicationInfo( requestingPackageName, 0);
+ requestingAppName = pm.getApplicationLabel(info);
+ } catch (PackageManager.NameNotFoundException nnfe) {
+ Log.w(this, "Could not determine package name.");
+ requestingAppName = requestingPackageName;
+ }
+
+ // We only want this to work on active or ringing calls
+ if (call.getState() == CallState.RINGING) {
+ // After the connection service sets up the call with the other end, it'll set the call
+ // state to AUDIO_PROCESSING
+ answerCallForAudioProcessing(call);
+ call.setAudioProcessingRequestingApp(requestingAppName);
+ } else if (call.getState() == CallState.ACTIVE) {
+ setCallState(call, CallState.AUDIO_PROCESSING,
+ "audio processing set by dialer request");
+ call.setAudioProcessingRequestingApp(requestingAppName);
+ }
+ }
+
+ /**
* Instructs Telecom to bring a call out of the AUDIO_PROCESSING state.
*
* Used by the background audio call screener (also the default dialer) to signal that it's
@@ -2691,6 +2740,11 @@
return getFirstCallWithState(CallState.RINGING, CallState.ANSWERED) != null;
}
+ boolean hasRingingOrSimulatedRingingCall() {
+ return getFirstCallWithState(
+ CallState.SIMULATED_RINGING, CallState.RINGING, CallState.ANSWERED) != null;
+ }
+
@VisibleForTesting
public boolean onMediaButton(int type) {
if (hasAnyCalls()) {
@@ -2793,8 +2847,9 @@
}
@VisibleForTesting
- public Call getRingingCall() {
- return getFirstCallWithState(CallState.RINGING, CallState.ANSWERED);
+ public Call getRingingOrSimulatedRingingCall() {
+ return getFirstCallWithState(CallState.RINGING,
+ CallState.ANSWERED, CallState.SIMULATED_RINGING);
}
public Call getActiveCall() {
diff --git a/src/com/android/server/telecom/InCallAdapter.java b/src/com/android/server/telecom/InCallAdapter.java
index 81314ea..0c4c1db 100644
--- a/src/com/android/server/telecom/InCallAdapter.java
+++ b/src/com/android/server/telecom/InCallAdapter.java
@@ -19,7 +19,6 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
-import android.os.RemoteException;
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;
@@ -36,21 +35,21 @@
private final CallsManager mCallsManager;
private final CallIdMapper mCallIdMapper;
private final TelecomSystem.SyncRoot mLock;
- private final String mOwnerComponentName;
+ private final String mOwnerPackageName;
/** Persists the specified parameters. */
public InCallAdapter(CallsManager callsManager, CallIdMapper callIdMapper,
- TelecomSystem.SyncRoot lock, String ownerComponentName) {
+ TelecomSystem.SyncRoot lock, String ownerPackageName) {
mCallsManager = callsManager;
mCallIdMapper = callIdMapper;
mLock = lock;
- mOwnerComponentName = ownerComponentName;
+ mOwnerPackageName = ownerPackageName;
}
@Override
public void answerCall(String callId, int videoState) {
try {
- Log.startSession(LogUtils.Sessions.ICA_ANSWER_CALL, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_ANSWER_CALL, mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -73,7 +72,7 @@
@Override
public void deflectCall(String callId, Uri address) {
try {
- Log.startSession(LogUtils.Sessions.ICA_DEFLECT_CALL, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_DEFLECT_CALL, mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -96,7 +95,7 @@
@Override
public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) {
try {
- Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerPackageName);
int callingUid = Binder.getCallingUid();
long token = Binder.clearCallingIdentity();
@@ -129,7 +128,7 @@
@Override
public void playDtmfTone(String callId, char digit) {
try {
- Log.startSession("ICA.pDT", mOwnerComponentName);
+ Log.startSession("ICA.pDT", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -152,7 +151,7 @@
@Override
public void stopDtmfTone(String callId) {
try {
- Log.startSession("ICA.sDT", mOwnerComponentName);
+ Log.startSession("ICA.sDT", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -175,7 +174,7 @@
@Override
public void postDialContinue(String callId, boolean proceed) {
try {
- Log.startSession("ICA.pDC", mOwnerComponentName);
+ Log.startSession("ICA.pDC", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -198,7 +197,7 @@
@Override
public void disconnectCall(String callId) {
try {
- Log.startSession(LogUtils.Sessions.ICA_DISCONNECT_CALL, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_DISCONNECT_CALL, mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -221,7 +220,7 @@
@Override
public void holdCall(String callId) {
try {
- Log.startSession(LogUtils.Sessions.ICA_HOLD_CALL, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_HOLD_CALL, mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -243,7 +242,7 @@
@Override
public void unholdCall(String callId) {
try {
- Log.startSession(LogUtils.Sessions.ICA_UNHOLD_CALL, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_UNHOLD_CALL, mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -266,7 +265,7 @@
public void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle,
boolean setDefault) {
try {
- Log.startSession("ICA.pAS", mOwnerComponentName);
+ Log.startSession("ICA.pAS", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -288,7 +287,7 @@
@Override
public void mute(boolean shouldMute) {
try {
- Log.startSession(LogUtils.Sessions.ICA_MUTE, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_MUTE, mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -305,7 +304,7 @@
@Override
public void setAudioRoute(int route, String bluetoothAddress) {
try {
- Log.startSession(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -321,13 +320,28 @@
@Override
public void enterBackgroundAudioProcessing(String callId) {
- // TODO: implement this
+ try {
+ Log.startSession(LogUtils.Sessions.ICA_ENTER_AUDIO_PROCESSING, mOwnerPackageName);
+ // TODO: enforce the extra permission.
+ Binder.withCleanCallingIdentity(() -> {
+ synchronized (mLock) {
+ Call call = mCallIdMapper.getCall(callId);
+ if (call != null) {
+ mCallsManager.enterBackgroundAudioProcessing(call, mOwnerPackageName);
+ } else {
+ Log.w(this, "enterBackgroundAudioProcessing, unknown call id: %s", callId);
+ }
+ }
+ });
+ } finally {
+ Log.endSession();
+ }
}
@Override
public void exitBackgroundAudioProcessing(String callId, boolean shouldRing) {
try {
- Log.startSession(LogUtils.Sessions.ICA_EXIT_AUDIO_PROCESSING, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_EXIT_AUDIO_PROCESSING, mOwnerPackageName);
Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) {
Call call = mCallIdMapper.getCall(callId);
@@ -347,7 +361,7 @@
@Override
public void conference(String callId, String otherCallId) {
try {
- Log.startSession(LogUtils.Sessions.ICA_CONFERENCE, mOwnerComponentName);
+ Log.startSession(LogUtils.Sessions.ICA_CONFERENCE, mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -370,7 +384,7 @@
@Override
public void splitFromConference(String callId) {
try {
- Log.startSession("ICA.sFC", mOwnerComponentName);
+ Log.startSession("ICA.sFC", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -392,7 +406,7 @@
@Override
public void mergeConference(String callId) {
try {
- Log.startSession("ICA.mC", mOwnerComponentName);
+ Log.startSession("ICA.mC", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -414,7 +428,7 @@
@Override
public void swapConference(String callId) {
try {
- Log.startSession("ICA.sC", mOwnerComponentName);
+ Log.startSession("ICA.sC", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -436,7 +450,7 @@
@Override
public void pullExternalCall(String callId) {
try {
- Log.startSession("ICA.pEC", mOwnerComponentName);
+ Log.startSession("ICA.pEC", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -458,7 +472,7 @@
@Override
public void sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras) {
try {
- Log.startSession("ICA.sCE", mOwnerComponentName);
+ Log.startSession("ICA.sCE", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -480,7 +494,7 @@
@Override
public void putExtras(String callId, Bundle extras) {
try {
- Log.startSession("ICA.pE", mOwnerComponentName);
+ Log.startSession("ICA.pE", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -502,7 +516,7 @@
@Override
public void removeExtras(String callId, List<String> keys) {
try {
- Log.startSession("ICA.rE", mOwnerComponentName);
+ Log.startSession("ICA.rE", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -524,7 +538,7 @@
@Override
public void turnOnProximitySensor() {
try {
- Log.startSession("ICA.tOnPS", mOwnerComponentName);
+ Log.startSession("ICA.tOnPS", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -541,7 +555,7 @@
@Override
public void turnOffProximitySensor(boolean screenOnImmediately) {
try {
- Log.startSession("ICA.tOffPS", mOwnerComponentName);
+ Log.startSession("ICA.tOffPS", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -642,7 +656,7 @@
public void handoverTo(String callId, PhoneAccountHandle destAcct, int videoState,
Bundle extras) {
try {
- Log.startSession("ICA.hT", mOwnerComponentName);
+ Log.startSession("ICA.hT", mOwnerPackageName);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
diff --git a/src/com/android/server/telecom/InCallWakeLockController.java b/src/com/android/server/telecom/InCallWakeLockController.java
index ac93bb5..b37883d 100644
--- a/src/com/android/server/telecom/InCallWakeLockController.java
+++ b/src/com/android/server/telecom/InCallWakeLockController.java
@@ -62,7 +62,7 @@
private void handleWakeLock() {
// We grab a full lock as long as there exists a ringing call.
- Call ringingCall = mCallsManager.getRingingCall();
+ Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
if (ringingCall != null) {
mTelecomWakeLock.acquire();
Log.i(this, "Acquiring full wake lock");
diff --git a/src/com/android/server/telecom/PhoneStateBroadcaster.java b/src/com/android/server/telecom/PhoneStateBroadcaster.java
index d574589..a5e3848 100644
--- a/src/com/android/server/telecom/PhoneStateBroadcaster.java
+++ b/src/com/android/server/telecom/PhoneStateBroadcaster.java
@@ -85,7 +85,7 @@
// Note: CallsManager#hasRingingCall() and CallsManager#getFirstCallWithState(..) do not
// consider external calls, so an external call is going to cause the state to be idle.
int callState = TelephonyManager.CALL_STATE_IDLE;
- if (mCallsManager.hasRingingCall()) {
+ if (mCallsManager.hasRingingOrSimulatedRingingCall()) {
callState = TelephonyManager.CALL_STATE_RINGING;
} else if (mCallsManager.getFirstCallWithState(CallState.DIALING, CallState.PULLING,
CallState.ACTIVE, CallState.ON_HOLD) != null) {
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index f354b94..f3b7b25 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -23,6 +23,7 @@
import com.android.server.telecom.callfiltering.IncomingCallFilter;
import com.android.server.telecom.components.UserCallIntentProcessor;
import com.android.server.telecom.components.UserCallIntentProcessorFactory;
+import com.android.server.telecom.ui.AudioProcessingNotification;
import com.android.server.telecom.ui.IncomingCallNotifier;
import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
import com.android.server.telecom.BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory;
@@ -267,6 +268,9 @@
}
};
+ AudioProcessingNotification audioProcessingNotification =
+ new AudioProcessingNotification(mContext);
+
mCallsManager = new CallsManager(
mContext,
mLock,
@@ -288,6 +292,7 @@
emergencyCallHelper,
toneGeneratorFactory,
clockProxy,
+ audioProcessingNotification,
bluetoothStateReceiver,
callAudioRouteStateMachineFactory,
callAudioModeStateMachineFactory,
diff --git a/src/com/android/server/telecom/callfiltering/CallFilteringResult.java b/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
index afd145e..c17a256 100644
--- a/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
+++ b/src/com/android/server/telecom/callfiltering/CallFilteringResult.java
@@ -144,6 +144,14 @@
other.mCallScreeningAppName, other.mCallScreeningComponentName);
}
+ if (shouldScreenViaAudio) {
+ return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_NOT_BLOCKED,
+ mCallScreeningAppName, mCallScreeningComponentName);
+ } else if (other.shouldScreenViaAudio) {
+ return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_NOT_BLOCKED,
+ other.mCallScreeningAppName, other.mCallScreeningComponentName);
+ }
+
return new Builder()
.setShouldAllowCall(shouldAllowCall && other.shouldAllowCall)
.setShouldReject(shouldReject || other.shouldReject)
diff --git a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
index 7e0f6b0..a795f73 100644
--- a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
+++ b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
@@ -182,7 +182,8 @@
@Override
public void screenCallFurther(String callId) {
Log.startSession("CSCR.sCF");
- Binder.withCleanCallingIdentity(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
synchronized (mTelecomLock) {
// This is only allowed if the caller is also the default dialer.
if (!mCallsManager.getDefaultDialerCache().isDefaultOrSystemDialer(
@@ -199,13 +200,17 @@
.setShouldReject(false)
.setShouldSilence(false)
.setShouldScreenViaAudio(true)
+ .setCallScreeningAppName(mAppName)
.build();
} else {
Log.w(this, "screenCallFurther, unknown call id: %s", callId);
}
finishCallScreening();
}
- });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ Log.endSession();
+ }
}
}
diff --git a/src/com/android/server/telecom/ui/AudioProcessingNotification.java b/src/com/android/server/telecom/ui/AudioProcessingNotification.java
new file mode 100644
index 0000000..7a61460
--- /dev/null
+++ b/src/com/android/server/telecom/ui/AudioProcessingNotification.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2019, 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.server.telecom.ui;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.telecom.Log;
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallState;
+import com.android.server.telecom.CallsManagerListenerBase;
+import com.android.server.telecom.R;
+
+/**
+ * Displays a persistent notification whenever there's a call in the AUDIO_PROCESSING state so that
+ * the user is aware that there's some app
+ */
+public class AudioProcessingNotification extends CallsManagerListenerBase {
+
+ private static final int AUDIO_PROCESSING_NOTIFICATION_ID = 2;
+ private static final String NOTIFICATION_TAG =
+ AudioProcessingNotification.class.getSimpleName();
+
+ private final Context mContext;
+ private final NotificationManager mNotificationManager;
+ private Call mCallInAudioProcessing;
+
+ public AudioProcessingNotification(Context context) {
+ mContext = context;
+ mNotificationManager =
+ (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+
+ @Override
+ public void onCallStateChanged(Call call, int oldState, int newState) {
+ if (newState == CallState.AUDIO_PROCESSING && oldState != CallState.AUDIO_PROCESSING) {
+ showAudioProcessingNotification(call);
+ } else if (oldState == CallState.AUDIO_PROCESSING
+ && newState != CallState.AUDIO_PROCESSING) {
+ cancelAudioProcessingNotification();
+ }
+ }
+
+ @Override
+ public void onCallAdded(Call call) {
+ if (call.getState() == CallState.AUDIO_PROCESSING) {
+ showAudioProcessingNotification(call);
+ }
+ }
+
+ @Override
+ public void onCallRemoved(Call call) {
+ if (call == mCallInAudioProcessing) {
+ cancelAudioProcessingNotification();
+ }
+ }
+
+ /**
+ * Create a system notification for the audio processing call.
+ *
+ * @param call The missed call.
+ */
+ private void showAudioProcessingNotification(Call call) {
+ Log.i(this, "showAudioProcessingNotification");
+ mCallInAudioProcessing = call;
+
+ Notification.Builder builder = new Notification.Builder(mContext,
+ NotificationChannelManager.CHANNEL_ID_AUDIO_PROCESSING);
+ builder.setSmallIcon(R.drawable.ic_phone)
+ .setColor(mContext.getResources().getColor(R.color.theme_color))
+ .setContentTitle(mContext.getText(R.string.notification_audioProcessing_title))
+ .setStyle(new Notification.BigTextStyle()
+ .bigText(mContext.getString(
+ R.string.notification_audioProcessing_body,
+ call.getAudioProcessingRequestingApp())))
+ .setOngoing(true);
+
+ Notification notification = builder.build();
+
+ mNotificationManager.notify(
+ NOTIFICATION_TAG, AUDIO_PROCESSING_NOTIFICATION_ID, notification);
+ }
+
+ /** Cancels the audio processing notification. */
+ private void cancelAudioProcessingNotification() {
+ mNotificationManager.cancel(NOTIFICATION_TAG, AUDIO_PROCESSING_NOTIFICATION_ID);
+ }
+}
diff --git a/src/com/android/server/telecom/ui/NotificationChannelManager.java b/src/com/android/server/telecom/ui/NotificationChannelManager.java
index 70d4d0d..d812ad8 100644
--- a/src/com/android/server/telecom/ui/NotificationChannelManager.java
+++ b/src/com/android/server/telecom/ui/NotificationChannelManager.java
@@ -37,6 +37,7 @@
public static final String CHANNEL_ID_MISSED_CALLS = "TelecomMissedCalls";
public static final String CHANNEL_ID_INCOMING_CALLS = "TelecomIncomingCalls";
public static final String CHANNEL_ID_CALL_BLOCKING = "TelecomCallBlocking";
+ public static final String CHANNEL_ID_AUDIO_PROCESSING = "TelecomBackgroundAudioProcessing";
private BroadcastReceiver mLocaleChangeReceiver = new BroadcastReceiver() {
@Override
@@ -57,6 +58,7 @@
createOrUpdateChannel(context, CHANNEL_ID_MISSED_CALLS);
createOrUpdateChannel(context, CHANNEL_ID_INCOMING_CALLS);
createOrUpdateChannel(context, CHANNEL_ID_CALL_BLOCKING);
+ createOrUpdateChannel(context, CHANNEL_ID_AUDIO_PROCESSING);
}
private void createOrUpdateChannel(Context context, String channelId) {
@@ -98,6 +100,14 @@
vibration = false;
sound = null;
break;
+ case CHANNEL_ID_AUDIO_PROCESSING:
+ name = context.getText(R.string.notification_channel_background_calls);
+ importance = NotificationManager.IMPORTANCE_LOW;
+ canShowBadge = false;
+ lights = false;
+ vibration = false;
+ sound = null;
+ break;
}
NotificationChannel channel = new NotificationChannel(channelId, name, importance);
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index e339356..f19c13e 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -20,7 +20,7 @@
<uses-sdk
android:minSdkVersion="28"
- android:targetSdkVersion="28" />
+ android:targetSdkVersion="30" />
<uses-permission android:name="android.permission.ACCEPT_HANDOVER" />
<uses-permission android:name="android.permission.BLUETOOTH" />
diff --git a/testapps/res/layout/incall_screen.xml b/testapps/res/layout/incall_screen.xml
index 452cb2b..414bdb8 100644
--- a/testapps/res/layout/incall_screen.xml
+++ b/testapps/res/layout/incall_screen.xml
@@ -71,6 +71,21 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/handoverButton"/>
+ <Button
+ android:id="@+id/exit_audio_processing_ring_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/exit_audio_processing_ring_button"/>
+ <Button
+ android:id="@+id/exit_audio_processing_noring_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/exit_audio_processing_noring_button"/>
+ <Button
+ android:id="@+id/reject_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/reject_button"/>
</GridLayout>
<LinearLayout
android:layout_width="wrap_content"
diff --git a/testapps/res/values/donottranslate_strings.xml b/testapps/res/values/donottranslate_strings.xml
index abd2949..6a085ee 100644
--- a/testapps/res/values/donottranslate_strings.xml
+++ b/testapps/res/values/donottranslate_strings.xml
@@ -56,6 +56,12 @@
<string name="holdButton">Hold</string>
+ <string name="exit_audio_processing_noring_button">Exit AP (no ring)</string>
+
+ <string name="exit_audio_processing_ring_button">Exit AP (ring)</string>
+
+ <string name="reject_button">Reject</string>
+
<string name="handoverButton">Handover</string>
<string name="inCallUiAppLabel">Test InCall UI</string>
diff --git a/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java b/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
index 4de6eed..5fa13e3 100644
--- a/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
+++ b/testapps/src/com/android/server/telecom/testapps/CallListAdapter.java
@@ -150,6 +150,10 @@
return "ringing";
case Call.STATE_SELECT_PHONE_ACCOUNT:
return "select phone account";
+ case Call.STATE_AUDIO_PROCESSING:
+ return "audio processing";
+ case Call.STATE_SIMULATED_RINGING:
+ return "simulated ringing";
default:
return "unknown";
}
diff --git a/testapps/src/com/android/server/telecom/testapps/CallScreeningActivity.java b/testapps/src/com/android/server/telecom/testapps/CallScreeningActivity.java
deleted file mode 100644
index 05ba500..0000000
--- a/testapps/src/com/android/server/telecom/testapps/CallScreeningActivity.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2018 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.server.telecom.testapps;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.telecom.CallScreeningService;
-import android.view.WindowManager;
-
-public class CallScreeningActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- AlertDialog alertDialog = new AlertDialog.Builder(this)
- .setTitle("Test Call Screening")
- .setMessage("Allow the call?")
- .setNegativeButton("Block", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (TestCallScreeningService.getInstance() != null) {
- TestCallScreeningService.getInstance().blockCall();
- }
- finish();
- }
- })
- .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (TestCallScreeningService.getInstance() != null) {
- TestCallScreeningService.getInstance().allowCall();
- }
- finish();
- }
- }).create();
- alertDialog.show();
- }
-}
diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java b/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
index 5f7f4d5..544eb28 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
@@ -16,12 +16,16 @@
package com.android.server.telecom.testapps;
-import android.content.Intent;
-import android.graphics.drawable.Icon;
+import android.os.SystemProperties;
import android.telecom.Call;
import android.telecom.CallScreeningService;
import android.telecom.Log;
+/**
+ * To use this while testing, use:
+ * adb shell setprop com.android.server.telecom.testapps.callscreeningresult n,
+ * where n is one of the codes defined below.
+ */
public class TestCallScreeningService extends CallScreeningService {
private Call.Details mDetails;
private static TestCallScreeningService sTestCallScreeningService;
@@ -30,6 +34,13 @@
return sTestCallScreeningService;
}
+ private static final int ALLOW_CALL = 0;
+ private static final int BLOCK_CALL = 1;
+ private static final int SCREEN_CALL_FURTHER = 2;
+
+ private static final String SCREENING_RESULT_KEY =
+ TestCallScreeningService.class.getPackage().getName() + ".callscreeningresult";
+
/**
* Handles request from the system to screen an incoming call.
* @param callDetails Information about a new incoming call, see {@link Call.Details}.
@@ -40,10 +51,21 @@
sTestCallScreeningService = this;
mDetails = callDetails;
+
if (callDetails.getCallDirection() == Call.Details.DIRECTION_INCOMING) {
- Intent errorIntent = new Intent(this, CallScreeningActivity.class);
- errorIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(errorIntent);
+ Log.i(this, "%s = %d", SCREENING_RESULT_KEY,
+ SystemProperties.getInt(SCREENING_RESULT_KEY, 0));
+ switch (SystemProperties.getInt(SCREENING_RESULT_KEY, 0)) {
+ case ALLOW_CALL:
+ allowCall();
+ break;
+ case BLOCK_CALL:
+ blockCall();
+ break;
+ case SCREEN_CALL_FURTHER:
+ screenCallFurther();
+ break;
+ }
}
}
@@ -68,4 +90,16 @@
.build();
respondToCall(mDetails, response);
}
+
+ void screenCallFurther() {
+ CallScreeningService.CallResponse
+ response = new CallScreeningService.CallResponse.Builder()
+ .setDisallowCall(false)
+ .setRejectCall(false)
+ .setSkipCallLog(false)
+ .setSkipNotification(false)
+ .setShouldScreenCallFurther(true)
+ .build();
+ respondToCall(mDetails, response);
+ }
}
diff --git a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
index 2a5b33a..edcbba1 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
@@ -125,6 +125,10 @@
View setBtDeviceButton = findViewById(R.id.set_bt_device_button);
View earpieceButton = findViewById(R.id.earpiece_button);
View speakerButton = findViewById(R.id.speaker_button);
+ View exitAudioProcessingRingButton = findViewById(R.id.exit_audio_processing_ring_button);
+ View exitAudioProcessingNoRingButton =
+ findViewById(R.id.exit_audio_processing_noring_button);
+ View rejectButton = findViewById(R.id.reject_button);
mBtDeviceList = findViewById(R.id.available_bt_devices);
mBluetoothDeviceAdapter = new BluetoothDeviceAdapter();
mBtDeviceList.setAdapter(mBluetoothDeviceAdapter);
@@ -173,7 +177,8 @@
answerButton.setOnClickListener(view -> {
Call call = mCallList.getCall(0);
- if (call.getState() == Call.STATE_RINGING) {
+ if (call.getState() == Call.STATE_RINGING
+ || call.getState() == Call.STATE_SIMULATED_RINGING) {
call.answer(VideoProfile.STATE_AUDIO_ONLY);
}
});
@@ -213,6 +218,21 @@
call.handoverTo(getHandoverToPhoneAccountHandle(), VideoProfile.STATE_BIDIRECTIONAL,
null);
});
+
+ exitAudioProcessingRingButton.setOnClickListener((v) -> {
+ Call call = mCallList.getCall(0);
+ call.exitBackgroundAudioProcessing(true);
+ });
+
+ exitAudioProcessingNoRingButton.setOnClickListener((v) -> {
+ Call call = mCallList.getCall(0);
+ call.exitBackgroundAudioProcessing(false);
+ });
+
+ rejectButton.setOnClickListener((v) -> {
+ Call call = mCallList.getCall(0);
+ call.reject(false, null);
+ });
}
public void updateCallAudioState(CallAudioState cas) {
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java b/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
index 882f437..16e6355 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
@@ -113,7 +113,7 @@
doNothing().when(mMockCallsManager).addListener(any(
CallsManager.CallsManagerListener.class));
doReturn(null).when(mMockCallsManager).getActiveCall();
- doReturn(null).when(mMockCallsManager).getRingingCall();
+ doReturn(null).when(mMockCallsManager).getRingingOrSimulatedRingingCall();
doReturn(null).when(mMockCallsManager).getHeldCall();
doReturn(null).when(mMockCallsManager).getOutgoingCall();
doReturn(0).when(mMockCallsManager).getNumHeldCalls();
@@ -147,7 +147,7 @@
@SmallTest
@Test
public void testHeadsetAnswerCallNull() throws Exception {
- when(mMockCallsManager.getRingingCall()).thenReturn(null);
+ when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
boolean callAnswered = mBluetoothPhoneService.mBinder.answerCall();
@@ -282,7 +282,7 @@
when(silentRingingCall.isConference()).thenReturn(false);
when(silentRingingCall.getHandle()).thenReturn(Uri.parse("tel:555-000"));
when(mMockCallsManager.getCalls()).thenReturn(calls);
- when(mMockCallsManager.getRingingCall()).thenReturn(silentRingingCall);
+ when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(silentRingingCall);
mBluetoothPhoneService.mBinder.listCurrentCalls();
@@ -819,8 +819,8 @@
mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
- verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
- eq(""), eq(128), nullable(String.class));
+ verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
+ anyString(), anyInt(), nullable(String.class));
}
@MediumTest
@@ -876,6 +876,64 @@
@MediumTest
@Test
+ public void testOnCallAddedAudioProcessing() throws Exception {
+ Call call = mock(Call.class);
+ when(call.getState()).thenReturn(CallState.AUDIO_PROCESSING);
+ mBluetoothPhoneService.mCallsManagerListener.onCallAdded(call);
+
+ verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
+ anyString(), anyInt(), nullable(String.class));
+ }
+
+ @MediumTest
+ @Test
+ public void testOnCallStateChangedRingingToAudioProcessing() throws Exception {
+ Call ringingCall = createRingingCall();
+ when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));
+
+ mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
+
+ verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
+ eq("555000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
+
+ when(ringingCall.getState()).thenReturn(CallState.AUDIO_PROCESSING);
+ when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
+
+ mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
+ CallState.RINGING, CallState.AUDIO_PROCESSING);
+
+ verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
+ eq(""), eq(128), nullable(String.class));
+ }
+
+ @MediumTest
+ @Test
+ public void testOnCallStateChangedAudioProcessingToSimulatedRinging() throws Exception {
+ Call ringingCall = createRingingCall();
+ when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
+
+ mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
+ CallState.AUDIO_PROCESSING, CallState.SIMULATED_RINGING);
+
+ verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
+ eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
+ }
+
+ @MediumTest
+ @Test
+ public void testOnCallStateChangedAudioProcessingToActive() throws Exception {
+ Call activeCall = createActiveCall();
+ when(activeCall.getState()).thenReturn(CallState.ACTIVE);
+
+ mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall,
+ CallState.AUDIO_PROCESSING, CallState.ACTIVE);
+
+ verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
+ eq(""), eq(128), nullable(String.class));
+ }
+
+ @MediumTest
+ @Test
public void testOnCallStateChangedDialing() throws Exception {
Call activeCall = createActiveCall();
@@ -931,7 +989,7 @@
eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
//Switch to active
- doReturn(null).when(mMockCallsManager).getRingingCall();
+ doReturn(null).when(mMockCallsManager).getRingingOrSimulatedRingingCall();
when(mMockCallsManager.getActiveCall()).thenReturn(ringingCall);
mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
@@ -1021,7 +1079,7 @@
private Call createRingingCall() {
Call call = mock(Call.class);
- when(mMockCallsManager.getRingingCall()).thenReturn(call);
+ when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(call);
return call;
}
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 6da4723..b25b4c8 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -83,6 +83,7 @@
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
import com.android.server.telecom.callfiltering.IncomingCallFilter;
+import com.android.server.telecom.ui.AudioProcessingNotification;
import org.junit.After;
import org.junit.Before;
@@ -165,6 +166,7 @@
@Mock private EmergencyCallHelper mEmergencyCallHelper;
@Mock private InCallTonePlayer.ToneGeneratorFactory mToneGeneratorFactory;
@Mock private ClockProxy mClockProxy;
+ @Mock private AudioProcessingNotification mAudioProcessingNotification;
@Mock private InCallControllerFactory mInCallControllerFactory;
@Mock private InCallController mInCallController;
@Mock private ConnectionServiceFocusManager mConnectionSvrFocusMgr;
@@ -223,6 +225,7 @@
mEmergencyCallHelper,
mToneGeneratorFactory,
mClockProxy,
+ mAudioProcessingNotification,
mBluetoothStateReceiver,
mCallAudioRouteStateMachineFactory,
mCallAudioModeStateMachineFactory,
diff --git a/tests/src/com/android/server/telecom/tests/InCallWakeLockControllerTest.java b/tests/src/com/android/server/telecom/tests/InCallWakeLockControllerTest.java
index fd581f3..fd7505b 100644
--- a/tests/src/com/android/server/telecom/tests/InCallWakeLockControllerTest.java
+++ b/tests/src/com/android/server/telecom/tests/InCallWakeLockControllerTest.java
@@ -66,7 +66,7 @@
@SmallTest
@Test
public void testRingingCallAdded() throws Exception {
- when(mCallsManager.getRingingCall()).thenReturn(mCall);
+ when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(mCall);
when(mWakeLockAdapter.isHeld()).thenReturn(false);
mInCallWakeLockController.onCallAdded(mCall);
@@ -77,7 +77,7 @@
@SmallTest
@Test
public void testNonRingingCallAdded() throws Exception {
- when(mCallsManager.getRingingCall()).thenReturn(null);
+ when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
when(mWakeLockAdapter.isHeld()).thenReturn(false);
mInCallWakeLockController.onCallAdded(mCall);
@@ -88,7 +88,7 @@
@SmallTest
@Test
public void testRingingCallTransition() throws Exception {
- when(mCallsManager.getRingingCall()).thenReturn(mCall);
+ when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(mCall);
when(mWakeLockAdapter.isHeld()).thenReturn(false);
mInCallWakeLockController.onCallStateChanged(mCall, CallState.NEW, CallState.RINGING);
@@ -99,7 +99,7 @@
@SmallTest
@Test
public void testRingingCallRemoved() throws Exception {
- when(mCallsManager.getRingingCall()).thenReturn(null);
+ when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
when(mWakeLockAdapter.isHeld()).thenReturn(false);
mInCallWakeLockController.onCallRemoved(mCall);
@@ -110,7 +110,7 @@
@SmallTest
@Test
public void testWakeLockReleased() throws Exception {
- when(mCallsManager.getRingingCall()).thenReturn(null);
+ when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
when(mWakeLockAdapter.isHeld()).thenReturn(true);
mInCallWakeLockController.onCallRemoved(mCall);
@@ -121,7 +121,7 @@
@SmallTest
@Test
public void testAcquireWakeLockWhenHeld() throws Exception {
- when(mCallsManager.getRingingCall()).thenReturn(mCall);
+ when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(mCall);
when(mWakeLockAdapter.isHeld()).thenReturn(true);
mInCallWakeLockController.onCallAdded(mock(Call.class));