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.telecom.CallException; 20 21 import com.android.server.telecom.LoggedHandlerExecutor; 22 import com.android.server.telecom.TelecomSystem; 23 24 import java.util.List; 25 import java.util.concurrent.CompletableFuture; 26 import java.util.concurrent.atomic.AtomicInteger; 27 28 /** 29 * A VoipCallTransaction implementation that its sub transactions will be executed in serial 30 */ 31 public class SerialTransaction extends VoipCallTransaction { SerialTransaction(List<VoipCallTransaction> subTransactions, TelecomSystem.SyncRoot lock)32 public SerialTransaction(List<VoipCallTransaction> subTransactions, 33 TelecomSystem.SyncRoot lock) { 34 super(subTransactions, lock); 35 } 36 appendTransaction(VoipCallTransaction transaction)37 public void appendTransaction(VoipCallTransaction transaction){ 38 mSubTransactions.add(transaction); 39 } 40 41 @Override processTransactions()42 public void processTransactions() { 43 if (mSubTransactions == null || mSubTransactions.isEmpty()) { 44 scheduleTransaction(); 45 return; 46 } 47 TransactionManager.TransactionCompleteListener subTransactionListener = 48 new TransactionManager.TransactionCompleteListener() { 49 private final AtomicInteger mTransactionIndex = new AtomicInteger(0); 50 51 @Override 52 public void onTransactionCompleted(VoipCallTransactionResult result, 53 String transactionName) { 54 if (result.getResult() != VoipCallTransactionResult.RESULT_SUCCEED) { 55 handleTransactionFailure(); 56 CompletableFuture.completedFuture(null).thenApplyAsync( 57 (x) -> { 58 finish(result); 59 mCompleteListener.onTransactionCompleted(result, 60 mTransactionName); 61 return null; 62 }, new LoggedHandlerExecutor(mHandler, 63 mTransactionName + "@" + hashCode() 64 + ".oTC", mLock)); 65 } else { 66 int currTransactionIndex = mTransactionIndex.incrementAndGet(); 67 if (currTransactionIndex < mSubTransactions.size()) { 68 VoipCallTransaction transaction = mSubTransactions.get( 69 currTransactionIndex); 70 transaction.setCompleteListener(this); 71 transaction.start(); 72 } else { 73 scheduleTransaction(); 74 } 75 } 76 } 77 78 @Override 79 public void onTransactionTimeout(String transactionName) { 80 handleTransactionFailure(); 81 CompletableFuture.completedFuture(null).thenApplyAsync( 82 (x) -> { 83 VoipCallTransactionResult mainResult = 84 new VoipCallTransactionResult( 85 CallException.CODE_OPERATION_TIMED_OUT, 86 String.format("sub transaction %s timed out", 87 transactionName)); 88 finish(mainResult); 89 mCompleteListener.onTransactionCompleted(mainResult, 90 mTransactionName); 91 return null; 92 }, new LoggedHandlerExecutor(mHandler, 93 mTransactionName + "@" + hashCode() 94 + ".oTT", mLock)); 95 } 96 }; 97 VoipCallTransaction transaction = mSubTransactions.get(0); 98 transaction.setCompleteListener(subTransactionListener); 99 transaction.start(); 100 101 } 102 handleTransactionFailure()103 public void handleTransactionFailure() {} 104 } 105