Merge "Revert^2 "Modify Tests to make SessionManager final for tests"" into main
diff --git a/flags/telecom_non_critical_security_flags.aconfig b/flags/telecom_non_critical_security_flags.aconfig
index 37929a8..e492073 100644
--- a/flags/telecom_non_critical_security_flags.aconfig
+++ b/flags/telecom_non_critical_security_flags.aconfig
@@ -7,4 +7,15 @@
namespace: "telecom"
description: "When set, Telecom will unregister accounts if the service is not resolvable"
bug: "281061708"
+}
+
+# OWNER=tgunn TARGET=25Q2
+flag {
+ name: "enforce_transactional_exclusivity"
+ namespace: "telecom"
+ description: "When set, ensure that transactional accounts cannot also be call capable"
+ bug: "376936125"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index d2ac13a..ba75d0c 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -100,7 +100,7 @@
<string name="notification_channel_background_calls" msgid="7785659903711350506">"Pozivi u pozadini"</string>
<string name="notification_channel_disconnected_calls" msgid="8228636543997645757">"Prekinuti pozivi"</string>
<string name="notification_channel_in_call_service_crash" msgid="7313237519166984267">"Padovi aplikacija za telefon"</string>
- <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Prijenos poziva"</string>
+ <string name="notification_channel_call_streaming" msgid="5100510699787538991">"Prenos poziva"</string>
<string name="alert_outgoing_call" msgid="5319895109298927431">"Upućivanje ovog poziva će prekinuti poziv: <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string>
<string name="alert_redirect_outgoing_call_or_not" msgid="665409645789521636">"Odaberite kako želite uputiti ovaj poziv"</string>
<string name="alert_place_outgoing_call_with_redirection" msgid="5221065030959024121">"Preusmjeri poziv pomoću aplikacije <xliff:g id="OTHER_APP">%1$s</xliff:g>"</string>
@@ -131,7 +131,7 @@
<string name="callendpoint_name_speaker" msgid="1971760468695323189">"Zvučnik"</string>
<string name="callendpoint_name_streaming" msgid="2337595450408275576">"Vanjski"</string>
<string name="callendpoint_name_unknown" msgid="2199074708477193852">"Nepoznato"</string>
- <string name="call_streaming_notification_body" msgid="502216105683378263">"Prijenos zvuka na drugom uređaju"</string>
+ <string name="call_streaming_notification_body" msgid="502216105683378263">"Prenos zvuka na drugom uređaju"</string>
<string name="call_streaming_notification_action_hang_up" msgid="7017663335289063827">"Prekini vezu"</string>
<string name="call_streaming_notification_action_switch_here" msgid="3524180754186221228">"Prebaci ovdje"</string>
</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 876b049..7d8045a 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -126,7 +126,7 @@
<string name="cancel" msgid="6733466216239934756">"Anulo"</string>
<string name="back" msgid="6915955601805550206">"Pas"</string>
<string name="callendpoint_name_earpiece" msgid="7047285080319678594">"Receptori"</string>
- <string name="callendpoint_name_bluetooth" msgid="210210953208913172">"Bluetooth"</string>
+ <string name="callendpoint_name_bluetooth" msgid="210210953208913172">"Bluetooth-i"</string>
<string name="callendpoint_name_wiredheadset" msgid="6860787176412079742">"Kufje me tel"</string>
<string name="callendpoint_name_speaker" msgid="1971760468695323189">"Altoparlant"</string>
<string name="callendpoint_name_streaming" msgid="2337595450408275576">"E jashtme"</string>
diff --git a/src/com/android/server/telecom/CachedVideoStateChange.java b/src/com/android/server/telecom/CachedVideoStateChange.java
index cefb92b..8aa6d40 100644
--- a/src/com/android/server/telecom/CachedVideoStateChange.java
+++ b/src/com/android/server/telecom/CachedVideoStateChange.java
@@ -16,7 +16,8 @@
package com.android.server.telecom;
-import static com.android.server.telecom.voip.VideoStateTranslation.TransactionalVideoStateToString;
+import static com.android.server.telecom.callsequencing.voip.VideoStateTranslation
+ .TransactionalVideoStateToString;
import android.telecom.Log;
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index c391641..df31e02 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -21,8 +21,10 @@
import static com.android.server.telecom.CachedCallback.TYPE_QUEUE;
import static com.android.server.telecom.CachedCallback.TYPE_STATE;
-import static com.android.server.telecom.voip.VideoStateTranslation.TransactionalVideoStateToString;
-import static com.android.server.telecom.voip.VideoStateTranslation.VideoProfileStateToTransactionalVideoState;
+import static com.android.server.telecom.callsequencing.voip.VideoStateTranslation
+ .TransactionalVideoStateToString;
+import static com.android.server.telecom.callsequencing.voip.VideoStateTranslation
+ .VideoProfileStateToTransactionalVideoState;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -78,9 +80,9 @@
import com.android.server.telecom.stats.CallFailureCause;
import com.android.server.telecom.stats.CallStateChangedAtomWriter;
import com.android.server.telecom.ui.ToastFactory;
-import com.android.server.telecom.voip.TransactionManager;
-import com.android.server.telecom.voip.VerifyCallStateChangeTransaction;
-import com.android.server.telecom.voip.VoipCallTransactionResult;
+import com.android.server.telecom.callsequencing.TransactionManager;
+import com.android.server.telecom.callsequencing.VerifyCallStateChangeTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.io.IOException;
import java.text.SimpleDateFormat;
@@ -3185,7 +3187,7 @@
tm.addTransaction(new VerifyCallStateChangeTransaction(mCallsManager.getLock(),
this, targetCallState), new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
Log.i(this, "awaitCallStateChangeAndMaybeDisconnectCall: %s: onResult:"
+ " due to CallException=[%s]", callingMethod, result);
}
diff --git a/src/com/android/server/telecom/CallStreamingController.java b/src/com/android/server/telecom/CallStreamingController.java
index efd458e..d14a553 100644
--- a/src/com/android/server/telecom/CallStreamingController.java
+++ b/src/com/android/server/telecom/CallStreamingController.java
@@ -39,10 +39,10 @@
import android.telecom.Log;
import com.android.internal.telecom.ICallStreamingService;
-import com.android.server.telecom.voip.ParallelTransaction;
-import com.android.server.telecom.voip.SerialTransaction;
-import com.android.server.telecom.voip.VoipCallTransaction;
-import com.android.server.telecom.voip.VoipCallTransactionResult;
+import com.android.server.telecom.callsequencing.voip.ParallelTransaction;
+import com.android.server.telecom.callsequencing.voip.SerialTransaction;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.util.ArrayList;
import java.util.List;
@@ -112,7 +112,7 @@
}
}
- public static class QueryCallStreamingTransaction extends VoipCallTransaction {
+ public static class QueryCallStreamingTransaction extends CallTransaction {
private final CallsManager mCallsManager;
public QueryCallStreamingTransaction(CallsManager callsManager) {
@@ -121,24 +121,24 @@
}
@Override
- public CompletableFuture<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletableFuture<CallTransactionResult> processTransaction(Void v) {
Log.i(this, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
if (mCallsManager.getCallStreamingController().isStreaming()) {
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
"STREAMING_FAILED_ALREADY_STREAMING"));
} else {
- future.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, null));
+ future.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, null));
}
return future;
}
}
- public static class AudioInterceptionTransaction extends VoipCallTransaction {
+ public static class AudioInterceptionTransaction extends CallTransaction {
private Call mCall;
private boolean mEnterInterception;
@@ -150,16 +150,16 @@
}
@Override
- public CompletableFuture<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletableFuture<CallTransactionResult> processTransaction(Void v) {
Log.i(this, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
if (mEnterInterception) {
mCall.startStreaming();
} else {
mCall.stopStreaming();
}
- future.complete(new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED,
+ future.complete(new CallTransactionResult(CallTransactionResult.RESULT_SUCCEED,
null));
return future;
}
@@ -170,7 +170,7 @@
return new StreamingServiceTransaction(context, wrapper, call);
}
- public class StreamingServiceTransaction extends VoipCallTransaction {
+ public class StreamingServiceTransaction extends CallTransaction {
public static final String MESSAGE = "STREAMING_FAILED_NO_SENDER";
private final TransactionalServiceWrapper mWrapper;
private final Context mContext;
@@ -188,14 +188,14 @@
@SuppressLint("LongLogTag")
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.i(this, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
RoleManager roleManager = mContext.getSystemService(RoleManager.class);
PackageManager packageManager = mContext.getPackageManager();
if (roleManager == null || packageManager == null) {
Log.w(this, "processTransaction: Can't find system service");
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
MESSAGE));
return future;
@@ -205,7 +205,7 @@
RoleManager.ROLE_SYSTEM_CALL_STREAMING, mUserHandle);
if (holders.isEmpty()) {
Log.w(this, "processTransaction: Can't find streaming app");
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
MESSAGE));
return future;
@@ -217,7 +217,7 @@
PackageManager.GET_META_DATA, mUserHandle);
if (infos.isEmpty()) {
Log.w(this, "processTransaction: Can't find streaming service");
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
MESSAGE));
return future;
@@ -229,7 +229,7 @@
Manifest.permission.BIND_CALL_STREAMING_SERVICE)) {
Log.w(this, "Must require BIND_CALL_STREAMING_SERVICE: " +
serviceInfo.packageName);
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
MESSAGE));
return future;
@@ -242,7 +242,7 @@
| Context.BIND_FOREGROUND_SERVICE
| Context.BIND_SCHEDULE_LIKE_TOP_APP, mUserHandle)) {
Log.w(this, "Can't bind to streaming service");
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
"STREAMING_FAILED_SENDER_BINDING_ERROR"));
}
@@ -254,19 +254,19 @@
return new UnbindStreamingServiceTransaction();
}
- public class UnbindStreamingServiceTransaction extends VoipCallTransaction {
+ public class UnbindStreamingServiceTransaction extends CallTransaction {
public UnbindStreamingServiceTransaction() {
super(mTelecomLock);
}
@SuppressLint("LongLogTag")
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.i(this, "processTransaction (unbindStreaming");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
resetController();
- future.complete(new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED,
+ future.complete(new CallTransactionResult(CallTransactionResult.RESULT_SUCCEED,
null));
return future;
}
@@ -275,7 +275,7 @@
public class StartStreamingTransaction extends SerialTransaction {
private Call mCall;
- public StartStreamingTransaction(List<VoipCallTransaction> subTransactions, Call call,
+ public StartStreamingTransaction(List<CallTransaction> subTransactions, Call call,
TelecomSystem.SyncRoot lock) {
super(subTransactions, lock);
mCall = call;
@@ -287,7 +287,7 @@
}
}
- public VoipCallTransaction getStartStreamingTransaction(CallsManager callsManager,
+ public CallTransaction getStartStreamingTransaction(CallsManager callsManager,
TransactionalServiceWrapper wrapper, Call call, TelecomSystem.SyncRoot lock) {
// start streaming transaction flow:
// 1. make sure there's no ongoing streaming call --> bind to EXO
@@ -296,7 +296,7 @@
// If bind to EXO failed, add transaction for stop the streaming
// create list for multiple transactions
- List<VoipCallTransaction> transactions = new ArrayList<>();
+ List<CallTransaction> transactions = new ArrayList<>();
transactions.add(new QueryCallStreamingTransaction(callsManager));
transactions.add(new AudioInterceptionTransaction(call, true, lock));
transactions.add(getCallStreamingServiceTransaction(
@@ -304,10 +304,10 @@
return new StartStreamingTransaction(transactions, call, lock);
}
- public VoipCallTransaction getStopStreamingTransaction(Call call, TelecomSystem.SyncRoot lock) {
+ public CallTransaction getStopStreamingTransaction(Call call, TelecomSystem.SyncRoot lock) {
// TODO: implement this
// Stop streaming transaction flow:
- List<VoipCallTransaction> transactions = new ArrayList<>();
+ List<CallTransaction> transactions = new ArrayList<>();
// 1. unbind to call streaming service
transactions.add(getUnbindStreamingServiceTransaction());
@@ -352,7 +352,7 @@
mTransactionalServiceWrapper.getTransactionManager().addTransaction(transaction,
new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
// ignore
}
@@ -366,7 +366,7 @@
}
}
- private class CallStreamingStateChangeTransaction extends VoipCallTransaction {
+ private class CallStreamingStateChangeTransaction extends CallTransaction {
@StreamingCall.StreamingCallState int mState;
public CallStreamingStateChangeTransaction(@StreamingCall.StreamingCallState int state) {
@@ -375,14 +375,14 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
try {
mService.onCallStreamingStateChanged(mState);
- future.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, null));
+ future.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, null));
} catch (RemoteException e) {
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
"Exception when request "
+ "setting state to streaming app."));
@@ -395,10 +395,10 @@
ServiceConnection {
private Call mCall;
private TransactionalServiceWrapper mWrapper;
- private CompletableFuture<VoipCallTransactionResult> mFuture;
+ private CompletableFuture<CallTransactionResult> mFuture;
public CallStreamingServiceConnection(Call call, TransactionalServiceWrapper wrapper,
- CompletableFuture<VoipCallTransactionResult> future) {
+ CompletableFuture<CallTransactionResult> future) {
mCall = call;
mWrapper = wrapper;
mFuture = future;
@@ -409,11 +409,11 @@
try {
Log.i(this, "onServiceConnected: " + name);
onConnectedInternal(mCall, mWrapper, service);
- mFuture.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, null));
+ mFuture.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, null));
} catch (RemoteException e) {
resetController();
- mFuture.complete(new VoipCallTransactionResult(
+ mFuture.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
StreamingServiceTransaction.MESSAGE));
}
@@ -437,7 +437,7 @@
private void clearBinding() {
resetController();
if (!mFuture.isDone()) {
- mFuture.complete(new VoipCallTransactionResult(
+ mFuture.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /* TODO:: define error b/335703584 */,
"STREAMING_FAILED_SENDER_BINDING_ERROR"));
} else {
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 134bc4f..ab350bc 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -131,8 +131,10 @@
import com.android.server.telecom.callfiltering.IncomingCallFilterGraph;
import com.android.server.telecom.callfiltering.IncomingCallFilterGraphProvider;
import com.android.server.telecom.callredirection.CallRedirectionProcessor;
+import com.android.server.telecom.callsequencing.CallSequencingController;
import com.android.server.telecom.components.ErrorDialogActivity;
import com.android.server.telecom.components.TelecomBroadcastReceiver;
+import com.android.server.telecom.callsequencing.CallsManagerCallSequencingAdapter;
import com.android.server.telecom.flags.FeatureFlags;
import com.android.server.telecom.metrics.ErrorStats;
import com.android.server.telecom.metrics.TelecomMetricsController;
@@ -144,8 +146,8 @@
import com.android.server.telecom.ui.DisconnectedCallNotifier;
import com.android.server.telecom.ui.IncomingCallNotifier;
import com.android.server.telecom.ui.ToastFactory;
-import com.android.server.telecom.voip.VoipCallMonitor;
-import com.android.server.telecom.voip.TransactionManager;
+import com.android.server.telecom.callsequencing.voip.VoipCallMonitor;
+import com.android.server.telecom.callsequencing.TransactionManager;
import java.util.ArrayList;
import java.util.Arrays;
@@ -491,6 +493,7 @@
private final UserManager mUserManager;
private final CallStreamingNotification mCallStreamingNotification;
private final BlockedNumbersManager mBlockedNumbersManager;
+ private final CallsManagerCallSequencingAdapter mCallSequencingAdapter;
private final FeatureFlags mFeatureFlags;
private final com.android.internal.telephony.flags.FeatureFlags mTelephonyFeatureFlags;
@@ -740,6 +743,9 @@
mBlockedNumbersManager = mFeatureFlags.telecomMainlineBlockedNumbersManager()
? mContext.getSystemService(BlockedNumbersManager.class)
: null;
+ mCallSequencingAdapter = new CallsManagerCallSequencingAdapter(this,
+ new CallSequencingController(this, mFeatureFlags.enableCallSequencing()),
+ mFeatureFlags.enableCallSequencing());
if (mFeatureFlags.useImprovedListenerOrder()) {
mListeners.add(mInCallController);
@@ -2083,21 +2089,18 @@
// This future checks the status of existing calls and attempts to make room for the
- // outgoing call. The future returned by the inner method will usually be pre-completed --
- // we only pause here if user interaction is required to disconnect a self-managed call.
- // It runs after the account handle is set, independently of the phone account suggestion
- // future.
- CompletableFuture<Call> makeRoomForCall = setAccountHandle.thenComposeAsync(
+ // outgoing call.
+ CompletableFuture<Boolean> makeRoomForCall = setAccountHandle.thenComposeAsync(
potentialPhoneAccounts -> {
Log.i(CallsManager.this, "make room for outgoing call stage");
if (mMmiUtils.isPotentialInCallMMICode(handle) && !isSelfManaged) {
- return CompletableFuture.completedFuture(finalCall);
+ return CompletableFuture.completedFuture(true);
}
// If a call is being reused, then it has already passed the
// makeRoomForOutgoingCall check once and will fail the second time due to the
// call transitioning into the CONNECTING state.
if (isReusedCall) {
- return CompletableFuture.completedFuture(finalCall);
+ return CompletableFuture.completedFuture(true);
} else {
Call reusableCall = reuseOutgoingCall(handle);
if (reusableCall != null) {
@@ -2124,48 +2127,75 @@
finalCall.getTargetPhoneAccount(), finalCall);
}
finalCall.setStartFailCause(CallFailureCause.IN_EMERGENCY_CALL);
- return CompletableFuture.completedFuture(null);
+ return CompletableFuture.completedFuture(false);
}
- // If we can not supportany more active calls, our options are to move a call
+ // If we can not support any more active calls, our options are to move a call
// to hold, disconnect a call, or cancel this call altogether.
- boolean isRoomForCall = finalCall.isEmergencyCall() ?
- makeRoomForOutgoingEmergencyCall(finalCall) :
- makeRoomForOutgoingCall(finalCall);
- if (!isRoomForCall) {
- Call foregroundCall = getForegroundCall();
- Log.d(CallsManager.this, "No more room for outgoing call %s ", finalCall);
- if (foregroundCall.isSelfManaged()) {
- // If the ongoing call is a self-managed call, then prompt the user to
- // ask if they'd like to disconnect their ongoing call and place the
- // outgoing call.
- Log.i(CallsManager.this, "Prompting user to disconnect "
- + "self-managed call");
- finalCall.setOriginalCallIntent(originalIntent);
- CompletableFuture<Call> completionFuture = new CompletableFuture<>();
- startCallConfirmation(finalCall, completionFuture);
- return completionFuture;
- } else {
- // If the ongoing call is a managed call, we will prevent the outgoing
- // call from dialing.
- if (isConference) {
- notifyCreateConferenceFailed(finalCall.getTargetPhoneAccount(),
- finalCall);
- } else {
- notifyCreateConnectionFailed(
- finalCall.getTargetPhoneAccount(), finalCall);
- }
+ CompletableFuture<Boolean> isRoomForCallFuture =
+ mCallSequencingAdapter.makeRoomForOutgoingCall(
+ finalCall.isEmergencyCall(), finalCall);
+ isRoomForCallFuture.exceptionally((throwable -> {
+ if (throwable != null) {
+ Log.w(CallsManager.this,
+ "Exception thrown in makeRoomForOutgoing*Call, "
+ + "returning false. Ex:" + throwable);
}
- Log.i(CallsManager.this, "Aborting call since there's no room");
+ return false;
+ }));
+ return isRoomForCallFuture;
+ }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.dSMCP", mLock));
+
+ // The future returned by the inner method will usually be pre-completed --
+ // we only pause here if user interaction is required to disconnect a self-managed call.
+ // It runs after the account handle is set, independently of the phone account suggestion
+ // future.
+ CompletableFuture<Call> makeRoomResultHandler = makeRoomForCall
+ .thenComposeAsync((isRoom) -> {
+ // If we have an ongoing emergency call, we would have already notified
+ // connection failure for the new call being placed. Catch this so we don't
+ // resend it again.
+ boolean hasOngoingEmergencyCall = !finalCall.isEmergencyCall()
+ && isInEmergencyCall();
+ if (isRoom) {
+ return CompletableFuture.completedFuture(finalCall);
+ } else if (hasOngoingEmergencyCall) {
return CompletableFuture.completedFuture(null);
}
- return CompletableFuture.completedFuture(finalCall);
- }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.dSMCP", mLock));
+ Call foregroundCall = getForegroundCall();
+ Log.d(CallsManager.this, "No more room for outgoing call %s ",
+ finalCall);
+ if (foregroundCall.isSelfManaged()) {
+ // If the ongoing call is a self-managed call, then prompt the
+ // user to ask if they'd like to disconnect their ongoing call
+ // and place the outgoing call.
+ Log.i(CallsManager.this, "Prompting user to disconnect "
+ + "self-managed call");
+ finalCall.setOriginalCallIntent(originalIntent);
+ CompletableFuture<Call> completionFuture =
+ new CompletableFuture<>();
+ startCallConfirmation(finalCall, completionFuture);
+ return completionFuture;
+ } else {
+ // If the ongoing call is a managed call, we will prevent the
+ // outgoing call from dialing.
+ if (isConference) {
+ notifyCreateConferenceFailed(
+ finalCall.getTargetPhoneAccount(),
+ finalCall);
+ } else {
+ notifyCreateConnectionFailed(
+ finalCall.getTargetPhoneAccount(), finalCall);
+ }
+ }
+ Log.i(CallsManager.this, "Aborting call since there's no room");
+ return CompletableFuture.completedFuture(null);
+ }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.mROC", mLock));
// The outgoing call can be placed, go forward. This future glues together the results of
// the account suggestion stage and the make room for call stage.
CompletableFuture<Pair<Call, List<PhoneAccountSuggestion>>> preSelectStage =
- makeRoomForCall.thenCombine(suggestionFuture, Pair::create);
+ makeRoomResultHandler.thenCombine(suggestionFuture, Pair::create);
mLatestPreAccountSelectionFuture = preSelectStage;
// This future takes the list of suggested accounts and the call and determines if more
@@ -3102,7 +3132,22 @@
public void answerCall(Call call, int videoState) {
if (!mCalls.contains(call)) {
Log.i(this, "Request to answer a non-existent call %s", call);
- } else if (call.isTransactionalCall()) {
+ }
+ mCallSequencingAdapter.answerCall(call, videoState);
+ }
+
+ /**
+ * CS: Hold any existing calls, request focus, and then set the call state to answered state.
+ * <p>
+ * T: Call TransactionalServiceWrapper, which then generates transactions to hold calls
+ * {@link #transactionHoldPotentialActiveCallForNewCall} and then move the active call focus
+ * {@link #requestNewCallFocusAndVerify} and notify the remote VOIP app of the call state
+ * moving to active.
+ * <p>
+ * Note: This is only used when {@link FeatureFlags#enableCallSequencing()} is false.
+ */
+ public void answerCallOld(Call call, int videoState) {
+ if (call.isTransactionalCall()) {
// InCallAdapter is requesting to answer the given transactioanl call. Must get an ack
// from the client via a transaction before answering.
call.answer(videoState);
@@ -3436,10 +3481,10 @@
public void holdCall(Call call) {
if (!mCalls.contains(call)) {
Log.w(this, "Unknown call (%s) asked to be put on hold", call);
- } else {
- Log.d(this, "Putting call on hold: (%s)", call);
- call.hold();
+ return;
}
+ Log.d(this, "Putting call on hold: (%s)", call);
+ mCallSequencingAdapter.holdCall(call);
}
/**
@@ -3451,44 +3496,57 @@
public void unholdCall(Call call) {
if (!mCalls.contains(call)) {
Log.w(this, "Unknown call (%s) asked to be removed from hold", call);
- } else {
- if (getOutgoingCall() != null) {
- Log.w(this, "There is an outgoing call, so it is unable to unhold this call %s",
- call);
- return;
- }
- Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
- String activeCallId = null;
- if (activeCall != null && !activeCall.isLocallyDisconnecting()) {
- activeCallId = activeCall.getId();
- if (canHold(activeCall)) {
- activeCall.hold("Swap to " + call.getId());
- Log.addEvent(activeCall, LogUtils.Events.SWAP, "To " + call.getId());
- Log.addEvent(call, LogUtils.Events.SWAP, "From " + activeCall.getId());
- } else {
- // This call does not support hold. If it is from a different connection
- // service or connection manager, then disconnect it, otherwise invoke
- // call.hold() and allow the connection service or connection manager to handle
- // the situation.
- if (!areFromSameSource(activeCall, call)) {
- if (!activeCall.isEmergencyCall()) {
- activeCall.disconnect("Swap to " + call.getId());
- } else {
- Log.w(this, "unholdCall: % is an emergency call, aborting swap to %s",
- activeCall.getId(), call.getId());
- // Don't unhold the call as requested; we don't want to drop an
- // emergency call.
- return;
- }
+ return;
+ }
+ if (getOutgoingCall() != null) {
+ Log.w(this, "There is an outgoing call, so it is unable to unhold this call %s",
+ call);
+ return;
+ }
+ mCallSequencingAdapter.unholdCall(call);
+ }
+
+ /**
+ * Instructs telecom to hold any ongoing active calls and bring this call to the active state.
+ * <p>
+ * Note: This is only used when {@link FeatureFlags#enableCallSequencing()} is false.
+ */
+ public void unholdCallOld(Call call) {
+ Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
+ String activeCallId = null;
+ if (activeCall != null && !activeCall.isLocallyDisconnecting()) {
+ activeCallId = activeCall.getId();
+ if (canHold(activeCall)) {
+ activeCall.hold("Swap to " + call.getId());
+ Log.addEvent(activeCall, LogUtils.Events.SWAP, "To " + call.getId());
+ Log.addEvent(call, LogUtils.Events.SWAP, "From " + activeCall.getId());
+ } else {
+ // This call does not support hold. If it is from a different connection
+ // service or connection manager, then disconnect it, otherwise invoke
+ // call.hold() and allow the connection service or connection manager to handle
+ // the situation.
+ if (!areFromSameSource(activeCall, call)) {
+ if (!activeCall.isEmergencyCall()) {
+ activeCall.disconnect("Swap to " + call.getId());
} else {
- activeCall.hold("Swap to " + call.getId());
+ Log.w(this, "unholdCall: % is an emergency call, aborting swap to %s",
+ activeCall.getId(), call.getId());
+ // Don't unhold the call as requested; we don't want to drop an
+ // emergency call.
+ return;
}
+ } else {
+ activeCall.hold("Swap to " + call.getId());
}
}
- mConnectionSvrFocusMgr.requestFocus(
- call,
- new RequestCallback(new ActionUnHoldCall(call, activeCallId)));
}
+ requestActionUnholdCall(call, activeCallId);
+ }
+
+ public void requestActionUnholdCall(Call call, String activeCallId) {
+ mConnectionSvrFocusMgr.requestFocus(
+ call,
+ new RequestCallback(new ActionUnHoldCall(call, activeCallId)));
}
@Override
@@ -3857,6 +3915,11 @@
maybeMoveToSpeakerPhone(call);
}
+ void requestFocusActionAnswerCall(Call call, int videoState) {
+ mConnectionSvrFocusMgr.requestFocus(call, new CallsManager.RequestCallback(
+ new CallsManager.ActionAnswerCall(call, videoState)));
+ }
+
/**
* Returns true if the active call is held.
*/
@@ -3998,6 +4061,12 @@
return supportsHold(activeCall) && areFromSameSource(activeCall, call);
}
+ /**
+ * CS: Mark a call as active. If the call is self-mangaed, we will also hold any active call
+ * before moving the self-managed call to active.
+ * <p>
+ * Note: Only used when {@link FeatureFlags#enableCallSequencing()} is false.
+ */
@VisibleForTesting
public void markCallAsActive(Call call) {
Log.i(this, "markCallAsActive, isSelfManaged: " + call.isSelfManaged());
@@ -4032,6 +4101,11 @@
}
}
+ /**
+ * Mark a call as on hold after the hold operation has already completed.
+ * <p>
+ * Note: only used when {@link FeatureFlags#enableCallSequencing()} is false.
+ */
public void markCallAsOnHold(Call call) {
setCallState(call, CallState.ON_HOLD, "on-hold set explicitly");
}
@@ -4207,12 +4281,24 @@
private void doRemoval(Call call) {
call.maybeCleanupHandover();
removeCall(call);
+ boolean isLocallyDisconnecting = mLocallyDisconnectingCalls.contains(call);
+ mLocallyDisconnectingCalls.remove(call);
+ mCallSequencingAdapter.unholdCallForRemoval(call, isLocallyDisconnecting);
+ }
+
+ /**
+ * Move the held call to foreground in the event that there is a held call and the disconnected
+ * call was disconnected locally or the held call has no way to auto-unhold because it does not
+ * support hold capability.
+ * <p>
+ * Note: This is only used when {@link FeatureFlags#enableCallSequencing()} is set to false.
+ */
+ public void maybeMoveHeldCallToForeground(Call removedCall, boolean isLocallyDisconnecting) {
Call foregroundCall = mCallAudioManager.getPossiblyHeldForegroundCall();
- if (mLocallyDisconnectingCalls.contains(call)) {
- boolean isDisconnectingChildCall = call.isDisconnectingChildCall();
- Log.v(this, "performRemoval: isDisconnectingChildCall = "
- + isDisconnectingChildCall + "call -> %s", call);
- mLocallyDisconnectingCalls.remove(call);
+ if (isLocallyDisconnecting) {
+ boolean isDisconnectingChildCall = removedCall.isDisconnectingChildCall();
+ Log.v(this, "maybeMoveHeldCallToForeground: isDisconnectingChildCall = "
+ + isDisconnectingChildCall + "call -> %s", removedCall);
// Auto-unhold the foreground call due to a locally disconnected call, except if the
// call which was disconnected is a member of a conference (don't want to auto
// un-hold the conference if we remove a member of the conference).
@@ -4221,7 +4307,8 @@
// implementations, especially if one is managed and the other is a VoIP CS.
if (!isDisconnectingChildCall && foregroundCall != null
&& foregroundCall.getState() == CallState.ON_HOLD
- && areFromSameSource(foregroundCall, call)) {
+ && areFromSameSource(foregroundCall, removedCall)) {
+
foregroundCall.unhold();
}
} else if (foregroundCall != null &&
@@ -4231,8 +4318,8 @@
// The new foreground call is on hold, however the carrier does not display the hold
// button in the UI. Therefore, we need to auto unhold the held call since the user
// has no means of unholding it themselves.
- Log.i(this, "performRemoval: Auto-unholding held foreground call (call doesn't "
- + "support hold)");
+ Log.i(this, "maybeMoveHeldCallToForeground: Auto-unholding held foreground call (call "
+ + "doesn't support hold)");
foregroundCall.unhold();
}
}
@@ -4456,6 +4543,10 @@
return getFirstCallWithState(null, states);
}
+ public Call getFirstCallWithLiveState() {
+ return getFirstCallWithState(null, LIVE_CALL_STATES);
+ }
+
@VisibleForTesting
public PhoneNumberUtilsAdapter getPhoneNumberUtilsAdapter() {
return mPhoneNumberUtilsAdapter;
@@ -5037,7 +5128,7 @@
return (int) callsStream.count();
}
- private boolean hasMaximumLiveCalls(Call exceptCall) {
+ public boolean hasMaximumLiveCalls(Call exceptCall) {
return MAXIMUM_LIVE_CALLS <= getNumCallsWithState(CALL_FILTER_ALL,
exceptCall, null /* phoneAccountHandle*/, LIVE_CALL_STATES);
}
@@ -5181,6 +5272,14 @@
&& incomingCall.getHandoverSourceCall() == null;
}
+ /**
+ * Make room for a pending outgoing emergency {@link Call}.
+ * <p>
+ * Note: This method is only applicable when {@link FeatureFlags#enableCallSequencing()}
+ * is false.
+ * @param call The new pending outgoing call.
+ * @return true if room was made, false if no room could be made.
+ */
@VisibleForTesting
public boolean makeRoomForOutgoingEmergencyCall(Call emergencyCall) {
// Always disconnect any ringing/incoming calls when an emergency call is placed to minimize
@@ -5347,6 +5446,14 @@
return false;
}
+ /**
+ * Make room for a pending outgoing {@link Call}.
+ * <p>
+ * Note: This method is only applicable when {@link FeatureFlags#enableCallSequencing()}
+ * is false.
+ * @param call The new pending outgoing call.
+ * @return true if room was made, false if no room could be made.
+ */
@VisibleForTesting
public boolean makeRoomForOutgoingCall(Call call) {
// Already room!
@@ -6510,7 +6617,7 @@
call.can(Connection.CAPABILITY_HOLD)) && call.getState() != CallState.DIALING;
}
- private boolean supportsHold(Call call) {
+ public boolean supportsHold(Call call) {
return call.can(Connection.CAPABILITY_SUPPORT_HOLD);
}
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index a2998fb..bda5063 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -1581,8 +1581,16 @@
mHandler.postDelayed(new Runnable("ICC.oDCTP", mLock) {
@Override
public void loggedRun() {
- Log.i(this, "onDisconnectedTonePlaying: unbinding");
- connection.disconnect();
+ Log.i(this, "onDisconnectedTonePlaying: unbinding from BT ICS.");
+ // Prevent unbinding in the case that this is run while another call
+ // has been placed/received. Otherwise, we will early unbind from
+ // the BT ICS and not be able to properly relay call state updates.
+ if (!mBTInCallServiceConnections.containsKey(userHandle)) {
+ connection.disconnect();
+ } else {
+ Log.i(this, "onDisconnectedTonePlaying: Refraining from "
+ + "unbinding BT ICS. Another call is ongoing.");
+ }
}
}.prepare(), mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
mContext.getContentResolver()));
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index f0423c3..796a62b 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -1284,12 +1284,15 @@
boolean isNewAccount;
// add self-managed capability for transactional accounts that are missing it
- if (hasTransactionalCallCapabilities(account) &&
- !account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
+ if (hasTransactionalCallCapabilities(account)
+ && !account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
account = account.toBuilder()
.setCapabilities(account.getCapabilities()
| PhoneAccount.CAPABILITY_SELF_MANAGED)
.build();
+ // Note: below we will automatically remove CAPABILITY_CONNECTION_MANAGER,
+ // CAPABILITY_CALL_PROVIDER, and CAPABILITY_SIM_SUBSCRIPTION if this magically becomes
+ // a self-managed phone account here.
}
PhoneAccount oldAccount = getPhoneAccountUnchecked(account.getAccountHandle());
@@ -1310,6 +1313,12 @@
if (account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
// Turn off bits we don't want to be able to set (TelecomServiceImpl protects against
// this but we'll also prevent it from happening here, just to be safe).
+ if ((account.getCapabilities() & (PhoneAccount.CAPABILITY_CALL_PROVIDER
+ | PhoneAccount.CAPABILITY_CONNECTION_MANAGER
+ | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) > 0) {
+ Log.w(this, "addOrReplacePhoneAccount: attempt to register a "
+ + "VoIP phone account with call provider/cm/sim sub capabilities.");
+ }
int newCapabilities = account.getCapabilities() &
~(PhoneAccount.CAPABILITY_CALL_PROVIDER |
PhoneAccount.CAPABILITY_CONNECTION_MANAGER |
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index e6a6dd6..7ec2687 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -86,11 +86,11 @@
import com.android.server.telecom.metrics.ApiStats;
import com.android.server.telecom.metrics.TelecomMetricsController;
import com.android.server.telecom.settings.BlockedNumbersActivity;
-import com.android.server.telecom.voip.IncomingCallTransaction;
-import com.android.server.telecom.voip.OutgoingCallTransaction;
-import com.android.server.telecom.voip.TransactionManager;
-import com.android.server.telecom.voip.VoipCallTransaction;
-import com.android.server.telecom.voip.VoipCallTransactionResult;
+import com.android.server.telecom.callsequencing.voip.IncomingCallTransaction;
+import com.android.server.telecom.callsequencing.voip.OutgoingCallTransaction;
+import com.android.server.telecom.callsequencing.TransactionManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -192,7 +192,7 @@
extras.putInt(CallAttributes.CALLER_UID_KEY, Binder.getCallingUid());
extras.putInt(CallAttributes.CALLER_PID_KEY, Binder.getCallingPid());
- VoipCallTransaction transaction = null;
+ CallTransaction transaction = null;
// create transaction based on the call direction
switch (callAttributes.getDirection()) {
case DIRECTION_OUTGOING:
@@ -212,7 +212,7 @@
mTransactionManager.addTransaction(transaction, new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
Log.d(TAG, "addCall: onResult");
Call call = result.getCall();
@@ -882,16 +882,20 @@
try {
enforcePhoneAccountModificationForPackage(
account.getAccountHandle().getComponentName().getPackageName());
- if (account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
+ if (account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
+ || (mFeatureFlags.enforceTransactionalExclusivity()
+ && account.hasCapabilities(
+ PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS))) {
enforceRegisterSelfManaged();
if (account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) ||
account.hasCapabilities(
PhoneAccount.CAPABILITY_CONNECTION_MANAGER) ||
account.hasCapabilities(
PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
- throw new SecurityException("Self-managed ConnectionServices " +
- "cannot also be call capable, connection managers, or " +
- "SIM accounts.");
+ throw new SecurityException("Self-managed ConnectionServices and "
+ + "transactional voip apps "
+ + "cannot also be call capable, connection managers, or "
+ + "SIM accounts.");
}
// For self-managed CS, the phone account registrar will override the
@@ -2951,7 +2955,7 @@
});
mTransactionManager = TransactionManager.getInstance();
- mTransactionalServiceRepository = new TransactionalServiceRepository();
+ mTransactionalServiceRepository = new TransactionalServiceRepository(mFeatureFlags);
mBlockedNumbersManager = mFeatureFlags.telecomMainlineBlockedNumbersManager()
? mContext.getSystemService(BlockedNumbersManager.class)
: null;
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 34afdb0..94bea42 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -55,7 +55,7 @@
import com.android.server.telecom.ui.IncomingCallNotifier;
import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
import com.android.server.telecom.ui.ToastFactory;
-import com.android.server.telecom.voip.TransactionManager;
+import com.android.server.telecom.callsequencing.TransactionManager;
import java.io.FileNotFoundException;
import java.io.InputStream;
diff --git a/src/com/android/server/telecom/TransactionalServiceRepository.java b/src/com/android/server/telecom/TransactionalServiceRepository.java
index 793840e..5ae459e 100644
--- a/src/com/android/server/telecom/TransactionalServiceRepository.java
+++ b/src/com/android/server/telecom/TransactionalServiceRepository.java
@@ -20,6 +20,8 @@
import android.telecom.PhoneAccountHandle;
import com.android.internal.telecom.ICallEventCallback;
+import com.android.server.telecom.flags.FeatureFlags;
+import com.android.server.telecom.callsequencing.TransactionManager;
import java.util.HashMap;
import java.util.Map;
@@ -32,8 +34,10 @@
private static final String TAG = TransactionalServiceRepository.class.getSimpleName();
private static final Map<PhoneAccountHandle, TransactionalServiceWrapper> mServiceLookupTable =
new HashMap<>();
+ private final FeatureFlags mFlags;
- public TransactionalServiceRepository() {
+ public TransactionalServiceRepository(FeatureFlags flags) {
+ mFlags = flags;
}
public TransactionalServiceWrapper addNewCallForTransactionalServiceWrapper
@@ -45,7 +49,8 @@
if (!hasExistingServiceWrapper(phoneAccountHandle)) {
Log.d(TAG, "creating a new TSW; handle=[%s]", phoneAccountHandle);
service = new TransactionalServiceWrapper(callEventCallback,
- callsManager, phoneAccountHandle, call, this);
+ callsManager, phoneAccountHandle, call, this,
+ TransactionManager.getInstance(), mFlags.enableCallSequencing());
} else {
Log.d(TAG, "add a new call to an existing TSW; handle=[%s]", phoneAccountHandle);
service = getTransactionalServiceWrapper(phoneAccountHandle);
diff --git a/src/com/android/server/telecom/TransactionalServiceWrapper.java b/src/com/android/server/telecom/TransactionalServiceWrapper.java
index b73de23..cf5ef41 100644
--- a/src/com/android/server/telecom/TransactionalServiceWrapper.java
+++ b/src/com/android/server/telecom/TransactionalServiceWrapper.java
@@ -39,23 +39,18 @@
import com.android.internal.telecom.ICallControl;
import com.android.internal.telecom.ICallEventCallback;
-import com.android.server.telecom.voip.CallEventCallbackAckTransaction;
-import com.android.server.telecom.voip.EndpointChangeTransaction;
-import com.android.server.telecom.voip.HoldCallTransaction;
-import com.android.server.telecom.voip.EndCallTransaction;
-import com.android.server.telecom.voip.MaybeHoldCallForNewCallTransaction;
-import com.android.server.telecom.voip.RequestNewActiveCallTransaction;
-import com.android.server.telecom.voip.SerialTransaction;
-import com.android.server.telecom.voip.SetMuteStateTransaction;
-import com.android.server.telecom.voip.RequestVideoStateTransaction;
-import com.android.server.telecom.voip.TransactionManager;
-import com.android.server.telecom.voip.VoipCallTransaction;
-import com.android.server.telecom.voip.VoipCallTransactionResult;
+import com.android.server.telecom.callsequencing.TransactionalCallSequencingAdapter;
+import com.android.server.telecom.callsequencing.voip.CallEventCallbackAckTransaction;
+import com.android.server.telecom.callsequencing.voip.EndpointChangeTransaction;
+import com.android.server.telecom.callsequencing.voip.SetMuteStateTransaction;
+import com.android.server.telecom.callsequencing.voip.RequestVideoStateTransaction;
+import com.android.server.telecom.callsequencing.TransactionManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Locale;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -73,6 +68,8 @@
public static final String DISCONNECT = "Disconnect";
public static final String START_STREAMING = "StartStreaming";
public static final String REQUEST_VIDEO_STATE = "RequestVideoState";
+ public static final String SET_MUTE_STATE = "SetMuteState";
+ public static final String CALL_ENDPOINT_CHANGE = "CallEndpointChange";
// CallEventCallback : Telecom --> Client (ex. voip app)
public static final String ON_SET_ACTIVE = "onSetActive";
@@ -80,6 +77,7 @@
public static final String ON_ANSWER = "onAnswer";
public static final String ON_DISCONNECT = "onDisconnect";
public static final String ON_STREAMING_STARTED = "onStreamingStarted";
+ public static final String STOP_STREAMING = "stopStreaming";
private final CallsManager mCallsManager;
private final ICallEventCallback mICallEventCallback;
@@ -93,6 +91,7 @@
// needs to be non-final for testing
private TransactionManager mTransactionManager;
private CallStreamingController mStreamingController;
+ private final TransactionalCallSequencingAdapter mCallSequencingAdapter;
// Each TransactionalServiceWrapper should have their own Binder.DeathRecipient to clean up
@@ -108,26 +107,24 @@
public TransactionalServiceWrapper(ICallEventCallback callEventCallback,
CallsManager callsManager, PhoneAccountHandle phoneAccountHandle, Call call,
- TransactionalServiceRepository repo) {
+ TransactionalServiceRepository repo, TransactionManager transactionManager,
+ boolean isCallSequencingEnabled) {
// passed args
mICallEventCallback = callEventCallback;
mCallsManager = callsManager;
mPhoneAccountHandle = phoneAccountHandle;
mTrackedCalls.put(call.getId(), call); // service is now tracking its first call
mRepository = repo;
+ mTransactionManager = transactionManager;
// init instance vars
mPackageName = phoneAccountHandle.getComponentName().getPackageName();
- mTransactionManager = TransactionManager.getInstance();
mStreamingController = mCallsManager.getCallStreamingController();
mLock = mCallsManager.getLock();
+ mCallSequencingAdapter = new TransactionalCallSequencingAdapter(mTransactionManager,
+ mCallsManager, isCallSequencingEnabled);
setDeathRecipient(callEventCallback);
}
- @VisibleForTesting
- public void setTransactionManager(TransactionManager transactionManager) {
- mTransactionManager = transactionManager;
- }
-
public TransactionManager getTransactionManager() {
return mTransactionManager;
}
@@ -170,11 +167,7 @@
}
private void cleanupTransactionalServiceWrapper() {
- for (Call call : mTrackedCalls.values()) {
- mCallsManager.markCallAsDisconnected(call,
- new DisconnectCause(DisconnectCause.ERROR, "process died"));
- mCallsManager.removeCall(call); // This will clear mTrackedCalls && ClientTWS
- }
+ mCallSequencingAdapter.cleanup(mTrackedCalls.values());
}
/***
@@ -184,8 +177,7 @@
*/
private final ICallControl mICallControl = new ICallControl.Stub() {
@Override
- public void setActive(String callId, android.os.ResultReceiver callback)
- throws RemoteException {
+ public void setActive(String callId, android.os.ResultReceiver callback) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSW.sA");
@@ -197,8 +189,8 @@
}
@Override
- public void answer(int videoState, String callId, android.os.ResultReceiver callback)
- throws RemoteException {
+
+ public void answer(int videoState, String callId, android.os.ResultReceiver callback) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSW.a");
@@ -210,8 +202,7 @@
}
@Override
- public void setInactive(String callId, android.os.ResultReceiver callback)
- throws RemoteException {
+ public void setInactive(String callId, android.os.ResultReceiver callback) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSW.sI");
@@ -224,8 +215,7 @@
@Override
public void disconnect(String callId, DisconnectCause disconnectCause,
- android.os.ResultReceiver callback)
- throws RemoteException {
+ android.os.ResultReceiver callback) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSW.d");
@@ -237,12 +227,11 @@
}
@Override
- public void setMuteState(boolean isMuted, android.os.ResultReceiver callback)
- throws RemoteException {
+ public void setMuteState(boolean isMuted, android.os.ResultReceiver callback) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSW.sMS");
- addTransactionsToManager(
+ addTransactionsToManager(SET_MUTE_STATE,
new SetMuteStateTransaction(mCallsManager, isMuted), callback);
} finally {
Binder.restoreCallingIdentity(token);
@@ -251,8 +240,7 @@
}
@Override
- public void startCallStreaming(String callId, android.os.ResultReceiver callback)
- throws RemoteException {
+ public void startCallStreaming(String callId, android.os.ResultReceiver callback) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSW.sCS");
@@ -264,8 +252,7 @@
}
@Override
- public void requestVideoState(int videoState, String callId, ResultReceiver callback)
- throws RemoteException {
+ public void requestVideoState(int videoState, String callId, ResultReceiver callback) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSW.rVS");
@@ -283,27 +270,29 @@
if (call != null) {
switch (action) {
case SET_ACTIVE:
- handleCallControlNewCallFocusTransactions(call, SET_ACTIVE,
- false /* isAnswer */, 0/*VideoState (ignored)*/, callback);
+ mCallSequencingAdapter.setActive(call,
+ getCompleteReceiver(action, callback));
break;
case ANSWER:
- handleCallControlNewCallFocusTransactions(call, ANSWER,
- true /* isAnswer */, (int) objects[0] /*VideoState*/, callback);
+ mCallSequencingAdapter.setAnswered(call, (int) objects[0] /*VideoState*/,
+ getCompleteReceiver(action, callback));
break;
case DISCONNECT:
- addTransactionsToManager(new EndCallTransaction(mCallsManager,
- (DisconnectCause) objects[0], call), callback);
+ DisconnectCause dc = (DisconnectCause) objects[0];
+ mCallSequencingAdapter.setDisconnected(call, dc,
+ getCompleteReceiver(action, callback));
break;
case SET_INACTIVE:
- addTransactionsToManager(
- new HoldCallTransaction(mCallsManager, call), callback);
+ mCallSequencingAdapter.setInactive(call,
+ getCompleteReceiver(action,callback));
break;
case START_STREAMING:
- addTransactionsToManager(mStreamingController.getStartStreamingTransaction(mCallsManager,
- TransactionalServiceWrapper.this, call, mLock), callback);
+ addTransactionsToManager(action,
+ mStreamingController.getStartStreamingTransaction(mCallsManager,
+ TransactionalServiceWrapper.this, call, mLock), callback);
break;
case REQUEST_VIDEO_STATE:
- addTransactionsToManager(
+ addTransactionsToManager(action,
new RequestVideoStateTransaction(mCallsManager, call,
(int) objects[0]), callback);
break;
@@ -321,40 +310,13 @@
}
}
- // The client is request their VoIP call state go ACTIVE/ANSWERED.
- // This request is originating from the VoIP application.
- private void handleCallControlNewCallFocusTransactions(Call call, String action,
- boolean isAnswer, int potentiallyNewVideoState, ResultReceiver callback) {
- mTransactionManager.addTransaction(
- createSetActiveTransactions(call, true /* isCallControlRequest */),
- new OutcomeReceiver<>() {
- @Override
- public void onResult(VoipCallTransactionResult result) {
- Log.i(TAG, String.format(Locale.US,
- "%s: onResult: callId=[%s]", action, call.getId()));
- if (isAnswer) {
- call.setVideoState(potentiallyNewVideoState);
- }
- callback.send(TELECOM_TRANSACTION_SUCCESS, new Bundle());
- }
-
- @Override
- public void onError(CallException exception) {
- Bundle extras = new Bundle();
- extras.putParcelable(TRANSACTION_EXCEPTION_KEY, exception);
- callback.send(exception == null ? CallException.CODE_ERROR_UNKNOWN :
- exception.getCode(), extras);
- }
- });
- }
-
@Override
public void requestCallEndpointChange(CallEndpoint endpoint, ResultReceiver callback) {
long token = Binder.clearCallingIdentity();
try {
Log.startSession("TSW.rCEC");
- addTransactionsToManager(new EndpointChangeTransaction(endpoint, mCallsManager),
- callback);
+ addTransactionsToManager(CALL_ENDPOINT_CHANGE,
+ new EndpointChangeTransaction(endpoint, mCallsManager), callback);
} finally {
Binder.restoreCallingIdentity(token);
Log.endSession();
@@ -384,26 +346,31 @@
}
};
- private void addTransactionsToManager(VoipCallTransaction transaction,
+ private void addTransactionsToManager(String action, CallTransaction transaction,
ResultReceiver callback) {
Log.d(TAG, "addTransactionsToManager");
+ CompletableFuture<Boolean> transactionResult = mTransactionManager
+ .addTransaction(transaction, getCompleteReceiver(action, callback));
+ }
- mTransactionManager.addTransaction(transaction, new OutcomeReceiver<>() {
+ private OutcomeReceiver<CallTransactionResult, CallException> getCompleteReceiver(
+ String action, ResultReceiver callback) {
+ return new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
- Log.d(TAG, "addTransactionsToManager: onResult:");
+ public void onResult(CallTransactionResult result) {
+ Log.d(TAG, "completeReceiver: onResult[" + action + "]:" + result);
callback.send(TELECOM_TRANSACTION_SUCCESS, new Bundle());
}
@Override
public void onError(CallException exception) {
- Log.d(TAG, "addTransactionsToManager: onError");
+ Log.d(TAG, "completeReceiver: onError[" + action + "]" + exception);
Bundle extras = new Bundle();
extras.putParcelable(TRANSACTION_EXCEPTION_KEY, exception);
callback.send(exception == null ? CallException.CODE_ERROR_UNKNOWN :
exception.getCode(), extras);
}
- });
+ };
}
public ICallControl getICallControl() {
@@ -416,89 +383,53 @@
**********************************************************************************************
*/
- public void onSetActive(Call call) {
+ public CompletableFuture<Boolean> onSetActive(Call call) {
+ CallTransaction callTransaction = new CallEventCallbackAckTransaction(
+ mICallEventCallback, ON_SET_ACTIVE, call.getId(), mLock);
+ CompletableFuture<Boolean> onSetActiveFuture;
try {
Log.startSession("TSW.oSA");
Log.d(TAG, String.format(Locale.US, "onSetActive: callId=[%s]", call.getId()));
- handleCallEventCallbackNewFocus(call, ON_SET_ACTIVE, false /*isAnswerRequest*/,
- 0 /*VideoState*/);
+ onSetActiveFuture = mCallSequencingAdapter.onSetActive(call,
+ callTransaction, result ->
+ Log.i(TAG, String.format(Locale.US,
+ "%s: onResult: callId=[%s], result=[%s]", ON_SET_ACTIVE,
+ call.getId(), result)));
} finally {
Log.endSession();
}
+ return onSetActiveFuture;
}
public void onAnswer(Call call, int videoState) {
try {
Log.startSession("TSW.oA");
Log.d(TAG, String.format(Locale.US, "onAnswer: callId=[%s]", call.getId()));
- handleCallEventCallbackNewFocus(call, ON_ANSWER, true /*isAnswerRequest*/,
- videoState /*VideoState*/);
+ mCallSequencingAdapter.onSetAnswered(call, videoState,
+ new CallEventCallbackAckTransaction(mICallEventCallback,
+ ON_ANSWER, call.getId(), videoState, mLock),
+ result -> Log.i(TAG, String.format(Locale.US,
+ "%s: onResult: callId=[%s], result=[%s]",
+ ON_ANSWER, call.getId(), result)));
} finally {
Log.endSession();
}
}
- // handle a CallEventCallback to set a call ACTIVE/ANSWERED. Must get ack from client since the
- // request has come from another source (ex. Android Auto is requesting a call to go active)
- private void handleCallEventCallbackNewFocus(Call call, String action, boolean isAnswerRequest,
- int potentiallyNewVideoState) {
- // save CallsManager state before sending client state changes
- Call foregroundCallBeforeSwap = mCallsManager.getForegroundCall();
- boolean wasActive = foregroundCallBeforeSwap != null && foregroundCallBeforeSwap.isActive();
-
- SerialTransaction serialTransactions = createSetActiveTransactions(call,
- false /* isCallControlRequest */);
- // 3. get ack from client (that the requested call can go active)
- if (isAnswerRequest) {
- serialTransactions.appendTransaction(
- new CallEventCallbackAckTransaction(mICallEventCallback,
- action, call.getId(), potentiallyNewVideoState, mLock));
- } else {
- serialTransactions.appendTransaction(
- new CallEventCallbackAckTransaction(mICallEventCallback,
- action, call.getId(), mLock));
- }
-
- // do CallsManager workload before asking client and
- // reset CallsManager state if client does NOT ack
- mTransactionManager.addTransaction(serialTransactions,
- new OutcomeReceiver<>() {
- @Override
- public void onResult(VoipCallTransactionResult result) {
- Log.i(TAG, String.format(Locale.US,
- "%s: onResult: callId=[%s]", action, call.getId()));
- if (isAnswerRequest) {
- call.setVideoState(potentiallyNewVideoState);
- }
- }
-
- @Override
- public void onError(CallException exception) {
- if (isAnswerRequest) {
- // This also sends the signal to untrack from TSW and the client_TSW
- removeCallFromCallsManager(call,
- new DisconnectCause(DisconnectCause.REJECTED,
- "client rejected to answer the call;"
- + " force disconnecting"));
- } else {
- mCallsManager.markCallAsOnHold(call);
- }
- maybeResetForegroundCall(foregroundCallBeforeSwap, wasActive);
- }
- });
- }
-
-
- public void onSetInactive(Call call) {
+ public CompletableFuture<Boolean> onSetInactive(Call call) {
+ CallTransaction callTransaction = new CallEventCallbackAckTransaction(
+ mICallEventCallback, ON_SET_INACTIVE, call.getId(), mLock);
+ CompletableFuture<Boolean> onSetInactiveFuture;
try {
Log.startSession("TSW.oSI");
Log.i(TAG, String.format(Locale.US, "onSetInactive: callId=[%s]", call.getId()));
- mTransactionManager.addTransaction(
- new CallEventCallbackAckTransaction(mICallEventCallback,
- ON_SET_INACTIVE, call.getId(), mLock), new OutcomeReceiver<>() {
+ onSetInactiveFuture = mCallSequencingAdapter.onSetInactive(call,
+ callTransaction, new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
- mCallsManager.markCallAsOnHold(call);
+ public void onResult(CallTransactionResult result) {
+ Log.i(TAG, String.format(Locale.US, "onSetInactive: callId=[%s]"
+ + ", result=[%s]",
+ call.getId(), result));
}
@Override
@@ -510,30 +441,26 @@
} finally {
Log.endSession();
}
+ return onSetInactiveFuture;
}
- public void onDisconnect(Call call, DisconnectCause cause) {
+ public CompletableFuture<Boolean> onDisconnect(Call call,
+ DisconnectCause cause) {
+ CallTransaction callTransaction = new CallEventCallbackAckTransaction(
+ mICallEventCallback, ON_DISCONNECT, call.getId(), cause, mLock);
+ CompletableFuture<Boolean> onDisconnectFuture;
try {
Log.startSession("TSW.oD");
Log.d(TAG, String.format(Locale.US, "onDisconnect: callId=[%s]", call.getId()));
-
- mTransactionManager.addTransaction(
- new CallEventCallbackAckTransaction(mICallEventCallback, ON_DISCONNECT,
- call.getId(), cause, mLock), new OutcomeReceiver<>() {
- @Override
- public void onResult(VoipCallTransactionResult result) {
- removeCallFromCallsManager(call, cause);
- }
-
- @Override
- public void onError(CallException exception) {
- removeCallFromCallsManager(call, cause);
- }
- }
- );
+ onDisconnectFuture = mCallSequencingAdapter.onSetDisconnected(call, cause,
+ callTransaction,
+ result -> Log.i(TAG, String.format(Locale.US,
+ "%s: onResult: callId=[%s], result=[%s]",
+ ON_DISCONNECT, call.getId(), result)));
} finally {
Log.endSession();
}
+ return onDisconnectFuture;
}
public void onCallStreamingStarted(Call call) {
@@ -546,7 +473,7 @@
new CallEventCallbackAckTransaction(mICallEventCallback, ON_STREAMING_STARTED,
call.getId(), mLock), new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
}
@Override
@@ -641,35 +568,6 @@
** Helpers **
**********************************************************************************************
*/
- private void maybeResetForegroundCall(Call foregroundCallBeforeSwap, boolean wasActive) {
- if (foregroundCallBeforeSwap == null) {
- return;
- }
- if (wasActive && !foregroundCallBeforeSwap.isActive()) {
- mCallsManager.markCallAsActive(foregroundCallBeforeSwap);
- }
- }
-
- private void removeCallFromCallsManager(Call call, DisconnectCause cause) {
- if (cause.getCode() != DisconnectCause.REJECTED) {
- mCallsManager.markCallAsDisconnected(call, cause);
- }
- mCallsManager.removeCall(call);
- }
-
- private SerialTransaction createSetActiveTransactions(Call call, boolean isCallControlRequest) {
- // create list for multiple transactions
- List<VoipCallTransaction> transactions = new ArrayList<>();
-
- // potentially hold the current active call in order to set a new call (active/answered)
- transactions.add(
- new MaybeHoldCallForNewCallTransaction(mCallsManager, call, isCallControlRequest));
- // And request a new focus call update
- transactions.add(new RequestNewActiveCallTransaction(mCallsManager, call));
-
- return new SerialTransaction(transactions, mLock);
- }
-
private void setDeathRecipient(ICallEventCallback callEventCallback) {
try {
callEventCallback.asBinder().linkToDeath(mAppDeathListener, 0);
@@ -720,9 +618,10 @@
public void stopCallStreaming(Call call) {
Log.i(this, "stopCallStreaming; callid=%s", call.getId());
if (call != null && call.isStreaming()) {
- VoipCallTransaction stopStreamingTransaction = mStreamingController
+ CallTransaction stopStreamingTransaction = mStreamingController
.getStopStreamingTransaction(call, mLock);
- addTransactionsToManager(stopStreamingTransaction, new ResultReceiver(null));
+ addTransactionsToManager(STOP_STREAMING, stopStreamingTransaction,
+ new ResultReceiver(null));
}
}
}
diff --git a/src/com/android/server/telecom/callsequencing/CallSequencingController.java b/src/com/android/server/telecom/callsequencing/CallSequencingController.java
new file mode 100644
index 0000000..2f0ae45
--- /dev/null
+++ b/src/com/android/server/telecom/callsequencing/CallSequencingController.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 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.callsequencing;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallsManager;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Controls the sequencing between calls when moving between the user ACTIVE (RINGING/ACTIVE) and
+ * user INACTIVE (INCOMING/HOLD/DISCONNECTED) states.
+ */
+public class CallSequencingController {
+// private final CallsManager mCallsManager;
+ private final TransactionManager mTransactionManager;
+// private final Handler mHandler;
+// private boolean mCallSequencingEnabled;
+
+ public CallSequencingController(CallsManager callsManager, boolean callSequencingEnabled) {
+// mCallsManager = callsManager;
+ mTransactionManager = TransactionManager.getInstance();
+ HandlerThread handlerThread = new HandlerThread(this.toString());
+ handlerThread.start();
+// mHandler = new Handler(handlerThread.getLooper());
+// mCallSequencingEnabled = callSequencingEnabled;
+ }
+
+ public void answerCall(Call incomingCall, int videoState) {
+ // Todo: call sequencing logic (stubbed)
+ }
+
+// private CompletableFuture<Boolean> holdActiveCallForNewCallWithSequencing(Call call) {
+// // Todo: call sequencing logic (stubbed)
+// return null;
+// }
+
+ public void unholdCall(Call call) {
+ // Todo: call sequencing logic (stubbed)
+ }
+
+ public CompletableFuture<Boolean> makeRoomForOutgoingCall(boolean isEmergency, Call call) {
+ // Todo: call sequencing logic (stubbed)
+ return CompletableFuture.completedFuture(true);
+// return isEmergency ? makeRoomForOutgoingEmergencyCall(call) : makeRoomForOutgoingCall(call);
+ }
+
+// private CompletableFuture<Boolean> makeRoomForOutgoingEmergencyCall(Call emergencyCall) {
+// // Todo: call sequencing logic (stubbed)
+// return CompletableFuture.completedFuture(true);
+// }
+
+// private CompletableFuture<Boolean> makeRoomForOutgoingCall(Call call) {
+// // Todo: call sequencing logic (stubbed)
+// return CompletableFuture.completedFuture(true);
+// }
+
+// private void resetProcessingCallSequencing() {
+// mTransactionManager.setProcessingCallSequencing(false);
+// }
+
+ public CompletableFuture<Boolean> disconnectCall() {
+ return CompletableFuture.completedFuture(true);
+ }
+}
diff --git a/src/com/android/server/telecom/voip/VoipCallTransaction.java b/src/com/android/server/telecom/callsequencing/CallTransaction.java
similarity index 85%
rename from src/com/android/server/telecom/voip/VoipCallTransaction.java
rename to src/com/android/server/telecom/callsequencing/CallTransaction.java
index a589a6d..8d7da7c 100644
--- a/src/com/android/server/telecom/voip/VoipCallTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/CallTransaction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing;
import android.os.Handler;
import android.os.HandlerThread;
@@ -34,7 +34,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
-public class VoipCallTransaction {
+public class CallTransaction {
//TODO: add log events
private static final long DEFAULT_TRANSACTION_TIMEOUT_MS = 5000L;
@@ -52,7 +52,7 @@
private long mFinishedTimeNs = -1L;
// If finished, did this transaction finish because it timed out?
private boolean mIsTimedOut = false;
- private VoipCallTransactionResult mTransactionResult = null;
+ private CallTransactionResult mTransactionResult = null;
public Stats() {
addedTimeStamp = LocalDateTime.now();
@@ -70,7 +70,7 @@
/**
* Mark the transaction as completed and record the time.
*/
- public void markComplete(boolean isTimedOut, VoipCallTransactionResult result) {
+ public void markComplete(boolean isTimedOut, CallTransactionResult result) {
if (mFinishedTimeNs > -1) return;
mFinishedTimeNs = System.nanoTime();
mIsTimedOut = isTimedOut;
@@ -124,7 +124,7 @@
* @return the result if the transaction completed, null if it timed out or hasn't completed
* yet.
*/
- public VoipCallTransactionResult getTransactionResult() {
+ public CallTransactionResult getTransactionResult() {
return mTransactionResult;
}
}
@@ -134,13 +134,13 @@
private final HandlerThread mHandlerThread;
protected final Handler mHandler;
protected TransactionManager.TransactionCompleteListener mCompleteListener;
- protected final List<VoipCallTransaction> mSubTransactions;
+ protected final List<CallTransaction> mSubTransactions;
protected final TelecomSystem.SyncRoot mLock;
protected final long mTransactionTimeoutMs;
protected final Stats mStats;
- public VoipCallTransaction(
- List<VoipCallTransaction> subTransactions, TelecomSystem.SyncRoot lock,
+ public CallTransaction(
+ List<CallTransaction> subTransactions, TelecomSystem.SyncRoot lock,
long timeoutMs) {
mSubTransactions = subTransactions;
mHandlerThread = new HandlerThread(this.toString());
@@ -151,15 +151,15 @@
mStats = Flags.enableCallSequencing() ? new Stats() : null;
}
- public VoipCallTransaction(List<VoipCallTransaction> subTransactions,
+ public CallTransaction(List<CallTransaction> subTransactions,
TelecomSystem.SyncRoot lock) {
this(subTransactions, lock, DEFAULT_TRANSACTION_TIMEOUT_MS);
}
- public VoipCallTransaction(TelecomSystem.SyncRoot lock, long timeoutMs) {
+ public CallTransaction(TelecomSystem.SyncRoot lock, long timeoutMs) {
this(null /* mSubTransactions */, lock, timeoutMs);
}
- public VoipCallTransaction(TelecomSystem.SyncRoot lock) {
+ public CallTransaction(TelecomSystem.SyncRoot lock) {
this(null /* mSubTransactions */, lock);
}
@@ -178,7 +178,7 @@
}
/**
- * By default, this processes this transaction. For VoipCallTransactions with sub-transactions,
+ * By default, this processes this transaction. For CallTransaction with sub-transactions,
* this implementation should be overwritten to handle also processing sub-transactions.
*/
protected void processTransactions() {
@@ -187,7 +187,7 @@
/**
* This method is called when the transaction has finished either successfully or exceptionally.
- * VoipCallTransactions that are extending this class should override this method to clean up
+ * CallTransaction that are extending this class should override this method to clean up
* any leftover state.
*/
protected void finishTransaction() {
@@ -199,7 +199,7 @@
mTransactionName + "@" + hashCode() + ".sT", mLock);
CompletableFuture<Void> future = CompletableFuture.completedFuture(null);
future.thenComposeAsync(this::processTransaction, executor)
- .thenApplyAsync((Function<VoipCallTransactionResult, Void>) result -> {
+ .thenApplyAsync((Function<CallTransactionResult, Void>) result -> {
notifyListenersOfResult(result);
return null;
}, executor)
@@ -208,14 +208,14 @@
// Instead, propagate the failure to the other transactions immediately!
String errorMessage = throwable != null ? throwable.getMessage() :
"encountered an exception while processing " + mTransactionName;
- notifyListenersOfResult(new VoipCallTransactionResult(
+ notifyListenersOfResult(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN, errorMessage));
Log.e(this, throwable, "Error while executing transaction.");
return null;
}));
}
- protected void notifyListenersOfResult(VoipCallTransactionResult result){
+ protected void notifyListenersOfResult(CallTransactionResult result){
mCompleted.set(true);
finish(result);
if (mCompleteListener != null) {
@@ -223,9 +223,9 @@
}
}
- protected CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ protected CompletionStage<CallTransactionResult> processTransaction(Void v) {
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED, null));
+ new CallTransactionResult(CallTransactionResult.RESULT_SUCCEED, null));
}
public final void setCompleteListener(TransactionManager.TransactionCompleteListener listener) {
@@ -248,11 +248,11 @@
return mHandler;
}
- public final void finish(VoipCallTransactionResult result) {
+ public final void finish(CallTransactionResult result) {
finish(false, result);
}
- private void finish(boolean isTimedOut, VoipCallTransactionResult result) {
+ private void finish(boolean isTimedOut, CallTransactionResult result) {
if (mStats != null) mStats.markComplete(isTimedOut, result);
finishTransaction();
// finish all sub transactions
diff --git a/src/com/android/server/telecom/voip/VoipCallTransactionResult.java b/src/com/android/server/telecom/callsequencing/CallTransactionResult.java
similarity index 66%
rename from src/com/android/server/telecom/voip/VoipCallTransactionResult.java
rename to src/com/android/server/telecom/callsequencing/CallTransactionResult.java
index 50871f2..8b5f5bf 100644
--- a/src/com/android/server/telecom/voip/VoipCallTransactionResult.java
+++ b/src/com/android/server/telecom/callsequencing/CallTransactionResult.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -14,33 +14,38 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing;
import com.android.server.telecom.Call;
import java.util.Objects;
-public class VoipCallTransactionResult {
+public class CallTransactionResult {
public static final int RESULT_SUCCEED = 0;
+ private static final String VOIP_TRANSACTION_TAG = "VoipCallTransactionResult";
+ private static final String PSTN_TRANSACTION_TAG = "PstnTransactionResult";
- // NOTE: if the VoipCallTransactionResult should not use the RESULT_SUCCEED to represent a
+ // NOTE: if the CallTransactionResult should not use the RESULT_SUCCEED to represent a
// successful transaction, use an error code defined in the
// {@link android.telecom.CallException} class
private final int mResult;
private final String mMessage;
private final Call mCall;
+ private final String mCallType;
- public VoipCallTransactionResult(int result, String message) {
+ public CallTransactionResult(int result, String message) {
mResult = result;
mMessage = message;
mCall = null;
+ mCallType = "";
}
- public VoipCallTransactionResult(int result, Call call, String message) {
+ public CallTransactionResult(int result, Call call, String message, boolean isVoip) {
mResult = result;
mCall = call;
mMessage = message;
+ mCallType = isVoip ? VOIP_TRANSACTION_TAG : PSTN_TRANSACTION_TAG;
}
public int getResult() {
@@ -58,8 +63,8 @@
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (!(o instanceof VoipCallTransactionResult)) return false;
- VoipCallTransactionResult that = (VoipCallTransactionResult) o;
+ if (!(o instanceof CallTransactionResult)) return false;
+ CallTransactionResult that = (CallTransactionResult) o;
return mResult == that.mResult && Objects.equals(mMessage, that.mMessage);
}
@@ -71,7 +76,9 @@
@Override
public String toString() {
return new StringBuilder().
- append("{ VoipCallTransactionResult: [mResult: ").
+ append("{ ").
+ append(mCallType).
+ append(": [mResult: ").
append(mResult).
append("], [mCall: ").
append((mCall != null) ? mCall : "null").
diff --git a/src/com/android/server/telecom/callsequencing/CallsManagerCallSequencingAdapter.java b/src/com/android/server/telecom/callsequencing/CallsManagerCallSequencingAdapter.java
new file mode 100644
index 0000000..8410c54
--- /dev/null
+++ b/src/com/android/server/telecom/callsequencing/CallsManagerCallSequencingAdapter.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 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.callsequencing;
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallsManager;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Abstraction layer for CallsManager to perform call sequencing operations through CallsManager
+ * or CallSequencingController, which is controlled by {@link FeatureFlags#enableCallSequencing()}.
+ */
+public class CallsManagerCallSequencingAdapter {
+
+ private final CallsManager mCallsManager;
+ private final CallSequencingController mSequencingController;
+ private final boolean mIsCallSequencingEnabled;
+
+ public CallsManagerCallSequencingAdapter(CallsManager callsManager,
+ CallSequencingController sequencingController,
+ boolean isCallSequencingEnabled) {
+ mCallsManager = callsManager;
+ mSequencingController = sequencingController;
+ mIsCallSequencingEnabled = isCallSequencingEnabled;
+ }
+
+ public void answerCall(Call incomingCall, int videoState) {
+ if (mIsCallSequencingEnabled && !incomingCall.isTransactionalCall()) {
+ mSequencingController.answerCall(incomingCall, videoState);
+ } else {
+ mCallsManager.answerCallOld(incomingCall, videoState);
+ }
+ }
+
+ public void unholdCall(Call call) {
+ if (mIsCallSequencingEnabled) {
+ mSequencingController.unholdCall(call);
+ } else {
+ mCallsManager.unholdCallOld(call);
+ }
+ }
+
+ public void holdCall(Call call) {
+ // Sequencing already taken care of for CSW/TSW in Call class.
+ call.hold();
+ }
+
+ public void unholdCallForRemoval(Call removedCall,
+ boolean isLocallyDisconnecting) {
+ // Todo: confirm verification of disconnect logic
+ // Sequencing already taken care of for CSW/TSW in Call class.
+ mCallsManager.maybeMoveHeldCallToForeground(removedCall, isLocallyDisconnecting);
+ }
+
+ public CompletableFuture<Boolean> makeRoomForOutgoingCall(boolean isEmergency, Call call) {
+ if (mIsCallSequencingEnabled) {
+ return mSequencingController.makeRoomForOutgoingCall(isEmergency, call);
+ } else {
+ return isEmergency
+ ? CompletableFuture.completedFuture(
+ makeRoomForOutgoingEmergencyCallFlagOff(call))
+ : CompletableFuture.completedFuture(makeRoomForOutgoingCallFlagOff(call));
+ }
+ }
+
+ private boolean makeRoomForOutgoingCallFlagOff(Call call) {
+ return mCallsManager.makeRoomForOutgoingCall(call);
+ }
+
+ private boolean makeRoomForOutgoingEmergencyCallFlagOff(Call call) {
+ return mCallsManager.makeRoomForOutgoingEmergencyCall(call);
+ }
+}
diff --git a/src/com/android/server/telecom/voip/TransactionManager.java b/src/com/android/server/telecom/callsequencing/TransactionManager.java
similarity index 76%
rename from src/com/android/server/telecom/voip/TransactionManager.java
rename to src/com/android/server/telecom/callsequencing/TransactionManager.java
index 0086d07..a3b3828 100644
--- a/src/com/android/server/telecom/voip/TransactionManager.java
+++ b/src/com/android/server/telecom/callsequencing/TransactionManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing;
import static android.telecom.CallException.CODE_OPERATION_TIMED_OUT;
@@ -32,18 +32,20 @@
import java.util.List;
import java.util.Locale;
import java.util.Queue;
+import java.util.concurrent.CompletableFuture;
public class TransactionManager {
- private static final String TAG = "VoipCallTransactionManager";
+ private static final String TAG = "CallTransactionManager";
private static final int TRANSACTION_HISTORY_SIZE = 20;
private static TransactionManager INSTANCE = null;
private static final Object sLock = new Object();
- private final Queue<VoipCallTransaction> mTransactions;
- private final Deque<VoipCallTransaction> mCompletedTransactions;
- private VoipCallTransaction mCurrentTransaction;
+ private final Queue<CallTransaction> mTransactions;
+ private final Deque<CallTransaction> mCompletedTransactions;
+ private CallTransaction mCurrentTransaction;
+ private boolean mProcessingCallSequencing;
public interface TransactionCompleteListener {
- void onTransactionCompleted(VoipCallTransactionResult result, String transactionName);
+ void onTransactionCompleted(CallTransactionResult result, String transactionName);
void onTransactionTimeout(String transactionName);
}
@@ -70,28 +72,32 @@
return new TransactionManager();
}
- public void addTransaction(VoipCallTransaction transaction,
- OutcomeReceiver<VoipCallTransactionResult, CallException> receiver) {
+ public CompletableFuture<Boolean> addTransaction(CallTransaction transaction,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ CompletableFuture<Boolean> transactionCompleteFuture = new CompletableFuture<>();
synchronized (sLock) {
mTransactions.add(transaction);
}
transaction.setCompleteListener(new TransactionCompleteListener() {
@Override
- public void onTransactionCompleted(VoipCallTransactionResult result,
+ public void onTransactionCompleted(CallTransactionResult result,
String transactionName) {
Log.i(TAG, String.format("transaction %s completed: with result=[%d]",
transactionName, result.getResult()));
try {
if (result.getResult() == TelecomManager.TELECOM_TRANSACTION_SUCCESS) {
receiver.onResult(result);
+ transactionCompleteFuture.complete(true);
} else {
receiver.onError(
new CallException(result.getMessage(),
result.getResult()));
+ transactionCompleteFuture.complete(false);
}
} catch (Exception e) {
Log.e(TAG, String.format("onTransactionCompleted: Notifying transaction result"
+ " %s resulted in an Exception.", result), e);
+ transactionCompleteFuture.complete(false);
}
finishTransaction();
}
@@ -102,15 +108,18 @@
try {
receiver.onError(new CallException(transactionName + " timeout",
CODE_OPERATION_TIMED_OUT));
+ transactionCompleteFuture.complete(false);
} catch (Exception e) {
Log.e(TAG, String.format("onTransactionTimeout: Notifying transaction "
+ " %s resulted in an Exception.", transactionName), e);
+ transactionCompleteFuture.complete(false);
}
finishTransaction();
}
});
startTransactions();
+ return transactionCompleteFuture;
}
private void startTransactions() {
@@ -141,17 +150,17 @@
@VisibleForTesting
public void clear() {
- List<VoipCallTransaction> pendingTransactions;
+ List<CallTransaction> pendingTransactions;
synchronized (sLock) {
pendingTransactions = new ArrayList<>(mTransactions);
}
- for (VoipCallTransaction t : pendingTransactions) {
- t.finish(new VoipCallTransactionResult(CallException.CODE_ERROR_UNKNOWN
+ for (CallTransaction t : pendingTransactions) {
+ t.finish(new CallTransactionResult(CallException.CODE_ERROR_UNKNOWN
/* TODO:: define error b/335703584 */, "clear called"));
}
}
- private void addTransactionToHistory(VoipCallTransaction t) {
+ private void addTransactionToHistory(CallTransaction t) {
if (!Flags.enableCallSequencing()) return;
mCompletedTransactions.add(t);
@@ -160,6 +169,14 @@
}
}
+ public void setProcessingCallSequencing(boolean processingCallSequencing) {
+ mProcessingCallSequencing = processingCallSequencing;
+ }
+
+ public boolean isProcessingCallSequencing() {
+ return mProcessingCallSequencing;
+ }
+
/**
* Called when the dumpsys is created for telecom to capture the current state.
*/
@@ -171,7 +188,7 @@
synchronized (sLock) {
pw.println("Pending Transactions:");
pw.increaseIndent();
- for (VoipCallTransaction t : mTransactions) {
+ for (CallTransaction t : mTransactions) {
printPendingTransactionStats(t, pw);
}
pw.decreaseIndent();
@@ -185,7 +202,7 @@
pw.println("Completed Transactions:");
pw.increaseIndent();
- for (VoipCallTransaction t : mCompletedTransactions) {
+ for (CallTransaction t : mCompletedTransactions) {
printCompleteTransactionStats(t, pw);
}
pw.decreaseIndent();
@@ -193,12 +210,12 @@
}
/**
- * Recursively print the pending {@link VoipCallTransaction} stats for logging purposes.
+ * Recursively print the pending {@link CallTransaction} stats for logging purposes.
* @param t The transaction that stats should be printed for
* @param pw The IndentingPrintWriter to print the result to
*/
- private void printPendingTransactionStats(VoipCallTransaction t, IndentingPrintWriter pw) {
- VoipCallTransaction.Stats s = t.getStats();
+ private void printPendingTransactionStats(CallTransaction t, IndentingPrintWriter pw) {
+ CallTransaction.Stats s = t.getStats();
if (s == null) {
pw.println(String.format(Locale.getDefault(), "%s: <NO STATS>", t.mTransactionName));
return;
@@ -215,7 +232,7 @@
return;
}
pw.increaseIndent();
- for (VoipCallTransaction subTransaction : t.mSubTransactions) {
+ for (CallTransaction subTransaction : t.mSubTransactions) {
printPendingTransactionStats(subTransaction, pw);
}
pw.decreaseIndent();
@@ -226,8 +243,8 @@
* @param t The transaction that stats should be printed for
* @param pw The IndentingPrintWriter to print the result to
*/
- private void printCompleteTransactionStats(VoipCallTransaction t, IndentingPrintWriter pw) {
- VoipCallTransaction.Stats s = t.getStats();
+ private void printCompleteTransactionStats(CallTransaction t, IndentingPrintWriter pw) {
+ CallTransaction.Stats s = t.getStats();
if (s == null) {
pw.println(String.format(Locale.getDefault(), "%s: <NO STATS>", t.mTransactionName));
return;
@@ -242,16 +259,16 @@
return;
}
pw.increaseIndent();
- for (VoipCallTransaction subTransaction : t.mSubTransactions) {
+ for (CallTransaction subTransaction : t.mSubTransactions) {
printCompleteTransactionStats(subTransaction, pw);
}
pw.decreaseIndent();
}
- private String parseTransactionResult(VoipCallTransaction.Stats s) {
+ private String parseTransactionResult(CallTransaction.Stats s) {
if (s.isTimedOut()) return "TIMED OUT";
if (s.getTransactionResult() == null) return "PENDING";
- if (s.getTransactionResult().getResult() == VoipCallTransactionResult.RESULT_SUCCEED) {
+ if (s.getTransactionResult().getResult() == CallTransactionResult.RESULT_SUCCEED) {
return "SUCCESS";
}
return s.getTransactionResult().toString();
diff --git a/src/com/android/server/telecom/callsequencing/TransactionalCallSequencingAdapter.java b/src/com/android/server/telecom/callsequencing/TransactionalCallSequencingAdapter.java
new file mode 100644
index 0000000..7c8bbe4
--- /dev/null
+++ b/src/com/android/server/telecom/callsequencing/TransactionalCallSequencingAdapter.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2024 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.callsequencing;
+
+import android.os.OutcomeReceiver;
+import android.telecom.CallException;
+import android.telecom.DisconnectCause;
+
+import com.android.server.telecom.Call;
+import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.callsequencing.voip.EndCallTransaction;
+import com.android.server.telecom.callsequencing.voip.HoldCallTransaction;
+import com.android.server.telecom.callsequencing.voip.MaybeHoldCallForNewCallTransaction;
+import com.android.server.telecom.callsequencing.voip.RequestNewActiveCallTransaction;
+import com.android.server.telecom.callsequencing.voip.SerialTransaction;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Helper adapter class used to centralized code that will be affected by toggling the
+ * {@link Flags#enableCallSequencing()} flag.
+ */
+public class TransactionalCallSequencingAdapter {
+ private final TransactionManager mTransactionManager;
+ private final CallsManager mCallsManager;
+// private final boolean mIsCallSequencingEnabled;
+
+ public TransactionalCallSequencingAdapter(TransactionManager transactionManager,
+ CallsManager callsManager, boolean isCallSequencingEnabled) {
+ mTransactionManager = transactionManager;
+ mCallsManager = callsManager;
+ // TODO implement call sequencing changes
+// mIsCallSequencingEnabled = isCallSequencingEnabled;
+ }
+
+ /**
+ * Client -> Server request to set a call active
+ */
+ public void setActive(Call call,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ setActiveFlagOff(call, receiver);
+ }
+
+ /**
+ * Client -> Server request to answer a call
+ */
+ public void setAnswered(Call call, int newVideoState,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ setAnsweredFlagOff(call, newVideoState, receiver);
+ }
+
+ /**
+ * Client -> Server request to set a call to disconnected
+ */
+ public void setDisconnected(Call call, DisconnectCause dc,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ setDisconnectedFlagOff(call, dc, receiver);
+ }
+
+ /**
+ * Client -> Server request to set a call to inactive
+ */
+ public void setInactive(Call call,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ setInactiveFlagOff(call, receiver);
+ }
+
+ /**
+ * Server -> Client command to set the call active, which if it fails, will try to reset the
+ * state to what it was before the call was set to active.
+ */
+ public CompletableFuture<Boolean> onSetActive(Call call,
+ CallTransaction clientCbT,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ return onSetActiveFlagOff(call, clientCbT, receiver);
+ }
+
+ /**
+ * Server -> Client command to answer an incoming call, which if it fails, will trigger the
+ * disconnect of the call and then reset the state of the other call back to what it was before.
+ */
+ public void onSetAnswered(Call call, int videoState, CallTransaction clientCbT,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ onSetAnsweredFlagOff(call, videoState, clientCbT, receiver);
+ }
+
+ /**
+ * Server -> Client command to set the call as inactive
+ */
+ public CompletableFuture<Boolean> onSetInactive(Call call,
+ CallTransaction clientCbT,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ return onSetInactiveFlagOff(call, clientCbT, receiver);
+ }
+
+ /**
+ * Server -> Client command to disconnect the call
+ */
+ public CompletableFuture<Boolean> onSetDisconnected(Call call,
+ DisconnectCause dc, CallTransaction clientCbT, OutcomeReceiver<CallTransactionResult,
+ CallException> receiver) {
+ return onSetDisconnectedFlagOff(call, dc, clientCbT, receiver);
+ }
+
+ /**
+ * Clean up the calls that have been passed in from CallsManager
+ */
+ public void cleanup(Collection<Call> calls) {
+ cleanupFlagOff(calls);
+ }
+
+ private void setActiveFlagOff(Call call,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ CompletableFuture<Boolean> transactionResult = mTransactionManager
+ .addTransaction(createSetActiveTransactions(call,
+ true /* callControlRequest */), receiver);
+ }
+
+ private void setAnsweredFlagOff(Call call, int newVideoState,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ CompletableFuture<Boolean> transactionResult = mTransactionManager
+ .addTransaction(createSetActiveTransactions(call,
+ true /* callControlRequest */),
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(CallTransactionResult callTransactionResult) {
+ call.setVideoState(newVideoState);
+ receiver.onResult(callTransactionResult);
+ }
+
+ @Override
+ public void onError(CallException error) {
+ receiver.onError(error);
+ }
+ });
+ }
+
+ private void setDisconnectedFlagOff(Call call, DisconnectCause dc,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ CompletableFuture<Boolean> transactionResult = mTransactionManager
+ .addTransaction(new EndCallTransaction(mCallsManager,
+ dc, call), receiver);
+ }
+
+ private void setInactiveFlagOff(Call call,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ CompletableFuture<Boolean> transactionResult = mTransactionManager
+ .addTransaction(new HoldCallTransaction(mCallsManager,call), receiver);
+ }
+
+ private CompletableFuture<Boolean> onSetActiveFlagOff(Call call,
+ CallTransaction clientCbT,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ // save CallsManager state before sending client state changes
+ Call foregroundCallBeforeSwap = mCallsManager.getForegroundCall();
+ boolean wasActive = foregroundCallBeforeSwap != null && foregroundCallBeforeSwap.isActive();
+ SerialTransaction serialTransactions = createSetActiveTransactions(call,
+ false /* callControlRequest */);
+ serialTransactions.appendTransaction(clientCbT);
+ // do CallsManager workload before asking client and
+ // reset CallsManager state if client does NOT ack
+ return mTransactionManager.addTransaction(
+ serialTransactions,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(CallTransactionResult result) {
+ receiver.onResult(result);
+ }
+
+ @Override
+ public void onError(CallException exception) {
+ mCallsManager.markCallAsOnHold(call);
+ maybeResetForegroundCall(foregroundCallBeforeSwap, wasActive);
+ receiver.onError(exception);
+ }
+ });
+ }
+
+ private void onSetAnsweredFlagOff(Call call, int videoState, CallTransaction clientCbT,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ // save CallsManager state before sending client state changes
+ Call foregroundCallBeforeSwap = mCallsManager.getForegroundCall();
+ boolean wasActive = foregroundCallBeforeSwap != null && foregroundCallBeforeSwap.isActive();
+ SerialTransaction serialTransactions = createSetActiveTransactions(call,
+ false /* callControlRequest */);
+ serialTransactions.appendTransaction(clientCbT);
+ // do CallsManager workload before asking client and
+ // reset CallsManager state if client does NOT ack
+ CompletableFuture<Boolean> transactionResult = mTransactionManager
+ .addTransaction(serialTransactions,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(CallTransactionResult result) {
+ call.setVideoState(videoState);
+ receiver.onResult(result);
+ }
+
+ @Override
+ public void onError(CallException exception) {
+ // This also sends the signal to untrack from TSW and the client_TSW
+ removeCallFromCallsManager(call,
+ new DisconnectCause(DisconnectCause.REJECTED,
+ "client rejected to answer the call;"
+ + " force disconnecting"));
+ maybeResetForegroundCall(foregroundCallBeforeSwap, wasActive);
+ receiver.onError(exception);
+ }
+ });
+ }
+
+ private CompletableFuture<Boolean> onSetInactiveFlagOff(Call call,
+ CallTransaction clientCbT,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ return mTransactionManager.addTransaction(clientCbT,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(CallTransactionResult callTransactionResult) {
+ mCallsManager.markCallAsOnHold(call);
+ receiver.onResult(callTransactionResult);
+ }
+
+ @Override
+ public void onError(CallException error) {
+ receiver.onError(error);
+ }
+ });
+ }
+
+ /**
+ * Server -> Client command to disconnect the call
+ */
+ private CompletableFuture<Boolean> onSetDisconnectedFlagOff(Call call,
+ DisconnectCause dc, CallTransaction clientCbT,
+ OutcomeReceiver<CallTransactionResult, CallException> receiver) {
+ return mTransactionManager.addTransaction(clientCbT,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(CallTransactionResult result) {
+ removeCallFromCallsManager(call, dc);
+ receiver.onResult(result);
+ }
+
+ @Override
+ public void onError(CallException exception) {
+ removeCallFromCallsManager(call, dc);
+ receiver.onError(exception);
+ }
+ }
+ );
+ }
+
+ private SerialTransaction createSetActiveTransactions(Call call, boolean isCallControlRequest) {
+ // create list for multiple transactions
+ List<CallTransaction> transactions = new ArrayList<>();
+
+ // potentially hold the current active call in order to set a new call (active/answered)
+ transactions.add(new MaybeHoldCallForNewCallTransaction(mCallsManager, call,
+ isCallControlRequest));
+ // And request a new focus call update
+ transactions.add(new RequestNewActiveCallTransaction(mCallsManager, call));
+
+ return new SerialTransaction(transactions, mCallsManager.getLock());
+ }
+
+ private void removeCallFromCallsManager(Call call, DisconnectCause cause) {
+ if (cause.getCode() != DisconnectCause.REJECTED) {
+ mCallsManager.markCallAsDisconnected(call, cause);
+ }
+ mCallsManager.removeCall(call);
+ }
+
+ private void maybeResetForegroundCall(Call foregroundCallBeforeSwap, boolean wasActive) {
+ if (foregroundCallBeforeSwap == null) {
+ return;
+ }
+ if (wasActive && !foregroundCallBeforeSwap.isActive()) {
+ mCallsManager.markCallAsActive(foregroundCallBeforeSwap);
+ }
+ }
+ private void cleanupFlagOff(Collection<Call> calls) {
+ for (Call call : calls) {
+ mCallsManager.markCallAsDisconnected(call,
+ new DisconnectCause(DisconnectCause.ERROR, "process died"));
+ mCallsManager.removeCall(call); // This will clear mTrackedCalls && ClientTWS
+ }
+ }
+}
diff --git a/src/com/android/server/telecom/voip/VerifyCallStateChangeTransaction.java b/src/com/android/server/telecom/callsequencing/VerifyCallStateChangeTransaction.java
similarity index 69%
rename from src/com/android/server/telecom/voip/VerifyCallStateChangeTransaction.java
rename to src/com/android/server/telecom/callsequencing/VerifyCallStateChangeTransaction.java
index 5de4b1d..82b32fb 100644
--- a/src/com/android/server/telecom/voip/VerifyCallStateChangeTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/VerifyCallStateChangeTransaction.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.telecom.Call;
@@ -22,8 +22,11 @@
import android.telecom.Log;
+import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
/**
* VerifyCallStateChangeTransaction is a transaction that verifies a CallState change and has
@@ -31,21 +34,22 @@
* <p>
* Note: This transaction has a timeout of 2 seconds.
*/
-public class VerifyCallStateChangeTransaction extends VoipCallTransaction {
+public class VerifyCallStateChangeTransaction extends CallTransaction {
private static final String TAG = VerifyCallStateChangeTransaction.class.getSimpleName();
private static final long CALL_STATE_TIMEOUT_MILLISECONDS = 2000L;
private final Call mCall;
- private final int mTargetCallState;
- private final CompletableFuture<VoipCallTransactionResult> mTransactionResult =
+ private final Set<Integer> mTargetCallStates;
+ private final CompletableFuture<CallTransactionResult> mTransactionResult =
new CompletableFuture<>();
private final Call.CallStateListener mCallStateListenerImpl = new Call.CallStateListener() {
@Override
public void onCallStateChanged(int newCallState) {
- Log.d(TAG, "newState=[%d], expectedState=[%d]", newCallState, mTargetCallState);
- if (newCallState == mTargetCallState) {
- mTransactionResult.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, TAG));
+ Log.d(TAG, "newState=[%d], possible expected state(s)=[%s]", newCallState,
+ mTargetCallStates);
+ if (mTargetCallStates.contains(newCallState)) {
+ mTransactionResult.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, TAG));
}
// NOTE:: keep listening to the call state until the timeout is reached. It's possible
// another call state is reached in between...
@@ -53,19 +57,19 @@
};
public VerifyCallStateChangeTransaction(TelecomSystem.SyncRoot lock, Call call,
- int targetCallState) {
+ int... targetCallStates) {
super(lock, CALL_STATE_TIMEOUT_MILLISECONDS);
mCall = call;
- mTargetCallState = targetCallState;
+ mTargetCallStates = IntStream.of(targetCallStates).boxed().collect(Collectors.toSet());;
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction:");
// It's possible the Call is already in the expected call state
if (isNewCallStateTargetCallState()) {
- mTransactionResult.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, TAG));
+ mTransactionResult.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, TAG));
return mTransactionResult;
}
mCall.addCallStateListener(mCallStateListenerImpl);
@@ -78,11 +82,11 @@
}
private boolean isNewCallStateTargetCallState() {
- return mCall.getState() == mTargetCallState;
+ return mTargetCallStates.contains(mCall.getState());
}
@VisibleForTesting
- public CompletableFuture<VoipCallTransactionResult> getTransactionResult() {
+ public CompletableFuture<CallTransactionResult> getTransactionResult() {
return mTransactionResult;
}
diff --git a/src/com/android/server/telecom/voip/CallEventCallbackAckTransaction.java b/src/com/android/server/telecom/callsequencing/voip/CallEventCallbackAckTransaction.java
similarity index 90%
rename from src/com/android/server/telecom/voip/CallEventCallbackAckTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/CallEventCallbackAckTransaction.java
index 9e140a7..802ea7e 100644
--- a/src/com/android/server/telecom/voip/CallEventCallbackAckTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/CallEventCallbackAckTransaction.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import static android.telecom.TelecomManager.TELECOM_TRANSACTION_SUCCESS;
import static android.telecom.CallException.CODE_OPERATION_TIMED_OUT;
@@ -29,6 +29,8 @@
import com.android.internal.telecom.ICallEventCallback;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.TransactionalServiceWrapper;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
@@ -39,7 +41,7 @@
* SRP: using the ICallEventCallback binder, reach out to the client for the pending call event and
* get an acknowledgement that the call event can be completed.
*/
-public class CallEventCallbackAckTransaction extends VoipCallTransaction {
+public class CallEventCallbackAckTransaction extends CallTransaction {
private static final String TAG = CallEventCallbackAckTransaction.class.getSimpleName();
private final ICallEventCallback mICallEventCallback;
private final String mAction;
@@ -48,7 +50,7 @@
private int mVideoState = CallAttributes.AUDIO_CALL;
private DisconnectCause mDisconnectCause = null;
- private final VoipCallTransactionResult TRANSACTION_FAILED = new VoipCallTransactionResult(
+ private final CallTransactionResult TRANSACTION_FAILED = new CallTransactionResult(
CODE_OPERATION_TIMED_OUT, "failed to complete the operation before timeout");
private static class AckResultReceiver extends ResultReceiver {
@@ -96,7 +98,7 @@
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction");
CountDownLatch latch = new CountDownLatch(1);
ResultReceiver receiver = new AckResultReceiver(latch);
@@ -134,7 +136,7 @@
} else {
// success
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED,
+ new CallTransactionResult(CallTransactionResult.RESULT_SUCCEED,
"success"));
}
} catch (InterruptedException ie) {
diff --git a/src/com/android/server/telecom/voip/EndCallTransaction.java b/src/com/android/server/telecom/callsequencing/voip/EndCallTransaction.java
similarity index 82%
rename from src/com/android/server/telecom/voip/EndCallTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/EndCallTransaction.java
index 0cb7458..b4c92fe 100644
--- a/src/com/android/server/telecom/voip/EndCallTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/EndCallTransaction.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.telecom.DisconnectCause;
import android.util.Log;
@@ -22,6 +22,8 @@
import com.android.server.telecom.Call;
import com.android.server.telecom.CallState;
import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
@@ -29,7 +31,7 @@
/**
* This transaction should only be created for a CallControl action.
*/
-public class EndCallTransaction extends VoipCallTransaction {
+public class EndCallTransaction extends CallTransaction {
private static final String TAG = EndCallTransaction.class.getSimpleName();
private final CallsManager mCallsManager;
private final Call mCall;
@@ -43,7 +45,7 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
int code = mCause.getCode();
Log.d(TAG, String.format("processTransaction: mCode=[%d], mCall=[%s]", code, mCall));
@@ -56,7 +58,7 @@
mCallsManager.markCallAsRemoved(mCall);
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED,
+ new CallTransactionResult(CallTransactionResult.RESULT_SUCCEED,
"EndCallTransaction: RESULT_SUCCEED"));
}
}
diff --git a/src/com/android/server/telecom/voip/EndpointChangeTransaction.java b/src/com/android/server/telecom/callsequencing/voip/EndpointChangeTransaction.java
similarity index 75%
rename from src/com/android/server/telecom/voip/EndpointChangeTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/EndpointChangeTransaction.java
index 6841fcf..46678da 100644
--- a/src/com/android/server/telecom/voip/EndpointChangeTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/EndpointChangeTransaction.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.os.Bundle;
import android.os.ResultReceiver;
@@ -23,11 +23,13 @@
import android.util.Log;
import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
-public class EndpointChangeTransaction extends VoipCallTransaction {
+public class EndpointChangeTransaction extends CallTransaction {
private static final String TAG = EndpointChangeTransaction.class.getSimpleName();
private final CallEndpoint mCallEndpoint;
private final CallsManager mCallsManager;
@@ -39,19 +41,19 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.i(TAG, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
mCallsManager.requestCallEndpointChange(mCallEndpoint, new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
Log.i(TAG, "processTransaction: code=" + resultCode);
if (resultCode == CallEndpoint.ENDPOINT_OPERATION_SUCCESS) {
- future.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, null));
+ future.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, null));
} else {
// TODO:: define errors in CallException class. b/335703584
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN, null));
}
}
diff --git a/src/com/android/server/telecom/voip/HoldCallTransaction.java b/src/com/android/server/telecom/callsequencing/voip/HoldCallTransaction.java
similarity index 72%
rename from src/com/android/server/telecom/voip/HoldCallTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/HoldCallTransaction.java
index 6c4e8b7..2fa7ff7 100644
--- a/src/com/android/server/telecom/voip/HoldCallTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/HoldCallTransaction.java
@@ -14,18 +14,20 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.telecom.CallException;
import android.util.Log;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
-public class HoldCallTransaction extends VoipCallTransaction {
+public class HoldCallTransaction extends CallTransaction {
private static final String TAG = HoldCallTransaction.class.getSimpleName();
private final CallsManager mCallsManager;
@@ -38,17 +40,17 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
if (mCallsManager.canHold(mCall)) {
mCallsManager.markCallAsOnHold(mCall);
- future.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, null));
+ future.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, null));
} else {
Log.d(TAG, "processTransaction: onError");
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_CANNOT_HOLD_CURRENT_ACTIVE_CALL, "cannot hold call"));
}
return future;
diff --git a/src/com/android/server/telecom/voip/IncomingCallTransaction.java b/src/com/android/server/telecom/callsequencing/voip/IncomingCallTransaction.java
similarity index 85%
rename from src/com/android/server/telecom/voip/IncomingCallTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/IncomingCallTransaction.java
index ed0c7d6..31ce303 100644
--- a/src/com/android/server/telecom/voip/IncomingCallTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/IncomingCallTransaction.java
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import static android.telecom.CallAttributes.CALL_CAPABILITIES_KEY;
import static android.telecom.CallAttributes.DISPLAY_NAME_KEY;
-import static com.android.server.telecom.voip.VideoStateTranslation.TransactionalVideoStateToVideoProfileState;
+import static com.android.server.telecom.callsequencing.voip.VideoStateTranslation
+ .TransactionalVideoStateToVideoProfileState;
import android.os.Bundle;
import android.telecom.CallAttributes;
@@ -30,12 +31,14 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import com.android.server.telecom.flags.FeatureFlags;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
-public class IncomingCallTransaction extends VoipCallTransaction {
+public class IncomingCallTransaction extends CallTransaction {
private static final String TAG = IncomingCallTransaction.class.getSimpleName();
private final String mCallId;
@@ -64,7 +67,7 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction");
if (mCallsManager.isIncomingCallPermitted(mCallAttributes.getPhoneAccountHandle())) {
@@ -75,13 +78,13 @@
generateExtras(mCallAttributes), false);
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, call, "success"));
+ new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, call, "success", true));
} else {
Log.d(TAG, "processTransaction: incoming call is not permitted at this time");
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(
+ new CallTransactionResult(
CallException.CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME,
"incoming call not permitted at the current time"));
}
diff --git a/src/com/android/server/telecom/voip/MaybeHoldCallForNewCallTransaction.java b/src/com/android/server/telecom/callsequencing/voip/MaybeHoldCallForNewCallTransaction.java
similarity index 74%
rename from src/com/android/server/telecom/voip/MaybeHoldCallForNewCallTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/MaybeHoldCallForNewCallTransaction.java
index 3bed088..32062b5 100644
--- a/src/com/android/server/telecom/voip/MaybeHoldCallForNewCallTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/MaybeHoldCallForNewCallTransaction.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.os.OutcomeReceiver;
import android.telecom.CallException;
@@ -22,15 +22,17 @@
import com.android.server.telecom.Call;
import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
/**
- * This VoipCallTransaction is responsible for holding any active call in favor of a new call
+ * This VOIP CallTransaction is responsible for holding any active call in favor of a new call
* request. If the active call cannot be held or disconnected, the transaction will fail.
*/
-public class MaybeHoldCallForNewCallTransaction extends VoipCallTransaction {
+public class MaybeHoldCallForNewCallTransaction extends CallTransaction {
private static final String TAG = MaybeHoldCallForNewCallTransaction.class.getSimpleName();
private final CallsManager mCallsManager;
@@ -46,23 +48,23 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
mCallsManager.transactionHoldPotentialActiveCallForNewCall(mCall, mIsCallControlRequest,
new OutcomeReceiver<>() {
@Override
public void onResult(Boolean result) {
Log.d(TAG, "processTransaction: onResult");
- future.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, null));
+ future.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, null));
}
@Override
public void onError(CallException exception) {
Log.d(TAG, "processTransaction: onError");
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
exception.getCode(), exception.getMessage()));
}
});
diff --git a/src/com/android/server/telecom/voip/OutgoingCallTransaction.java b/src/com/android/server/telecom/callsequencing/voip/OutgoingCallTransaction.java
similarity index 87%
rename from src/com/android/server/telecom/voip/OutgoingCallTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/OutgoingCallTransaction.java
index 68ffecf..572de55 100644
--- a/src/com/android/server/telecom/voip/OutgoingCallTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/OutgoingCallTransaction.java
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import static android.Manifest.permission.CALL_PRIVILEGED;
import static android.telecom.CallAttributes.CALL_CAPABILITIES_KEY;
import static android.telecom.CallAttributes.DISPLAY_NAME_KEY;
import static android.telecom.CallException.CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME;
-import static com.android.server.telecom.voip.VideoStateTranslation.TransactionalVideoStateToVideoProfileState;
+import static com.android.server.telecom.callsequencing.voip.VideoStateTranslation
+ .TransactionalVideoStateToVideoProfileState;
import android.content.Context;
import android.content.Intent;
@@ -35,12 +36,14 @@
import com.android.server.telecom.Call;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.LoggedHandlerExecutor;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import com.android.server.telecom.flags.FeatureFlags;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
-public class OutgoingCallTransaction extends VoipCallTransaction {
+public class OutgoingCallTransaction extends CallTransaction {
private static final String TAG = OutgoingCallTransaction.class.getSimpleName();
private final String mCallId;
@@ -73,7 +76,7 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction");
final boolean hasCallPrivilegedPermission = mContext.checkCallingPermission(
@@ -95,11 +98,11 @@
if (callFuture == null) {
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(
+ new CallTransactionResult(
CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME,
"incoming call not permitted at the current time"));
}
- CompletionStage<VoipCallTransactionResult> result = callFuture.thenComposeAsync(
+ CompletionStage<CallTransactionResult> result = callFuture.thenComposeAsync(
(call) -> {
Log.d(TAG, "processTransaction: completing future");
@@ -107,7 +110,7 @@
if (call == null) {
Log.d(TAG, "processTransaction: call is null");
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(
+ new CallTransactionResult(
CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME,
"call could not be created at this time"));
} else {
@@ -121,16 +124,16 @@
}
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED,
- call, null));
+ new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED,
+ call, null, true));
}
, new LoggedHandlerExecutor(mHandler, "OCT.pT", null));
return result;
} else {
return CompletableFuture.completedFuture(
- new VoipCallTransactionResult(
+ new CallTransactionResult(
CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME,
"incoming call not permitted at the current time"));
diff --git a/src/com/android/server/telecom/voip/ParallelTransaction.java b/src/com/android/server/telecom/callsequencing/voip/ParallelTransaction.java
similarity index 79%
rename from src/com/android/server/telecom/voip/ParallelTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/ParallelTransaction.java
index e235ead..77e93f9 100644
--- a/src/com/android/server/telecom/voip/ParallelTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/ParallelTransaction.java
@@ -14,22 +14,25 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.telecom.CallException;
import com.android.server.telecom.LoggedHandlerExecutor;
import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
+import com.android.server.telecom.callsequencing.TransactionManager;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
/**
- * A VoipCallTransaction implementation that its sub transactions will be executed in parallel
+ * A CallTransaction implementation that its sub transactions will be executed in parallel
*/
-public class ParallelTransaction extends VoipCallTransaction {
- public ParallelTransaction(List<VoipCallTransaction> subTransactions,
+public class ParallelTransaction extends CallTransaction {
+ public ParallelTransaction(List<CallTransaction> subTransactions,
TelecomSystem.SyncRoot lock) {
super(subTransactions, lock);
}
@@ -45,9 +48,9 @@
private final AtomicInteger mCount = new AtomicInteger(mSubTransactions.size());
@Override
- public void onTransactionCompleted(VoipCallTransactionResult result,
+ public void onTransactionCompleted(CallTransactionResult result,
String transactionName) {
- if (result.getResult() != VoipCallTransactionResult.RESULT_SUCCEED) {
+ if (result.getResult() != CallTransactionResult.RESULT_SUCCEED) {
CompletableFuture.completedFuture(null).thenApplyAsync(
(x) -> {
finish(result);
@@ -68,8 +71,8 @@
public void onTransactionTimeout(String transactionName) {
CompletableFuture.completedFuture(null).thenApplyAsync(
(x) -> {
- VoipCallTransactionResult mainResult =
- new VoipCallTransactionResult(
+ CallTransactionResult mainResult =
+ new CallTransactionResult(
CallException.CODE_OPERATION_TIMED_OUT,
String.format("sub transaction %s timed out",
transactionName));
@@ -82,7 +85,7 @@
+ ".oTT", mLock));
}
};
- for (VoipCallTransaction transaction : mSubTransactions) {
+ for (CallTransaction transaction : mSubTransactions) {
transaction.setCompleteListener(subTransactionListener);
transaction.start();
}
diff --git a/src/com/android/server/telecom/voip/RequestNewActiveCallTransaction.java b/src/com/android/server/telecom/callsequencing/voip/RequestNewActiveCallTransaction.java
similarity index 83%
rename from src/com/android/server/telecom/voip/RequestNewActiveCallTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/RequestNewActiveCallTransaction.java
index e3aed8e..8e6e354 100644
--- a/src/com/android/server/telecom/voip/RequestNewActiveCallTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/RequestNewActiveCallTransaction.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.os.OutcomeReceiver;
import android.telecom.CallException;
@@ -24,6 +24,8 @@
import com.android.server.telecom.CallState;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.ConnectionServiceFocusManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import com.android.server.telecom.flags.Flags;
import java.util.concurrent.CompletableFuture;
@@ -42,7 +44,7 @@
* - MaybeHoldCallForNewCallTransaction was performed before this so any potential active calls
* should be held now.
*/
-public class RequestNewActiveCallTransaction extends VoipCallTransaction {
+public class RequestNewActiveCallTransaction extends CallTransaction {
private static final String TAG = RequestNewActiveCallTransaction.class.getSimpleName();
private final CallsManager mCallsManager;
@@ -55,14 +57,14 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
int currentCallState = mCall.getState();
// certain calls cannot go active/answered (ex. disconnect calls, etc.)
if (!canBecomeNewCallFocus(currentCallState)) {
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_CALL_CANNOT_BE_SET_TO_ACTIVE,
"CallState cannot be set to active or answered due to current call"
+ " state being in invalid state"));
@@ -71,7 +73,7 @@
if (!Flags.transactionalHoldDisconnectsUnholdable() &&
mCallsManager.getActiveCall() != null) {
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_CALL_CANNOT_BE_SET_TO_ACTIVE,
"Already an active call. Request hold on current active call."));
return future;
@@ -81,14 +83,14 @@
@Override
public void onResult(Boolean result) {
Log.d(TAG, "processTransaction: onResult");
- future.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED, null));
+ future.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED, null));
}
@Override
public void onError(CallException exception) {
Log.d(TAG, "processTransaction: onError");
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
exception.getCode(), exception.getMessage()));
}
});
diff --git a/src/com/android/server/telecom/voip/RequestVideoStateTransaction.java b/src/com/android/server/telecom/callsequencing/voip/RequestVideoStateTransaction.java
similarity index 73%
rename from src/com/android/server/telecom/voip/RequestVideoStateTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/RequestVideoStateTransaction.java
index c1bc343..6fb1836 100644
--- a/src/com/android/server/telecom/voip/RequestVideoStateTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/RequestVideoStateTransaction.java
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
-import static com.android.server.telecom.voip.VideoStateTranslation.TransactionalVideoStateToVideoProfileState;
+import static com.android.server.telecom.callsequencing.voip.VideoStateTranslation
+ .TransactionalVideoStateToVideoProfileState;
import android.telecom.CallException;
import android.telecom.VideoProfile;
@@ -24,11 +25,13 @@
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.Call;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
-public class RequestVideoStateTransaction extends VoipCallTransaction {
+public class RequestVideoStateTransaction extends CallTransaction {
private static final String TAG = RequestVideoStateTransaction.class.getSimpleName();
private final Call mCall;
@@ -42,19 +45,19 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
if (isRequestingVideoTransmission(mVideoProfileState) &&
!mCall.isVideoCallingSupportedByPhoneAccount()) {
- future.complete(new VoipCallTransactionResult(
+ future.complete(new CallTransactionResult(
CallException.CODE_ERROR_UNKNOWN /*TODO:: define error code. b/335703584 */,
"Video calling is not supported by the target account"));
} else {
mCall.setVideoState(mVideoProfileState);
- future.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED,
+ future.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED,
"The Video State was changed successfully"));
}
return future;
diff --git a/src/com/android/server/telecom/voip/SerialTransaction.java b/src/com/android/server/telecom/callsequencing/voip/SerialTransaction.java
similarity index 79%
rename from src/com/android/server/telecom/voip/SerialTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/SerialTransaction.java
index 748f285..d5d75d0 100644
--- a/src/com/android/server/telecom/voip/SerialTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/SerialTransaction.java
@@ -14,27 +14,30 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.telecom.CallException;
import com.android.server.telecom.LoggedHandlerExecutor;
import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
+import com.android.server.telecom.callsequencing.TransactionManager;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
/**
- * A VoipCallTransaction implementation that its sub transactions will be executed in serial
+ * A CallTransaction implementation that its sub transactions will be executed in serial
*/
-public class SerialTransaction extends VoipCallTransaction {
- public SerialTransaction(List<VoipCallTransaction> subTransactions,
+public class SerialTransaction extends CallTransaction {
+ public SerialTransaction(List<CallTransaction> subTransactions,
TelecomSystem.SyncRoot lock) {
super(subTransactions, lock);
}
- public void appendTransaction(VoipCallTransaction transaction){
+ public void appendTransaction(CallTransaction transaction){
mSubTransactions.add(transaction);
}
@@ -49,9 +52,9 @@
private final AtomicInteger mTransactionIndex = new AtomicInteger(0);
@Override
- public void onTransactionCompleted(VoipCallTransactionResult result,
+ public void onTransactionCompleted(CallTransactionResult result,
String transactionName) {
- if (result.getResult() != VoipCallTransactionResult.RESULT_SUCCEED) {
+ if (result.getResult() != CallTransactionResult.RESULT_SUCCEED) {
handleTransactionFailure();
CompletableFuture.completedFuture(null).thenApplyAsync(
(x) -> {
@@ -65,7 +68,7 @@
} else {
int currTransactionIndex = mTransactionIndex.incrementAndGet();
if (currTransactionIndex < mSubTransactions.size()) {
- VoipCallTransaction transaction = mSubTransactions.get(
+ CallTransaction transaction = mSubTransactions.get(
currTransactionIndex);
transaction.setCompleteListener(this);
transaction.start();
@@ -80,8 +83,8 @@
handleTransactionFailure();
CompletableFuture.completedFuture(null).thenApplyAsync(
(x) -> {
- VoipCallTransactionResult mainResult =
- new VoipCallTransactionResult(
+ CallTransactionResult mainResult =
+ new CallTransactionResult(
CallException.CODE_OPERATION_TIMED_OUT,
String.format("sub transaction %s timed out",
transactionName));
@@ -94,7 +97,7 @@
+ ".oTT", mLock));
}
};
- VoipCallTransaction transaction = mSubTransactions.get(0);
+ CallTransaction transaction = mSubTransactions.get(0);
transaction.setCompleteListener(subTransactionListener);
transaction.start();
diff --git a/src/com/android/server/telecom/voip/SetMuteStateTransaction.java b/src/com/android/server/telecom/callsequencing/voip/SetMuteStateTransaction.java
similarity index 73%
rename from src/com/android/server/telecom/voip/SetMuteStateTransaction.java
rename to src/com/android/server/telecom/callsequencing/voip/SetMuteStateTransaction.java
index d9f7329..14f8945 100644
--- a/src/com/android/server/telecom/voip/SetMuteStateTransaction.java
+++ b/src/com/android/server/telecom/callsequencing/voip/SetMuteStateTransaction.java
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.util.Log;
import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
@@ -27,7 +29,7 @@
* This transaction should be used to change the global mute state for transactional
* calls. There is currently no way for this transaction to fail.
*/
-public class SetMuteStateTransaction extends VoipCallTransaction {
+public class SetMuteStateTransaction extends CallTransaction {
private static final String TAG = SetMuteStateTransaction.class.getSimpleName();
private final CallsManager mCallsManager;
@@ -40,14 +42,14 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
Log.d(TAG, "processTransaction");
- CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> future = new CompletableFuture<>();
mCallsManager.mute(mIsMuted);
- future.complete(new VoipCallTransactionResult(
- VoipCallTransactionResult.RESULT_SUCCEED,
+ future.complete(new CallTransactionResult(
+ CallTransactionResult.RESULT_SUCCEED,
"The Mute State was changed successfully"));
return future;
diff --git a/src/com/android/server/telecom/voip/VideoStateTranslation.java b/src/com/android/server/telecom/callsequencing/voip/VideoStateTranslation.java
similarity index 95%
rename from src/com/android/server/telecom/voip/VideoStateTranslation.java
rename to src/com/android/server/telecom/callsequencing/voip/VideoStateTranslation.java
index 3812d15..4610f96 100644
--- a/src/com/android/server/telecom/voip/VideoStateTranslation.java
+++ b/src/com/android/server/telecom/callsequencing/voip/VideoStateTranslation.java
@@ -14,17 +14,12 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import android.telecom.CallAttributes;
import android.telecom.Log;
import android.telecom.VideoProfile;
-import com.android.server.telecom.AnomalyReporterAdapter;
-import com.android.server.telecom.AnomalyReporterAdapterImpl;
-
-import java.util.UUID;
-
/**
* This remapping class is needed because {@link VideoProfile} has more fine grain levels of video
* states as apposed to Transactional video states (defined in {@link CallAttributes.CallType}.
diff --git a/src/com/android/server/telecom/voip/VoipCallMonitor.java b/src/com/android/server/telecom/callsequencing/voip/VoipCallMonitor.java
similarity index 99%
rename from src/com/android/server/telecom/voip/VoipCallMonitor.java
rename to src/com/android/server/telecom/callsequencing/voip/VoipCallMonitor.java
index 8f6ad51..1d1a1a6 100644
--- a/src/com/android/server/telecom/voip/VoipCallMonitor.java
+++ b/src/com/android/server/telecom/callsequencing/voip/VoipCallMonitor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.telecom.voip;
+package com.android.server.telecom.callsequencing.voip;
import static android.app.ForegroundServiceDelegationOptions.DELEGATION_SERVICE_PHONE_CALL;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
diff --git a/testapps/transactionalVoipApp/res/values-bs/strings.xml b/testapps/transactionalVoipApp/res/values-bs/strings.xml
index 24ffba2..f417043 100644
--- a/testapps/transactionalVoipApp/res/values-bs/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-bs/strings.xml
@@ -31,7 +31,7 @@
<string name="request_earpiece_endpoint" msgid="6649571985089296573">"Slušalica"</string>
<string name="request_speaker_endpoint" msgid="1033259535289845405">"Zvučnik"</string>
<string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
- <string name="start_stream" msgid="3567634786280097431">"pokreni prijenos"</string>
+ <string name="start_stream" msgid="3567634786280097431">"pokreni prenos"</string>
<string name="crash_app" msgid="2548690390730057704">"izbaci izuzetak"</string>
<string name="update_notification" msgid="8677916482672588779">"ažuriraj obavještenje u stil poziva u toku"</string>
</resources>
diff --git a/testapps/transactionalVoipApp/res/values-in/strings.xml b/testapps/transactionalVoipApp/res/values-in/strings.xml
index 935f036..ba41376 100644
--- a/testapps/transactionalVoipApp/res/values-in/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-in/strings.xml
@@ -27,7 +27,7 @@
<string name="set_call_active" msgid="3365404393507589899">"setelAktif"</string>
<string name="answer" msgid="5423590397665409939">"jawab"</string>
<string name="set_call_inactive" msgid="7106775211368705195">"setelNonaktif"</string>
- <string name="disconnect_call" msgid="1349412380315371385">"putuskan koneksi"</string>
+ <string name="disconnect_call" msgid="1349412380315371385">"berhenti hubungkan"</string>
<string name="request_earpiece_endpoint" msgid="6649571985089296573">"Earpiece"</string>
<string name="request_speaker_endpoint" msgid="1033259535289845405">"Speaker"</string>
<string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
diff --git a/testapps/transactionalVoipApp/res/values-sq/strings.xml b/testapps/transactionalVoipApp/res/values-sq/strings.xml
index ddaba66..2816473 100644
--- a/testapps/transactionalVoipApp/res/values-sq/strings.xml
+++ b/testapps/transactionalVoipApp/res/values-sq/strings.xml
@@ -30,7 +30,7 @@
<string name="disconnect_call" msgid="1349412380315371385">"shkëput"</string>
<string name="request_earpiece_endpoint" msgid="6649571985089296573">"Receptori"</string>
<string name="request_speaker_endpoint" msgid="1033259535289845405">"Altoparlanti"</string>
- <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth"</string>
+ <string name="request_bluetooth_endpoint" msgid="5933254250623451836">"Bluetooth-i"</string>
<string name="start_stream" msgid="3567634786280097431">"nis transmetimin"</string>
<string name="crash_app" msgid="2548690390730057704">"gjenero një përjashtim"</string>
<string name="update_notification" msgid="8677916482672588779">"përditëso njoftimin me stilin e telefonatës në vazhdim"</string>
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index c592908..79fd3d5 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -142,7 +142,7 @@
import com.android.server.telecom.ui.CallStreamingNotification;
import com.android.server.telecom.ui.DisconnectedCallNotifier;
import com.android.server.telecom.ui.ToastFactory;
-import com.android.server.telecom.voip.TransactionManager;
+import com.android.server.telecom.callsequencing.TransactionManager;
import com.google.common.base.Objects;
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index 45b4ed1..519e596 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -113,7 +113,8 @@
private final String PACKAGE_1 = "PACKAGE_1";
private final String PACKAGE_2 = "PACKAGE_2";
private final String COMPONENT_NAME = "com.android.server.telecom.tests.MockConnectionService";
- private final UserHandle USER_HANDLE_10 = new UserHandle(10);
+ private final UserHandle USER_HANDLE_10 = UserHandle.of(10);
+ private final UserHandle USER_HANDLE_1000 = UserHandle.of(1000);
private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
private PhoneAccountRegistrar mRegistrar;
@Mock private SubscriptionManager mSubscriptionManager;
@@ -140,6 +141,7 @@
mRegistrar = new PhoneAccountRegistrar(
mComponentContextFixture.getTestDouble().getApplicationContext(), mLock, FILE_NAME,
mDefaultDialerCache, mAppLabelProxy, mTelephonyFeatureFlags, mFeatureFlags);
+ mRegistrar.setCurrentUserHandle(UserHandle.SYSTEM);
when(mFeatureFlags.onlyUpdateTelephonyOnValidSubIds()).thenReturn(false);
when(mFeatureFlags.unregisterUnresolvableAccounts()).thenReturn(true);
when(mTelephonyFeatureFlags.workProfileApiSplit()).thenReturn(false);
@@ -1306,8 +1308,7 @@
Mockito.mock(IConnectionService.class));
UserManager userManager = mContext.getSystemService(UserManager.class);
- List<UserHandle> users = Arrays.asList(new UserHandle(0),
- new UserHandle(1000));
+ List<UserHandle> users = Arrays.asList(UserHandle.SYSTEM, USER_HANDLE_1000);
PhoneAccount pa1 = new PhoneAccount.Builder(
new PhoneAccountHandle(new ComponentName(PACKAGE_1, COMPONENT_NAME), "1234",
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index 793cf14..07a12c4 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -97,9 +97,9 @@
import com.android.server.telecom.components.UserCallIntentProcessorFactory;
import com.android.server.telecom.flags.FeatureFlags;
import com.android.server.telecom.metrics.TelecomMetricsController;
-import com.android.server.telecom.voip.IncomingCallTransaction;
-import com.android.server.telecom.voip.OutgoingCallTransaction;
-import com.android.server.telecom.voip.TransactionManager;
+import com.android.server.telecom.callsequencing.voip.IncomingCallTransaction;
+import com.android.server.telecom.callsequencing.voip.OutgoingCallTransaction;
+import com.android.server.telecom.callsequencing.TransactionManager;
import org.junit.After;
import org.junit.Before;
diff --git a/tests/src/com/android/server/telecom/tests/TransactionTests.java b/tests/src/com/android/server/telecom/tests/TransactionTests.java
index 5876474..78c2210 100644
--- a/tests/src/com/android/server/telecom/tests/TransactionTests.java
+++ b/tests/src/com/android/server/telecom/tests/TransactionTests.java
@@ -16,24 +16,25 @@
package com.android.server.telecom.tests;
-import static com.android.server.telecom.voip.VideoStateTranslation.TransactionalVideoStateToVideoProfileState;
-import static com.android.server.telecom.voip.VideoStateTranslation.VideoProfileStateToTransactionalVideoState;
+import static com.android.server.telecom.callsequencing.voip.VideoStateTranslation
+ .TransactionalVideoStateToVideoProfileState;
+import static com.android.server.telecom.callsequencing.voip.VideoStateTranslation
+ .VideoProfileStateToTransactionalVideoState;
+import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.isA;
-import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
@@ -59,30 +60,26 @@
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ConnectionServiceWrapper;
-import com.android.server.telecom.flags.FeatureFlags;
import com.android.server.telecom.PhoneNumberUtilsAdapter;
import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
+import com.android.server.telecom.callsequencing.TransactionManager;
+import com.android.server.telecom.callsequencing.VerifyCallStateChangeTransaction;
+import com.android.server.telecom.callsequencing.voip.EndCallTransaction;
+import com.android.server.telecom.callsequencing.voip.HoldCallTransaction;
+import com.android.server.telecom.callsequencing.voip.IncomingCallTransaction;
+import com.android.server.telecom.callsequencing.voip.MaybeHoldCallForNewCallTransaction;
+import com.android.server.telecom.callsequencing.voip.OutgoingCallTransaction;
+import com.android.server.telecom.callsequencing.voip.RequestNewActiveCallTransaction;
import com.android.server.telecom.ui.ToastFactory;
-import com.android.server.telecom.voip.EndCallTransaction;
-import com.android.server.telecom.voip.HoldCallTransaction;
-import com.android.server.telecom.voip.IncomingCallTransaction;
-import com.android.server.telecom.voip.OutgoingCallTransaction;
-import com.android.server.telecom.voip.MaybeHoldCallForNewCallTransaction;
-import com.android.server.telecom.voip.RequestNewActiveCallTransaction;
-import com.android.server.telecom.voip.TransactionManager;
-import com.android.server.telecom.voip.VerifyCallStateChangeTransaction;
-import com.android.server.telecom.voip.VideoStateTranslation;
-import com.android.server.telecom.voip.VoipCallTransactionResult;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -421,7 +418,7 @@
// THEN
verify(mMockCall1, times(1)).addCallStateListener(t.getCallStateListenerImpl());
- assertEquals(VoipCallTransactionResult.RESULT_SUCCEED,
+ assertEquals(CallTransactionResult.RESULT_SUCCEED,
t.getTransactionResult().get(2, TimeUnit.SECONDS).getResult());
verify(mMockCall1, atLeastOnce()).removeCallStateListener(any());
}
diff --git a/tests/src/com/android/server/telecom/tests/TransactionalServiceWrapperTest.java b/tests/src/com/android/server/telecom/tests/TransactionalServiceWrapperTest.java
index fa5f2a2..fea6135 100644
--- a/tests/src/com/android/server/telecom/tests/TransactionalServiceWrapperTest.java
+++ b/tests/src/com/android/server/telecom/tests/TransactionalServiceWrapperTest.java
@@ -39,10 +39,10 @@
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.TransactionalServiceRepository;
import com.android.server.telecom.TransactionalServiceWrapper;
-import com.android.server.telecom.voip.EndCallTransaction;
-import com.android.server.telecom.voip.HoldCallTransaction;
-import com.android.server.telecom.voip.SerialTransaction;
-import com.android.server.telecom.voip.TransactionManager;
+import com.android.server.telecom.callsequencing.voip.EndCallTransaction;
+import com.android.server.telecom.callsequencing.voip.HoldCallTransaction;
+import com.android.server.telecom.callsequencing.voip.SerialTransaction;
+import com.android.server.telecom.callsequencing.TransactionManager;
import org.junit.After;
import org.junit.Before;
@@ -83,9 +83,8 @@
Mockito.when(mCallsManager.getLock()).thenReturn(mLock);
Mockito.when(mCallEventCallback.asBinder()).thenReturn(mIBinder);
mTransactionalServiceWrapper = new TransactionalServiceWrapper(mCallEventCallback,
- mCallsManager, SERVICE_HANDLE, mMockCall1, mRepository);
-
- mTransactionalServiceWrapper.setTransactionManager(mTransactionManager);
+ mCallsManager, SERVICE_HANDLE, mMockCall1, mRepository, mTransactionManager,
+ false /*call sequencing*/);
}
@Override
@@ -98,7 +97,8 @@
public void testTransactionalServiceWrapperStartState() throws Exception {
TransactionalServiceWrapper service =
new TransactionalServiceWrapper(mCallEventCallback,
- mCallsManager, SERVICE_HANDLE, mMockCall1, mRepository);
+ mCallsManager, SERVICE_HANDLE, mMockCall1, mRepository, mTransactionManager,
+ false /*call sequencing*/);
assertEquals(SERVICE_HANDLE, service.getPhoneAccountHandle());
assertEquals(1, service.getNumberOfTrackedCalls());
@@ -108,7 +108,8 @@
public void testTransactionalServiceWrapperCallCount() throws Exception {
TransactionalServiceWrapper service =
new TransactionalServiceWrapper(mCallEventCallback,
- mCallsManager, SERVICE_HANDLE, mMockCall1, mRepository);
+ mCallsManager, SERVICE_HANDLE, mMockCall1, mRepository, mTransactionManager,
+ false /*call sequencing*/);
assertEquals(1, service.getNumberOfTrackedCalls());
service.trackCall(mMockCall2);
diff --git a/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java b/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
index 7f7399c..bf68f8c 100644
--- a/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
+++ b/tests/src/com/android/server/telecom/tests/VoipCallMonitorTest.java
@@ -49,7 +49,7 @@
import com.android.server.telecom.Call;
import com.android.server.telecom.CallState;
import com.android.server.telecom.TelecomSystem;
-import com.android.server.telecom.voip.VoipCallMonitor;
+import com.android.server.telecom.callsequencing.voip.VoipCallMonitor;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/src/com/android/server/telecom/tests/VoipCallTransactionTest.java b/tests/src/com/android/server/telecom/tests/VoipCallTransactionTest.java
index c5be130..c479aac 100644
--- a/tests/src/com/android/server/telecom/tests/VoipCallTransactionTest.java
+++ b/tests/src/com/android/server/telecom/tests/VoipCallTransactionTest.java
@@ -25,11 +25,11 @@
import androidx.test.filters.SmallTest;
import com.android.server.telecom.TelecomSystem;
-import com.android.server.telecom.voip.ParallelTransaction;
-import com.android.server.telecom.voip.SerialTransaction;
-import com.android.server.telecom.voip.TransactionManager;
-import com.android.server.telecom.voip.VoipCallTransaction;
-import com.android.server.telecom.voip.VoipCallTransactionResult;
+import com.android.server.telecom.callsequencing.voip.ParallelTransaction;
+import com.android.server.telecom.callsequencing.voip.SerialTransaction;
+import com.android.server.telecom.callsequencing.TransactionManager;
+import com.android.server.telecom.callsequencing.CallTransaction;
+import com.android.server.telecom.callsequencing.CallTransactionResult;
import org.junit.After;
import org.junit.Before;
@@ -51,7 +51,7 @@
private TransactionManager mTransactionManager;
private static final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
- private class TestVoipCallTransaction extends VoipCallTransaction {
+ private class TestVoipCallTransaction extends CallTransaction {
public static final int SUCCESS = 0;
public static final int FAILED = 1;
public static final int TIMEOUT = 2;
@@ -70,27 +70,27 @@
}
@Override
- public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
+ public CompletionStage<CallTransactionResult> processTransaction(Void v) {
if (mType == EXCEPTION) {
mLog.append(mName).append(" exception;\n");
throw new IllegalStateException("TEST EXCEPTION");
}
- CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
+ CompletableFuture<CallTransactionResult> resultFuture = new CompletableFuture<>();
mHandler.postDelayed(() -> {
if (mType == SUCCESS) {
mLog.append(mName).append(" success;\n");
resultFuture.complete(
- new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED,
+ new CallTransactionResult(CallTransactionResult.RESULT_SUCCEED,
null));
} else if (mType == FAILED) {
mLog.append(mName).append(" failed;\n");
resultFuture.complete(
- new VoipCallTransactionResult(CallException.CODE_ERROR_UNKNOWN,
+ new CallTransactionResult(CallException.CODE_ERROR_UNKNOWN,
null));
} else {
mLog.append(mName).append(" timeout;\n");
resultFuture.complete(
- new VoipCallTransactionResult(CallException.CODE_ERROR_UNKNOWN,
+ new CallTransactionResult(CallException.CODE_ERROR_UNKNOWN,
"timeout"));
}
}, mSleepTime);
@@ -122,7 +122,7 @@
@Test
public void testSerialTransactionSuccess()
throws ExecutionException, InterruptedException, TimeoutException {
- List<VoipCallTransaction> subTransactions = new ArrayList<>();
+ List<CallTransaction> subTransactions = new ArrayList<>();
TestVoipCallTransaction t1 = new TestVoipCallTransaction("t1", 1000L,
TestVoipCallTransaction.SUCCESS);
TestVoipCallTransaction t2 = new TestVoipCallTransaction("t2", 1000L,
@@ -132,13 +132,13 @@
subTransactions.add(t1);
subTransactions.add(t2);
subTransactions.add(t3);
- CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeReceiver =
+ CompletableFuture<CallTransactionResult> resultFuture = new CompletableFuture<>();
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeReceiver =
resultFuture::complete;
String expectedLog = "t1 success;\nt2 success;\nt3 success;\n";
mTransactionManager.addTransaction(new SerialTransaction(subTransactions, mLock),
outcomeReceiver);
- assertEquals(VoipCallTransactionResult.RESULT_SUCCEED,
+ assertEquals(CallTransactionResult.RESULT_SUCCEED,
resultFuture.get(5000L, TimeUnit.MILLISECONDS).getResult());
assertEquals(expectedLog, mLog.toString());
verifyTransactionsFinished(t1, t2, t3);
@@ -148,7 +148,7 @@
@Test
public void testSerialTransactionFailed()
throws ExecutionException, InterruptedException, TimeoutException {
- List<VoipCallTransaction> subTransactions = new ArrayList<>();
+ List<CallTransaction> subTransactions = new ArrayList<>();
TestVoipCallTransaction t1 = new TestVoipCallTransaction("t1", 1000L,
TestVoipCallTransaction.SUCCESS);
TestVoipCallTransaction t2 = new TestVoipCallTransaction("t2", 1000L,
@@ -159,10 +159,10 @@
subTransactions.add(t2);
subTransactions.add(t3);
CompletableFuture<String> exceptionFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeReceiver =
- new OutcomeReceiver<VoipCallTransactionResult, CallException>() {
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeReceiver =
+ new OutcomeReceiver<CallTransactionResult, CallException>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
}
@@ -183,7 +183,7 @@
@Test
public void testParallelTransactionSuccess()
throws ExecutionException, InterruptedException, TimeoutException {
- List<VoipCallTransaction> subTransactions = new ArrayList<>();
+ List<CallTransaction> subTransactions = new ArrayList<>();
TestVoipCallTransaction t1 = new TestVoipCallTransaction("t1", 1000L,
TestVoipCallTransaction.SUCCESS);
TestVoipCallTransaction t2 = new TestVoipCallTransaction("t2", 500L,
@@ -193,12 +193,12 @@
subTransactions.add(t1);
subTransactions.add(t2);
subTransactions.add(t3);
- CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeReceiver =
+ CompletableFuture<CallTransactionResult> resultFuture = new CompletableFuture<>();
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeReceiver =
resultFuture::complete;
mTransactionManager.addTransaction(new ParallelTransaction(subTransactions, mLock),
outcomeReceiver);
- assertEquals(VoipCallTransactionResult.RESULT_SUCCEED,
+ assertEquals(CallTransactionResult.RESULT_SUCCEED,
resultFuture.get(5000L, TimeUnit.MILLISECONDS).getResult());
String log = mLog.toString();
assertTrue(log.contains("t1 success;\n"));
@@ -211,7 +211,7 @@
@Test
public void testParallelTransactionFailed()
throws ExecutionException, InterruptedException, TimeoutException {
- List<VoipCallTransaction> subTransactions = new ArrayList<>();
+ List<CallTransaction> subTransactions = new ArrayList<>();
TestVoipCallTransaction t1 = new TestVoipCallTransaction("t1", 1000L,
TestVoipCallTransaction.SUCCESS);
TestVoipCallTransaction t2 = new TestVoipCallTransaction("t2", 500L,
@@ -222,10 +222,10 @@
subTransactions.add(t2);
subTransactions.add(t3);
CompletableFuture<String> exceptionFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeReceiver =
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeReceiver =
new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
}
@@ -248,10 +248,10 @@
TestVoipCallTransaction t = new TestVoipCallTransaction("t", 10000L,
TestVoipCallTransaction.SUCCESS);
CompletableFuture<String> exceptionFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeReceiver =
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeReceiver =
new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
}
@@ -275,10 +275,10 @@
TestVoipCallTransaction t2 = new TestVoipCallTransaction("t2", 1000L,
TestVoipCallTransaction.SUCCESS);
CompletableFuture<String> exceptionFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeExceptionReceiver =
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeExceptionReceiver =
new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
}
@Override
@@ -291,12 +291,12 @@
exceptionFuture.get(7000L, TimeUnit.MILLISECONDS);
assertTrue(mLog.toString().contains("t1 exception;\n"));
// Verify an exception in a processing a previous transaction does not stall the next one.
- CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeReceiver =
+ CompletableFuture<CallTransactionResult> resultFuture = new CompletableFuture<>();
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeReceiver =
resultFuture::complete;
mTransactionManager.addTransaction(t2, outcomeReceiver);
String expectedLog = "t1 exception;\nt2 success;\n";
- assertEquals(VoipCallTransactionResult.RESULT_SUCCEED,
+ assertEquals(CallTransactionResult.RESULT_SUCCEED,
resultFuture.get(5000L, TimeUnit.MILLISECONDS).getResult());
assertEquals(expectedLog, mLog.toString());
verifyTransactionsFinished(t1, t2);
@@ -317,10 +317,10 @@
TestVoipCallTransaction.EXCEPTION);
// verify the TransactionManager informs the client of the failed transaction
CompletableFuture<String> exceptionFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeExceptionReceiver =
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeExceptionReceiver =
new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
}
@Override
@@ -346,10 +346,10 @@
TestVoipCallTransaction.SUCCESS);
TestVoipCallTransaction t3 = new TestVoipCallTransaction("t3", 1000L,
TestVoipCallTransaction.SUCCESS);
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeExceptionReceiver =
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeExceptionReceiver =
new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
throw new IllegalStateException("RESULT EXCEPTION");
}
@@ -358,10 +358,10 @@
}
};
mTransactionManager.addTransaction(t1, outcomeExceptionReceiver);
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeException2Receiver =
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeException2Receiver =
new OutcomeReceiver<>() {
@Override
- public void onResult(VoipCallTransactionResult result) {
+ public void onResult(CallTransactionResult result) {
}
@Override
@@ -371,12 +371,12 @@
};
mTransactionManager.addTransaction(t2, outcomeException2Receiver);
// Verify an exception in a previous transaction result does not stall the next one.
- CompletableFuture<VoipCallTransactionResult> resultFuture = new CompletableFuture<>();
- OutcomeReceiver<VoipCallTransactionResult, CallException> outcomeReceiver =
+ CompletableFuture<CallTransactionResult> resultFuture = new CompletableFuture<>();
+ OutcomeReceiver<CallTransactionResult, CallException> outcomeReceiver =
resultFuture::complete;
mTransactionManager.addTransaction(t3, outcomeReceiver);
String expectedLog = "t1 success;\nt2 success;\nt3 success;\n";
- assertEquals(VoipCallTransactionResult.RESULT_SUCCEED,
+ assertEquals(CallTransactionResult.RESULT_SUCCEED,
resultFuture.get(5000L, TimeUnit.MILLISECONDS).getResult());
assertEquals(expectedLog, mLog.toString());
verifyTransactionsFinished(t1, t2, t3);