1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.telecom.voip; 18 19 import android.os.OutcomeReceiver; 20 import android.telecom.CallException; 21 import android.util.Log; 22 23 import com.android.server.telecom.Call; 24 import com.android.server.telecom.CallState; 25 import com.android.server.telecom.CallsManager; 26 import com.android.server.telecom.ConnectionServiceFocusManager; 27 import com.android.server.telecom.flags.Flags; 28 29 import java.util.concurrent.CompletableFuture; 30 import java.util.concurrent.CompletionStage; 31 32 /** 33 * This transaction should be created when a requesting call would like to go from a valid inactive 34 * state (ex. HELD, RINGING, DIALING) to ACTIVE. 35 * 36 * This class performs some pre-checks to spot a failure in requesting a new call focus and sends 37 * the official request to transition the requested call to ACTIVE. 38 * 39 * Note: 40 * - This Transaction is used for CallControl and CallEventCallbacks, do not put logic in the 41 * onResult/onError that pertains to one direction. 42 * - MaybeHoldCallForNewCallTransaction was performed before this so any potential active calls 43 * should be held now. 44 */ 45 public class RequestNewActiveCallTransaction extends VoipCallTransaction { 46 47 private static final String TAG = RequestNewActiveCallTransaction.class.getSimpleName(); 48 private final CallsManager mCallsManager; 49 private final Call mCall; 50 RequestNewActiveCallTransaction(CallsManager callsManager, Call call)51 public RequestNewActiveCallTransaction(CallsManager callsManager, Call call) { 52 super(callsManager.getLock()); 53 mCallsManager = callsManager; 54 mCall = call; 55 } 56 57 @Override processTransaction(Void v)58 public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) { 59 Log.d(TAG, "processTransaction"); 60 CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>(); 61 int currentCallState = mCall.getState(); 62 63 // certain calls cannot go active/answered (ex. disconnect calls, etc.) 64 if (!canBecomeNewCallFocus(currentCallState)) { 65 future.complete(new VoipCallTransactionResult( 66 CallException.CODE_CALL_CANNOT_BE_SET_TO_ACTIVE, 67 "CallState cannot be set to active or answered due to current call" 68 + " state being in invalid state")); 69 return future; 70 } 71 72 if (!Flags.transactionalHoldDisconnectsUnholdable() && 73 mCallsManager.getActiveCall() != null) { 74 future.complete(new VoipCallTransactionResult( 75 CallException.CODE_CALL_CANNOT_BE_SET_TO_ACTIVE, 76 "Already an active call. Request hold on current active call.")); 77 return future; 78 } 79 80 mCallsManager.requestNewCallFocusAndVerify(mCall, new OutcomeReceiver<>() { 81 @Override 82 public void onResult(Boolean result) { 83 Log.d(TAG, "processTransaction: onResult"); 84 future.complete(new VoipCallTransactionResult( 85 VoipCallTransactionResult.RESULT_SUCCEED, null)); 86 } 87 88 @Override 89 public void onError(CallException exception) { 90 Log.d(TAG, "processTransaction: onError"); 91 future.complete(new VoipCallTransactionResult( 92 exception.getCode(), exception.getMessage())); 93 } 94 }); 95 96 return future; 97 } 98 isPriorityCallingState(int currentCallState)99 private boolean isPriorityCallingState(int currentCallState) { 100 return ConnectionServiceFocusManager.PRIORITY_FOCUS_CALL_STATE.contains(currentCallState); 101 } 102 canBecomeNewCallFocus(int currentCallState)103 private boolean canBecomeNewCallFocus(int currentCallState) { 104 return isPriorityCallingState(currentCallState) || currentCallState == CallState.ON_HOLD; 105 } 106 }