1 /*
2  * Copyright (C) 2019 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 android.telecom.cts.redirectiontestapp;
18 
19 import android.app.Service;
20 import android.content.ComponentName;
21 import android.content.Intent;
22 import android.net.Uri;
23 import android.telecom.PhoneAccountHandle;
24 import android.os.IBinder;
25 import android.telecom.CallRedirectionService;
26 import android.util.Log;
27 
28 import java.util.concurrent.CountDownLatch;
29 import java.util.concurrent.TimeUnit;
30 
31 public class CtsCallRedirectionServiceController extends Service {
32     private static final String TAG = CallRedirectionService.class.getSimpleName();
33     public static final String CONTROL_INTERFACE_ACTION =
34             "android.telecom.cts.redirectiontestapp.ACTION_CONTROL_CALL_REDIRECTION_SERVICE";
35     public static final ComponentName CONTROL_INTERFACE_COMPONENT =
36             ComponentName.unflattenFromString(
37                     "android.telecom.cts.redirectiontestapp/.CtsCallRedirectionServiceController");
38 
39     // Constants for call redirection decisions
40     public static final int NO_DECISION_YET = 0;
41     public static final int RESPONSE_TIMEOUT = 1;
42     public static final int PLACE_CALL_UNMODIFIED = 2;
43     public static final int PLACE_REDIRECTED_CALL = 3;
44     public static final int CANCEL_CALL = 4;
45     public static final long TIMEOUT = 6000;
46 
47     private int mDecision = NO_DECISION_YET;
48 
49     // Redirection information, only valid if decision is PLACE_REDIRECTED_CALL.
50     private Uri mTargetHandle = null;
51     private Uri mDestinationUri = null;
52     private PhoneAccountHandle mRedirectedPhoneAccount = null;
53     private PhoneAccountHandle mOriginalPhoneAccount = null;
54     private boolean mConfirmFirst = false;
55     private CountDownLatch mTimeoutNotified = new CountDownLatch(1);
56     private CountDownLatch mOnPlaceCallInvoked = new CountDownLatch(1);
57 
58     private static CtsCallRedirectionServiceController sCallRedirectionServiceController = null;
59 
60     private final IBinder mControllerInterface = new ICtsCallRedirectionServiceController.Stub() {
61                 @Override
62                 public void reset() {
63                     mDecision = NO_DECISION_YET;
64                     mTimeoutNotified = new CountDownLatch(1);
65                     mOnPlaceCallInvoked = new CountDownLatch(1);
66                 }
67 
68                 @Override
69                 public void setRedirectCall(Uri targetHandle,
70                                             PhoneAccountHandle redirectedPhoneAccount,
71                                             boolean confirmFirst) {
72                     Log.i(TAG, "redirectCall");
73                     mDecision = PLACE_REDIRECTED_CALL;
74                     mTargetHandle = targetHandle;
75                     mRedirectedPhoneAccount = redirectedPhoneAccount;
76                     mConfirmFirst = confirmFirst;
77                 }
78 
79                 @Override
80                 public void setCancelCall() {
81                     Log.i(TAG, "cancelCall");
82                     mDecision = CANCEL_CALL;
83                 }
84 
85                 @Override
86                 public void setPlaceCallUnmodified() {
87                     Log.i(TAG, "placeCallUnmodified");
88                     mDecision = PLACE_CALL_UNMODIFIED;
89                 }
90 
91                 @Override
92                 public void setWaitForTimeout() {
93                     Log.i(TAG, "setWaitForTimeout");
94                     mDecision = RESPONSE_TIMEOUT;
95                 }
96 
97                 @Override
98                 public boolean waitForTimeoutNotified() {
99                     Log.i(TAG, "waitForTimeoutNotified");
100                     try {
101                         return mTimeoutNotified.await(TIMEOUT, TimeUnit.MILLISECONDS);
102                     } catch (InterruptedException e) {
103                         return false;
104                     }
105                 }
106 
107                 @Override
108                 public boolean waitForOnPlaceCallInvoked() {
109                     try {
110                         return mOnPlaceCallInvoked.await(TIMEOUT, TimeUnit.MILLISECONDS);
111                     } catch (InterruptedException e) {
112                         return false;
113                     }
114                 }
115             };
116 
getInstance()117     public static CtsCallRedirectionServiceController getInstance() {
118         return sCallRedirectionServiceController;
119     }
120 
121     @Override
onBind(Intent intent)122     public IBinder onBind(Intent intent) {
123         if (CONTROL_INTERFACE_ACTION.equals(intent.getAction())) {
124             Log.i(TAG, "onBind: returning control interface");
125             sCallRedirectionServiceController = this;
126             return mControllerInterface;
127         }
128         Log.i(TAG, "onBind: ACTION is not matched");
129         return null;
130     }
131 
132     @Override
onUnbind(Intent intent)133     public boolean onUnbind(Intent intent) {
134         sCallRedirectionServiceController = null;
135         return false;
136     }
137 
getCallRedirectionDecision()138     public int getCallRedirectionDecision() {
139         return mDecision;
140     }
141 
getTargetHandle()142     public Uri getTargetHandle() {
143         return mTargetHandle;
144     }
145 
getTargetPhoneAccount()146     public PhoneAccountHandle getTargetPhoneAccount() {
147         return mRedirectedPhoneAccount != null ? mRedirectedPhoneAccount : mOriginalPhoneAccount;
148     }
149 
setOriginalPhoneAccount(PhoneAccountHandle originalPhoneAccount)150     public void setOriginalPhoneAccount(PhoneAccountHandle originalPhoneAccount) {
151         mOriginalPhoneAccount = originalPhoneAccount;
152     }
153 
setDestinationUri(Uri destinationUri)154     public void setDestinationUri(Uri destinationUri) {
155         mDestinationUri = destinationUri;
156     }
157 
isConfirmFirst()158     public boolean isConfirmFirst() {
159         return mConfirmFirst;
160     }
161 
timeoutNotified()162     public void timeoutNotified() {
163         mTimeoutNotified.countDown();
164     }
165 
onPlaceCallInvoked()166     public void onPlaceCallInvoked() {
167         mOnPlaceCallInvoked.countDown();
168     }
169 }
170