blob: 063469dd9e9cb67304ea1c2ae31194a0cec99c29 [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
Santos Cordon80d9bdc2014-02-13 18:28:46 -080059 /**
60 * Confirms the existence of an incoming call with the specified call service (asynchronously).
61 * Starts the timeout sequence in case the call service is unresponsive.
62 *
63 * @param call The call object.
64 * @param callService The call service.
65 * @param callToken The token used by the call service to identify the incoming call.
66 */
67 void confirmIncomingCall(
68 final Call call, final CallServiceWrapper callService, String callToken) {
69
70 ThreadUtil.checkOnMainThread();
71 // Just to be safe, lets make sure we're not already processing this call.
72 Preconditions.checkState(!mPendingIncomingCalls.containsKey(call));
73
74 mPendingIncomingCalls.put(call, callService);
75 startTimeoutForCall(call);
76
77 BindCallback callback = new BindCallback() {
78 @Override public void onSuccess() {
79 // TODO(santoscordon): ICallService needs to be updated with the following method.
80 // Confirmation won't work until this method is filled in.
81 // callService.confirmIncomingCall(call.toCallInfo(), callToken);
82 }
83 @Override public void onFailure() {
84 handleFailedIncomingCall(call);
85 }
86 };
87
88 callService.bind(callback);
89 }
90
91 /**
92 * Starts a timeout to timebox the confirmation of an incoming call. When the timeout expires,
93 * it will notify switchboard that the incoming call was not confirmed and thus does not exist
94 * as far as Telecomm is concerned.
95 *
96 * @param call The call.
97 */
98 void startTimeoutForCall(final Call call) {
99 Runnable timeoutCallback = new Runnable() {
100 @Override public void run() {
101 handleFailedIncomingCall(call);
102 }
103 };
104 mHandler.postDelayed(timeoutCallback, INCOMING_CALL_TIMEOUT_MS);
105 }
106
107 /**
108 * Notifies the switchboard of a successful incoming call after removing it from the pending
109 * list.
110 * TODO(santoscordon): Needs code in CallServiceAdapter to call this method.
111 *
112 * @param call The call.
113 */
114 void handleSuccessfulIncomingCall(Call call) {
115 ThreadUtil.checkOnMainThread();
116 if (mPendingIncomingCalls.remove(call) != null) {
117 mSwitchboard.handleSuccessfulIncomingCall(call);
118 }
119 }
120
121 /**
122 * Notifies switchboard of the failed incoming call after removing it from the pending list.
123 *
124 * @param call The call.
125 */
126 void handleFailedIncomingCall(Call call) {
127 ThreadUtil.checkOnMainThread();
128 if (mPendingIncomingCalls.remove(call) != null) {
129 // The call was found still waiting for confirmation. Consider it failed.
130 mSwitchboard.handleFailedIncomingCall(call);
131 }
132 }
133}