• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.telecom.CallException.CODE_OPERATION_TIMED_OUT;
20 
21 import android.os.OutcomeReceiver;
22 import android.telecom.TelecomManager;
23 import android.telecom.CallException;
24 import android.util.Log;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 
28 import java.util.ArrayDeque;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Queue;
32 
33 public class TransactionManager {
34     private static final String TAG = "VoipCallTransactionManager";
35     private static TransactionManager INSTANCE = null;
36     private static final Object sLock = new Object();
37     private Queue<VoipCallTransaction> mTransactions;
38     private VoipCallTransaction mCurrentTransaction;
39 
40     public interface TransactionCompleteListener {
onTransactionCompleted(VoipCallTransactionResult result, String transactionName)41         void onTransactionCompleted(VoipCallTransactionResult result, String transactionName);
onTransactionTimeout(String transactionName)42         void onTransactionTimeout(String transactionName);
43     }
44 
TransactionManager()45     private TransactionManager() {
46         mTransactions = new ArrayDeque<>();
47         mCurrentTransaction = null;
48     }
49 
getInstance()50     public static TransactionManager getInstance() {
51         synchronized (sLock) {
52             if (INSTANCE == null) {
53                 INSTANCE = new TransactionManager();
54             }
55         }
56         return INSTANCE;
57     }
58 
59     @VisibleForTesting
getTestInstance()60     public static TransactionManager getTestInstance() {
61         return new TransactionManager();
62     }
63 
addTransaction(VoipCallTransaction transaction, OutcomeReceiver<VoipCallTransactionResult, CallException> receiver)64     public void addTransaction(VoipCallTransaction transaction,
65             OutcomeReceiver<VoipCallTransactionResult, CallException> receiver) {
66         synchronized (sLock) {
67             mTransactions.add(transaction);
68         }
69         transaction.setCompleteListener(new TransactionCompleteListener() {
70             @Override
71             public void onTransactionCompleted(VoipCallTransactionResult result,
72                     String transactionName){
73                 Log.i(TAG, String.format("transaction %s completed: with result=[%d]",
74                         transactionName, result.getResult()));
75                 if (result.getResult() == TelecomManager.TELECOM_TRANSACTION_SUCCESS) {
76                     receiver.onResult(result);
77                 } else {
78                     receiver.onError(
79                             new CallException(result.getMessage(),
80                                     result.getResult()));
81                 }
82                 finishTransaction();
83             }
84 
85             @Override
86             public void onTransactionTimeout(String transactionName){
87                 Log.i(TAG, String.format("transaction %s timeout", transactionName));
88                 receiver.onError(new CallException(transactionName + " timeout",
89                         CODE_OPERATION_TIMED_OUT));
90                 finishTransaction();
91             }
92         });
93 
94         startTransactions();
95     }
96 
startTransactions()97     private void startTransactions() {
98         synchronized (sLock) {
99             if (mTransactions.isEmpty()) {
100                 // No transaction waiting for process
101                 return;
102             }
103 
104             if (mCurrentTransaction != null) {
105                 // Ongoing transaction
106                 return;
107             }
108             mCurrentTransaction = mTransactions.poll();
109         }
110         mCurrentTransaction.start();
111     }
112 
finishTransaction()113     private void finishTransaction() {
114         synchronized (sLock) {
115             mCurrentTransaction = null;
116         }
117         startTransactions();
118     }
119 
120     @VisibleForTesting
clear()121     public void clear() {
122         List<VoipCallTransaction> pendingTransactions;
123         synchronized (sLock) {
124             pendingTransactions = new ArrayList<>(mTransactions);
125         }
126         for (VoipCallTransaction transaction : pendingTransactions) {
127             transaction.finish();
128         }
129     }
130 }
131