blob: 1539cbf946b3049126cf100178d405e10af67e0e [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;
Santos Cordon493e8f22014-02-19 03:15:12 -080021import android.telecomm.CallInfo;
22import android.util.Log;
Santos Cordon80d9bdc2014-02-13 18:28:46 -080023
Santos Cordon80d9bdc2014-02-13 18:28:46 -080024import com.google.common.base.Preconditions;
25import com.google.common.collect.Maps;
26
27import java.util.Map;
28
29/**
Santos Cordon493e8f22014-02-19 03:15:12 -080030 * Utility class to retrieve details of an incoming call after receiving an incoming-call intent,
31 * see {@link CallActivity}. Binds with the specified call services and requests details of incoming
32 * calls. Upon receipt of the details, yields execution back to the switchboard to complete the
33 * incoming sequence. The entire process is timeboxed to protect against unresponsive call services.
Santos Cordon80d9bdc2014-02-13 18:28:46 -080034 */
35final class IncomingCallsManager {
36
Santos Cordon493e8f22014-02-19 03:15:12 -080037 private static final String TAG = IncomingCallsManager.class.getSimpleName();
38
Santos Cordon80d9bdc2014-02-13 18:28:46 -080039 /**
Santos Cordon493e8f22014-02-19 03:15:12 -080040 * The amount of time to wait for details of an incoming call, in milliseconds.
Santos Cordon80d9bdc2014-02-13 18:28:46 -080041 * TODO(santoscordon): Likely needs adjustment.
42 */
43 private static final int INCOMING_CALL_TIMEOUT_MS = 1000;
44
45 private final Switchboard mSwitchboard;
46
47 private final Handler mHandler = new Handler(Looper.getMainLooper());
48
Santos Cordon493e8f22014-02-19 03:15:12 -080049 /** Maps call ID to the call. */
50 private final Map<String, Call> mPendingIncomingCalls = Maps.newHashMap();
Santos Cordon80d9bdc2014-02-13 18:28:46 -080051
52 /**
53 * Persists the specified parameters.
54 *
55 * @param switchboard The switchboard.
56 */
57 IncomingCallsManager(Switchboard switchboard) {
58 mSwitchboard = switchboard;
59 }
60
Santos Cordon80d9bdc2014-02-13 18:28:46 -080061 /**
Santos Cordon493e8f22014-02-19 03:15:12 -080062 * Retrieves details of an incoming call through its associated call service (asynchronously).
Santos Cordon80d9bdc2014-02-13 18:28:46 -080063 * Starts the timeout sequence in case the call service is unresponsive.
64 *
65 * @param call The call object.
Santos Cordon80d9bdc2014-02-13 18:28:46 -080066 */
Santos Cordon493e8f22014-02-19 03:15:12 -080067 void retrieveIncomingCall(Call call) {
Santos Cordon80d9bdc2014-02-13 18:28:46 -080068 ThreadUtil.checkOnMainThread();
Santos Cordon493e8f22014-02-19 03:15:12 -080069 Log.d(TAG, "retrieveIncomingCall");
Santos Cordon80d9bdc2014-02-13 18:28:46 -080070
Santos Cordon493e8f22014-02-19 03:15:12 -080071 final String callId = call.getId();
72 // Just to be safe, lets make sure we're not already processing this call.
73 Preconditions.checkState(!mPendingIncomingCalls.containsKey(callId));
74
75 mPendingIncomingCalls.put(callId, call);
76
77 // TODO(santoscordon): Timeout will not be necessary after cleanup via tick() is implemented
78 // in Switchboard.
Santos Cordon80d9bdc2014-02-13 18:28:46 -080079 startTimeoutForCall(call);
80
Santos Cordon493e8f22014-02-19 03:15:12 -080081 Runnable errorCallback = getFailedIncomingCallback(call);
82 call.getCallService().retrieveIncomingCall(callId, errorCallback);
Santos Cordon80d9bdc2014-02-13 18:28:46 -080083 }
84
85 /**
86 * Notifies the switchboard of a successful incoming call after removing it from the pending
87 * list.
Santos Cordon80d9bdc2014-02-13 18:28:46 -080088 *
Santos Cordon493e8f22014-02-19 03:15:12 -080089 * @param callInfo The details of the call.
Santos Cordon80d9bdc2014-02-13 18:28:46 -080090 */
Santos Cordon493e8f22014-02-19 03:15:12 -080091 void handleSuccessfulIncomingCall(CallInfo callInfo) {
Santos Cordon80d9bdc2014-02-13 18:28:46 -080092 ThreadUtil.checkOnMainThread();
Santos Cordon493e8f22014-02-19 03:15:12 -080093
94 Call call = mPendingIncomingCalls.remove(callInfo.getId());
95 if (call != null) {
96 Log.d(TAG, "Incoming call " + call.getId() + " found.");
97 call.setHandle(callInfo.getHandle());
98 call.setState(callInfo.getState());
99
Santos Cordon80d9bdc2014-02-13 18:28:46 -0800100 mSwitchboard.handleSuccessfulIncomingCall(call);
101 }
102 }
103
104 /**
105 * Notifies switchboard of the failed incoming call after removing it from the pending list.
106 *
107 * @param call The call.
108 */
Santos Cordon493e8f22014-02-19 03:15:12 -0800109 private void handleFailedIncomingCall(Call call) {
Santos Cordon80d9bdc2014-02-13 18:28:46 -0800110 ThreadUtil.checkOnMainThread();
Santos Cordon493e8f22014-02-19 03:15:12 -0800111
112 if (mPendingIncomingCalls.remove(call.getId()) != null) {
113 Log.i(TAG, "Failed to get details for incoming call " + call);
114 // The call was found still waiting for details. Consider it failed.
Santos Cordon80d9bdc2014-02-13 18:28:46 -0800115 mSwitchboard.handleFailedIncomingCall(call);
116 }
117 }
Santos Cordon493e8f22014-02-19 03:15:12 -0800118
119 /**
120 * Starts a timeout to timebox the retrieval of an incoming call. When the timeout expires,
121 * it will notify switchboard that the incoming call was not retrieved and thus does not exist
122 * as far as Telecomm is concerned.
123 *
124 * @param call The call.
125 */
126 private void startTimeoutForCall(Call call) {
127 Runnable timeoutCallback = getFailedIncomingCallback(call);
128 mHandler.postDelayed(timeoutCallback, INCOMING_CALL_TIMEOUT_MS);
129 }
130
131 /**
132 * Returns a runnable to be invoked upon failure to get details for an incoming call.
133 *
134 * @param call The failed incoming call.
135 */
136 private Runnable getFailedIncomingCallback(final Call call) {
137 return new Runnable() {
138 @Override public void run() {
139 handleFailedIncomingCall(call);
140 }
141 };
142 }
Santos Cordon80d9bdc2014-02-13 18:28:46 -0800143}