blob: 941c248b18e8e5f758125551673ecdd657a273a4 [file] [log] [blame]
Santos Cordon80d9bdc2014-02-13 18:28:46 -08001/*
2 * Copyright 2014, 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
17package com.android.telecomm;
18
19import android.os.Handler;
20import android.os.Looper;
21
22import com.android.telecomm.ServiceBinder.BindCallback;
23import com.google.common.base.Preconditions;
24import com.google.common.collect.Maps;
25
26import java.util.Map;
27
28/**
29 * Utility class to confirm the existence of an incoming call after receiving an incoming-call
30 * intent, see {@link TelecommReceiver}. Binds with the specified call services and requests
31 * confirmation of incoming calls using call tokens provided as part of the intent. Upon receipt of
32 * the confirmation, yields execution back to the switchboard to complete the incoming sequence. The
33 * entire process is timeboxed to protect against unresponsive call services.
34 */
35final class IncomingCallsManager {
36
37 /**
38 * The amount of time to wait for confirmation of an incoming call, in milliseconds.
39 * TODO(santoscordon): Likely needs adjustment.
40 */
41 private static final int INCOMING_CALL_TIMEOUT_MS = 1000;
42
43 private final Switchboard mSwitchboard;
44
45 private final Handler mHandler = new Handler(Looper.getMainLooper());
46
47 /** Maps incoming calls to their call services. */
48 private final Map<Call, CallServiceWrapper> mPendingIncomingCalls = Maps.newHashMap();
49
50 /**
51 * Persists the specified parameters.
52 *
53 * @param switchboard The switchboard.
54 */
55 IncomingCallsManager(Switchboard switchboard) {
56 mSwitchboard = switchboard;
57 }
58
59
60 /**
61 * Confirms the existence of an incoming call with the specified call service (asynchronously).
62 * Starts the timeout sequence in case the call service is unresponsive.
63 *
64 * @param call The call object.
65 * @param callService The call service.
66 * @param callToken The token used by the call service to identify the incoming call.
67 */
68 void confirmIncomingCall(
69 final Call call, final CallServiceWrapper callService, String callToken) {
70
71 ThreadUtil.checkOnMainThread();
72 // Just to be safe, lets make sure we're not already processing this call.
73 Preconditions.checkState(!mPendingIncomingCalls.containsKey(call));
74
75 mPendingIncomingCalls.put(call, callService);
76 startTimeoutForCall(call);
77
78 BindCallback callback = new BindCallback() {
79 @Override public void onSuccess() {
80 // TODO(santoscordon): ICallService needs to be updated with the following method.
81 // Confirmation won't work until this method is filled in.
82 // callService.confirmIncomingCall(call.toCallInfo(), callToken);
83 }
84 @Override public void onFailure() {
85 handleFailedIncomingCall(call);
86 }
87 };
88
89 callService.bind(callback);
90 }
91
92 /**
93 * Starts a timeout to timebox the confirmation of an incoming call. When the timeout expires,
94 * it will notify switchboard that the incoming call was not confirmed and thus does not exist
95 * as far as Telecomm is concerned.
96 *
97 * @param call The call.
98 */
99 void startTimeoutForCall(final Call call) {
100 Runnable timeoutCallback = new Runnable() {
101 @Override public void run() {
102 handleFailedIncomingCall(call);
103 }
104 };
105 mHandler.postDelayed(timeoutCallback, INCOMING_CALL_TIMEOUT_MS);
106 }
107
108 /**
109 * Notifies the switchboard of a successful incoming call after removing it from the pending
110 * list.
111 * TODO(santoscordon): Needs code in CallServiceAdapter to call this method.
112 *
113 * @param call The call.
114 */
115 void handleSuccessfulIncomingCall(Call call) {
116 ThreadUtil.checkOnMainThread();
117 if (mPendingIncomingCalls.remove(call) != null) {
118 mSwitchboard.handleSuccessfulIncomingCall(call);
119 }
120 }
121
122 /**
123 * Notifies switchboard of the failed incoming call after removing it from the pending list.
124 *
125 * @param call The call.
126 */
127 void handleFailedIncomingCall(Call call) {
128 ThreadUtil.checkOnMainThread();
129 if (mPendingIncomingCalls.remove(call) != null) {
130 // The call was found still waiting for confirmation. Consider it failed.
131 mSwitchboard.handleFailedIncomingCall(call);
132 }
133 }
134}