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