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