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.CallAttributes; 21 import android.telecom.CallException; 22 import android.util.Log; 23 24 import com.android.server.telecom.Call; 25 import com.android.server.telecom.CallState; 26 import com.android.server.telecom.CallsManager; 27 import com.android.server.telecom.ConnectionServiceFocusManager; 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 (mCallsManager.getActiveCall() != null) { 73 future.complete(new VoipCallTransactionResult( 74 CallException.CODE_CALL_CANNOT_BE_SET_TO_ACTIVE, 75 "Already an active call. Request hold on current active call.")); 76 return future; 77 } 78 79 mCallsManager.requestNewCallFocusAndVerify(mCall, new OutcomeReceiver<>() { 80 @Override 81 public void onResult(Boolean result) { 82 Log.d(TAG, "processTransaction: onResult"); 83 future.complete(new VoipCallTransactionResult( 84 VoipCallTransactionResult.RESULT_SUCCEED, null)); 85 } 86 87 @Override 88 public void onError(CallException exception) { 89 Log.d(TAG, "processTransaction: onError"); 90 future.complete(new VoipCallTransactionResult( 91 exception.getCode(), exception.getMessage())); 92 } 93 }); 94 95 return future; 96 } 97 isPriorityCallingState(int currentCallState)98 private boolean isPriorityCallingState(int currentCallState) { 99 return ConnectionServiceFocusManager.PRIORITY_FOCUS_CALL_STATE.contains(currentCallState); 100 } 101 canBecomeNewCallFocus(int currentCallState)102 private boolean canBecomeNewCallFocus(int currentCallState) { 103 return isPriorityCallingState(currentCallState) || currentCallState == CallState.ON_HOLD; 104 } 105 }