• 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.TelecomManager.TELECOM_TRANSACTION_SUCCESS;
20 import static android.telecom.CallException.CODE_OPERATION_TIMED_OUT;
21 
22 import android.os.Bundle;
23 import android.os.RemoteException;
24 import android.os.ResultReceiver;
25 import android.telecom.CallAttributes;
26 import android.telecom.DisconnectCause;
27 import android.util.Log;
28 
29 import com.android.internal.telecom.ICallEventCallback;
30 import com.android.server.telecom.TelecomSystem;
31 import com.android.server.telecom.TransactionalServiceWrapper;
32 
33 import java.util.concurrent.CompletableFuture;
34 import java.util.concurrent.CompletionStage;
35 import java.util.concurrent.CountDownLatch;
36 import java.util.concurrent.TimeUnit;
37 
38 /**
39  * SRP: using the ICallEventCallback binder, reach out to the client for the pending call event and
40  * get an acknowledgement that the call event can be completed.
41  */
42 public class CallEventCallbackAckTransaction extends VoipCallTransaction {
43     private static final String TAG = CallEventCallbackAckTransaction.class.getSimpleName();
44     private final ICallEventCallback mICallEventCallback;
45     private final String mAction;
46     private final String mCallId;
47     // optional values
48     private int mVideoState = CallAttributes.AUDIO_CALL;
49     private DisconnectCause mDisconnectCause = null;
50 
51     private final VoipCallTransactionResult TRANSACTION_FAILED = new VoipCallTransactionResult(
52             CODE_OPERATION_TIMED_OUT, "failed to complete the operation before timeout");
53 
54     private static class AckResultReceiver extends ResultReceiver {
55         CountDownLatch mCountDownLatch;
56 
AckResultReceiver(CountDownLatch latch)57         public AckResultReceiver(CountDownLatch latch) {
58             super(null);
59             mCountDownLatch = latch;
60         }
61 
62         @Override
onReceiveResult(int resultCode, Bundle resultData)63         protected void onReceiveResult(int resultCode, Bundle resultData) {
64             if (resultCode == TELECOM_TRANSACTION_SUCCESS) {
65                 mCountDownLatch.countDown();
66             }
67         }
68     }
69 
CallEventCallbackAckTransaction(ICallEventCallback service, String action, String callId, TelecomSystem.SyncRoot lock)70     public CallEventCallbackAckTransaction(ICallEventCallback service, String action,
71             String callId, TelecomSystem.SyncRoot lock) {
72         super(lock);
73         mICallEventCallback = service;
74         mAction = action;
75         mCallId = callId;
76     }
77 
78 
CallEventCallbackAckTransaction(ICallEventCallback service, String action, String callId, int videoState, TelecomSystem.SyncRoot lock)79     public CallEventCallbackAckTransaction(ICallEventCallback service, String action, String callId,
80             int videoState, TelecomSystem.SyncRoot lock) {
81         super(lock);
82         mICallEventCallback = service;
83         mAction = action;
84         mCallId = callId;
85         mVideoState = videoState;
86     }
87 
CallEventCallbackAckTransaction(ICallEventCallback service, String action, String callId, DisconnectCause cause, TelecomSystem.SyncRoot lock)88     public CallEventCallbackAckTransaction(ICallEventCallback service, String action, String callId,
89             DisconnectCause cause, TelecomSystem.SyncRoot lock) {
90         super(lock);
91         mICallEventCallback = service;
92         mAction = action;
93         mCallId = callId;
94         mDisconnectCause = cause;
95     }
96 
97 
98     @Override
processTransaction(Void v)99     public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
100         Log.d(TAG, "processTransaction");
101         CountDownLatch latch = new CountDownLatch(1);
102         ResultReceiver receiver = new AckResultReceiver(latch);
103 
104         try {
105             switch (mAction) {
106                 case TransactionalServiceWrapper.ON_SET_INACTIVE:
107                     mICallEventCallback.onSetInactive(mCallId, receiver);
108                     break;
109                 case TransactionalServiceWrapper.ON_DISCONNECT:
110                     mICallEventCallback.onDisconnect(mCallId, mDisconnectCause, receiver);
111                     break;
112                 case TransactionalServiceWrapper.ON_SET_ACTIVE:
113                     mICallEventCallback.onSetActive(mCallId, receiver);
114                     break;
115                 case TransactionalServiceWrapper.ON_ANSWER:
116                     mICallEventCallback.onAnswer(mCallId, mVideoState, receiver);
117                     break;
118                 case TransactionalServiceWrapper.ON_STREAMING_STARTED:
119                     mICallEventCallback.onCallStreamingStarted(mCallId, receiver);
120                     break;
121             }
122         } catch (RemoteException remoteException) {
123             return CompletableFuture.completedFuture(TRANSACTION_FAILED);
124         }
125 
126         try {
127             // wait for the client to ack that CallEventCallback
128             boolean success = latch.await(VoipCallTransaction.TIMEOUT_LIMIT, TimeUnit.MILLISECONDS);
129             if (!success) {
130                 // client send onError and failed to complete transaction
131                 Log.i(TAG, String.format("CallEventCallbackAckTransaction:"
132                         + " client failed to complete the [%s] transaction", mAction));
133                 return CompletableFuture.completedFuture(TRANSACTION_FAILED);
134             } else {
135                 // success
136                 return CompletableFuture.completedFuture(
137                         new VoipCallTransactionResult(VoipCallTransactionResult.RESULT_SUCCEED,
138                                 "success"));
139             }
140         } catch (InterruptedException ie) {
141             return CompletableFuture.completedFuture(TRANSACTION_FAILED);
142         }
143     }
144 }
145