1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/* 2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2017 The Android Open Source Project 3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License"); 5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License. 6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at 7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * http://www.apache.org/licenses/LICENSE-2.0 9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software 11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS, 12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and 14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License 15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.incallui.call; 18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context; 20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Handler; 21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Message; 22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Trace; 23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.NonNull; 24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.Nullable; 25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.VisibleForTesting; 26ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.v4.os.BuildCompat; 27ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.Call; 28ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.DisconnectCause; 29ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.PhoneAccount; 30ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.util.ArrayMap; 31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; 32ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.blocking.FilteredNumbersUtil; 33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.Assert; 34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.LogUtil; 352f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.enrichedcall.EnrichedCallComponent; 362f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.enrichedcall.EnrichedCallManager; 3710b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanianimport com.android.dialer.location.GeoUtil; 388369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanianimport com.android.dialer.logging.DialerImpression; 39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.logging.Logger; 40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.shortcuts.ShortcutUsageReporter; 41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.spam.Spam; 42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.spam.SpamBindings; 43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.DialerCall.State; 44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.latencyreport.LatencyReport; 45ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.util.TelecomCallUtil; 469050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanianimport com.android.incallui.videotech.utils.SessionModificationState; 47ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Collections; 48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Iterator; 49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Map; 50ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Objects; 51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Set; 52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.concurrent.ConcurrentHashMap; 53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/** 55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Maintains the list of active calls and notifies interested classes of changes to the call list as 56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * they are received from the telephony stack. Primary listener of changes to this class is 57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * InCallPresenter. 58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic class CallList implements DialerCallDelegate { 60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int DISCONNECTED_CALL_SHORT_TIMEOUT_MS = 200; 62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int DISCONNECTED_CALL_MEDIUM_TIMEOUT_MS = 2000; 63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int DISCONNECTED_CALL_LONG_TIMEOUT_MS = 5000; 64ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int EVENT_DISCONNECTED_TIMEOUT = 1; 66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static CallList sInstance = new CallList(); 68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final Map<String, DialerCall> mCallById = new ArrayMap<>(); 70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final Map<android.telecom.Call, DialerCall> mCallByTelecomCall = new ArrayMap<>(); 71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is load factor before 74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * resizing, 1 means we only expect a single thread to access the map so make only a single shard 75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final Set<Listener> mListeners = 77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Collections.newSetFromMap(new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final Set<DialerCall> mPendingDisconnectCalls = 80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Collections.newSetFromMap(new ConcurrentHashMap<DialerCall, Boolean>(8, 0.9f, 1)); 81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Handles the timeout for destroying disconnected calls. */ 82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final Handler mHandler = 83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new Handler() { 84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void handleMessage(Message msg) { 86ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian switch (msg.what) { 87ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case EVENT_DISCONNECTED_TIMEOUT: 88ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.d("CallList.handleMessage", "EVENT_DISCONNECTED_TIMEOUT ", msg.obj); 89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian finishDisconnectedCall((DialerCall) msg.obj); 90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian default: 92ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.e("CallList.handleMessage", "Message not expected: " + msg.what); 93ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 95ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 96ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }; 97ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 98ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 99ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * USED ONLY FOR TESTING Testing-only constructor. Instance should only be acquired through 10010b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian * getRunningInstance(). 101ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 102ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @VisibleForTesting 103ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public CallList() {} 104ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 105d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian @VisibleForTesting 106d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian public static void setCallListInstance(CallList callList) { 107d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian sInstance = callList; 108d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian } 109d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian 110ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Static singleton accessor method. */ 111ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public static CallList getInstance() { 112ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return sInstance; 113ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 114ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 115ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onCallAdded( 116ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Context context, final android.telecom.Call telecomCall, LatencyReport latencyReport) { 117ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Trace.beginSection("onCallAdded"); 118ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final DialerCall call = 119ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new DialerCall(context, this, telecomCall, latencyReport, true /* registerCallback */); 120d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian logSecondIncomingCall(context, call); 121d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 1222f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian EnrichedCallManager manager = EnrichedCallComponent.get(context).getEnrichedCallManager(); 1232f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian manager.registerCapabilitiesListener(call); 1242f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian manager.registerStateChangedListener(call); 1252f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 126ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final DialerCallListenerImpl dialerCallListener = new DialerCallListenerImpl(call); 127ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.addListener(dialerCallListener); 128ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.d("CallList.onCallAdded", "callState=" + call.getState()); 129ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (Spam.get(context).isSpamEnabled()) { 130ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian String number = TelecomCallUtil.getNumber(telecomCall); 131ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Spam.get(context) 132ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian .checkSpamStatus( 133ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian number, 134ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian null, 135ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new SpamBindings.Listener() { 136ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 137ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onComplete(boolean isSpam) { 138d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian boolean isIncomingCall = 139d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian call.getState() == DialerCall.State.INCOMING 140d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian || call.getState() == DialerCall.State.CALL_WAITING; 141ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (isSpam) { 142d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian if (!isIncomingCall) { 143ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i( 144ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CallList.onCallAdded", 145ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "marking spam call as not spam because it's not an incoming call"); 146ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian isSpam = false; 147ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else if (isPotentialEmergencyCallback(context, call)) { 148ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i( 149ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CallList.onCallAdded", 150ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "marking spam call as not spam because an emergency call was made on this" 151ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian + " device recently"); 152ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian isSpam = false; 153ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 154ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 155ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 156d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian if (isIncomingCall) { 157d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian Logger.get(context) 158d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian .logCallImpression( 159d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian isSpam 160d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian ? DialerImpression.Type.INCOMING_SPAM_CALL 161d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian : DialerImpression.Type.INCOMING_NON_SPAM_CALL, 162d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian call.getUniqueCallId(), 163d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian call.getTimeAddedMs()); 164d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian } 165ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.setSpam(isSpam); 166ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian dialerCallListener.onDialerCallUpdate(); 167ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 168ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }); 169ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 170ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateUserMarkedSpamStatus(call, context, number, dialerCallListener); 171ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 172ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 173ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler = 174ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new FilteredNumberAsyncQueryHandler(context); 175ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 176ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian filteredNumberAsyncQueryHandler.isBlockedNumber( 177ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new FilteredNumberAsyncQueryHandler.OnCheckBlockedListener() { 178ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 179ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onCheckComplete(Integer id) { 180ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (id != null && id != FilteredNumberAsyncQueryHandler.INVALID_ID) { 181ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.setBlockedStatus(true); 182ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian dialerCallListener.onDialerCallUpdate(); 183ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 184ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 185ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }, 186ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.getNumber(), 187ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian GeoUtil.getCurrentCountryIso(context)); 188ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 189ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call.getState() == DialerCall.State.INCOMING 190ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian || call.getState() == DialerCall.State.CALL_WAITING) { 191ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian onIncoming(call); 192ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 193ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian dialerCallListener.onDialerCallUpdate(); 194ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 195ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 196ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call.getState() != State.INCOMING) { 197ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Only report outgoing calls 198ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian ShortcutUsageReporter.onOutgoingCallAdded(context, call.getNumber()); 199ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 200ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 201ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Trace.endSection(); 202ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 203ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 204d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian private void logSecondIncomingCall(@NonNull Context context, @NonNull DialerCall incomingCall) { 205d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian DialerCall firstCall = getFirstCall(); 206d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (firstCall != null) { 2078369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian DialerImpression.Type impression; 208d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (firstCall.isVideoCall()) { 209d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (incomingCall.isVideoCall()) { 210d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian impression = DialerImpression.Type.VIDEO_CALL_WITH_INCOMING_VIDEO_CALL; 211d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } else { 212d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian impression = DialerImpression.Type.VIDEO_CALL_WITH_INCOMING_VOICE_CALL; 213d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 214d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } else { 215d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (incomingCall.isVideoCall()) { 216d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian impression = DialerImpression.Type.VOICE_CALL_WITH_INCOMING_VIDEO_CALL; 217d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } else { 218d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian impression = DialerImpression.Type.VOICE_CALL_WITH_INCOMING_VOICE_CALL; 219d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 220d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 2218369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian Assert.checkArgument(impression != null); 222d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian Logger.get(context) 223d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian .logCallImpression( 224d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian impression, incomingCall.getUniqueCallId(), incomingCall.getTimeAddedMs()); 225d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 226d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian } 227d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian 228ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static boolean isPotentialEmergencyCallback(Context context, DialerCall call) { 229ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (BuildCompat.isAtLeastO()) { 230ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return call.isPotentialEmergencyCallback(); 231ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 232ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian long timestampMillis = FilteredNumbersUtil.getLastEmergencyCallTimeMillis(context); 233ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return call.isInEmergencyCallbackWindow(timestampMillis); 234ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 235ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 236ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 237ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 238ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getDialerCallFromTelecomCall(Call telecomCall) { 239ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return mCallByTelecomCall.get(telecomCall); 240ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 241ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 242ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void updateUserMarkedSpamStatus( 243ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final DialerCall call, 244ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Context context, 245ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian String number, 246ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final DialerCallListenerImpl dialerCallListener) { 247ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 248ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Spam.get(context) 249ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian .checkUserMarkedNonSpamStatus( 250ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian number, 251ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian null, 252ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new SpamBindings.Listener() { 253ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 254ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onComplete(boolean isInUserWhiteList) { 255ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.setIsInUserWhiteList(isInUserWhiteList); 256ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 257ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }); 258ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 259ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Spam.get(context) 260ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian .checkGlobalSpamListStatus( 261ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian number, 262ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian null, 263ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new SpamBindings.Listener() { 264ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 265ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onComplete(boolean isInGlobalSpamList) { 266ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.setIsInGlobalSpamList(isInGlobalSpamList); 267ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 268ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }); 269ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 270ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Spam.get(context) 271ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian .checkUserMarkedSpamStatus( 272ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian number, 273ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian null, 274ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new SpamBindings.Listener() { 275ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 276ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onComplete(boolean isInUserSpamList) { 277ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.setIsInUserSpamList(isInUserSpamList); 278ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 279ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian }); 280ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 281ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 282ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onCallRemoved(Context context, android.telecom.Call telecomCall) { 283ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCallByTelecomCall.containsKey(telecomCall)) { 284ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall call = mCallByTelecomCall.get(telecomCall); 285ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.checkArgument(!call.isExternalCall()); 286ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 2872f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian EnrichedCallManager manager = EnrichedCallComponent.get(context).getEnrichedCallManager(); 2882f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian manager.unregisterCapabilitiesListener(call); 2892f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian manager.unregisterStateChangedListener(call); 2902f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 291ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Don't log an already logged call. logCall() might be called multiple times 292ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // for the same call due to b/24109437. 293ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call.getLogState() != null && !call.getLogState().isLogged) { 294ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian getLegacyBindings(context).logCall(call); 295ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.getLogState().isLogged = true; 296ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 297ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 298ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (updateCallInMap(call)) { 299ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.w( 300ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian "CallList.onCallRemoved", "Removing call not previously disconnected " + call.getId()); 301ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 3022f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 3032f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian call.onRemovedFromCallList(); 304ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 305c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian 306c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian if (!hasLiveCall()) { 307c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian DialerCall.clearRestrictedCount(); 308c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian } 309ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 310ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 311ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian InCallUiLegacyBindings getLegacyBindings(Context context) { 312ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Objects.requireNonNull(context); 313ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 314ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Context application = context.getApplicationContext(); 315ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian InCallUiLegacyBindings legacyInstance = null; 316ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (application instanceof InCallUiLegacyBindingsFactory) { 317ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian legacyInstance = ((InCallUiLegacyBindingsFactory) application).newInCallUiLegacyBindings(); 318ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 319ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 320ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (legacyInstance == null) { 321ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian legacyInstance = new InCallUiLegacyBindingsStub(); 322ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 323ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return legacyInstance; 324ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 325ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 326ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 327ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Handles the case where an internal call has become an exteral call. We need to 328ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 329ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param context 330ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param telecomCall 331ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 332ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onInternalCallMadeExternal(Context context, android.telecom.Call telecomCall) { 333ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 334ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCallByTelecomCall.containsKey(telecomCall)) { 335ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall call = mCallByTelecomCall.get(telecomCall); 336ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 337ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Don't log an already logged call. logCall() might be called multiple times 338ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // for the same call due to b/24109437. 339ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call.getLogState() != null && !call.getLogState().isLogged) { 340ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian getLegacyBindings(context).logCall(call); 341ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.getLogState().isLogged = true; 342ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 343ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 344ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // When removing a call from the call list because it became an external call, we need to 345ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // ensure the callback is unregistered -- this is normally only done when calls disconnect. 346ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // However, the call won't be disconnected in this case. Also, logic in updateCallInMap 347ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // would just re-add the call anyways. 348ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.unregisterCallback(); 349ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCallById.remove(call.getId()); 350ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCallByTelecomCall.remove(telecomCall); 351ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 352ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 353ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 354ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Called when a single call has changed. */ 355ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void onIncoming(DialerCall call) { 356ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (updateCallInMap(call)) { 357ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("CallList.onIncoming", String.valueOf(call)); 358ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 359ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 360ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (Listener listener : mListeners) { 361ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian listener.onIncomingCall(call); 362ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 363ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 364ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 365ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void addListener(@NonNull Listener listener) { 366ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Objects.requireNonNull(listener); 367ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 368ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListeners.add(listener); 369ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 370ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Let the listener know about the active calls immediately. 371ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian listener.onCallListChange(this); 372ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 373ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 374ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void removeListener(@Nullable Listener listener) { 375ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (listener != null) { 376ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mListeners.remove(listener); 377ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 378ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 379ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 380ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 381ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * TODO: Change so that this function is not needed. Instead of assuming there is an active call, 382ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * the code should rely on the status of a specific DialerCall and allow the presenters to update 383ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * the DialerCall object when the active call changes. 384ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 385ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getIncomingOrActive() { 386ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall retval = getIncomingCall(); 387ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (retval == null) { 388ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian retval = getActiveCall(); 389ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 390ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return retval; 391ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 392ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 393ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getOutgoingOrActive() { 394ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall retval = getOutgoingCall(); 395ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (retval == null) { 396ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian retval = getActiveCall(); 397ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 398ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return retval; 399ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 400ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 401ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** A call that is waiting for {@link PhoneAccount} selection */ 402ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getWaitingForAccountCall() { 403ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getFirstCallWithState(DialerCall.State.SELECT_PHONE_ACCOUNT); 404ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 405ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 406ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getPendingOutgoingCall() { 407ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getFirstCallWithState(DialerCall.State.CONNECTING); 408ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 409ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 410ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getOutgoingCall() { 411ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall call = getFirstCallWithState(DialerCall.State.DIALING); 412ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call == null) { 413ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call = getFirstCallWithState(DialerCall.State.REDIALING); 414ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 415ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call == null) { 416ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call = getFirstCallWithState(DialerCall.State.PULLING); 417ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 418ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return call; 419ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 420ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 421ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getActiveCall() { 422ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getFirstCallWithState(DialerCall.State.ACTIVE); 423ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 424ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 425ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getSecondActiveCall() { 426ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getCallWithState(DialerCall.State.ACTIVE, 1); 427ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 428ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 429ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getBackgroundCall() { 430ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getFirstCallWithState(DialerCall.State.ONHOLD); 431ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 432ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 433ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getDisconnectedCall() { 434ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getFirstCallWithState(DialerCall.State.DISCONNECTED); 435ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 436ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 437ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getDisconnectingCall() { 438ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getFirstCallWithState(DialerCall.State.DISCONNECTING); 439ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 440ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 441ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getSecondBackgroundCall() { 442ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getCallWithState(DialerCall.State.ONHOLD, 1); 443ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 444ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 445ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getActiveOrBackgroundCall() { 446ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall call = getActiveCall(); 447ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call == null) { 448ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call = getBackgroundCall(); 449ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 450ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return call; 451ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 452ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 453ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getIncomingCall() { 454ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall call = getFirstCallWithState(DialerCall.State.INCOMING); 455ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call == null) { 456ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call = getFirstCallWithState(DialerCall.State.CALL_WAITING); 457ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 458ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 459ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return call; 460ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 461ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 462ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getFirstCall() { 463ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall result = getIncomingCall(); 464ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (result == null) { 465ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian result = getPendingOutgoingCall(); 466ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 467ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (result == null) { 468ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian result = getOutgoingCall(); 469ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 470ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (result == null) { 471ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian result = getFirstCallWithState(DialerCall.State.ACTIVE); 472ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 473ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (result == null) { 474ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian result = getDisconnectingCall(); 475ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 476ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (result == null) { 477ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian result = getDisconnectedCall(); 478ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 479ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return result; 480ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 481ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 482ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public boolean hasLiveCall() { 483ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall call = getFirstCall(); 484ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return call != null && call != getDisconnectingCall() && call != getDisconnectedCall(); 485ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 486ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 487ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 488ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Returns the first call found in the call map with the upgrade to video modification state. 489ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 490ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @return The first call with the upgrade to video state. 491ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 492ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getVideoUpgradeRequestCall() { 493ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (DialerCall call : mCallById.values()) { 494d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian if (call.getVideoTech().getSessionModificationState() 4959050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian == SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) { 496ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return call; 497ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 498ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 499ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return null; 500ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 501ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 502ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getCallById(String callId) { 503ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return mCallById.get(callId); 504ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 505ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 506ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Returns first call found in the call map with the specified state. */ 507ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getFirstCallWithState(int state) { 508ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return getCallWithState(state, 0); 509ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 510ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 511ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 512ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Returns the [position]th call found in the call map with the specified state. TODO: Improve 513ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * this logic to sort by call time. 514ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 515ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public DialerCall getCallWithState(int state, int positionToFind) { 516ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall retval = null; 517ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian int position = 0; 518ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (DialerCall call : mCallById.values()) { 519ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call.getState() == state) { 520ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (position >= positionToFind) { 521ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian retval = call; 522ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 523ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else { 524ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian position++; 525ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 526ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 527ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 528ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 529ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return retval; 530ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 531ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 532ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 533ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * This is called when the service disconnects, either expectedly or unexpectedly. For the 534ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * expected case, it's because we have no calls left. For the unexpected case, it is likely a 535ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * crash of phone and we need to clean up our calls manually. Without phone, there can be no 536ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * active calls, so this is relatively safe thing to do. 537ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 538ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void clearOnDisconnect() { 539ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (DialerCall call : mCallById.values()) { 540ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int state = call.getState(); 541ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (state != DialerCall.State.IDLE 542ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian && state != DialerCall.State.INVALID 543ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian && state != DialerCall.State.DISCONNECTED) { 544ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 545ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.setState(DialerCall.State.DISCONNECTED); 546ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.setDisconnectCause(new DisconnectCause(DisconnectCause.UNKNOWN)); 547ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateCallInMap(call); 548ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 549ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 550ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian notifyGenericListeners(); 551ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 552ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 553ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 554ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Called when the user has dismissed an error dialog. This indicates acknowledgement of the 555ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * disconnect cause, and that any pending disconnects should immediately occur. 556ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 557ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onErrorDialogDismissed() { 558ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Iterator<DialerCall> iterator = mPendingDisconnectCalls.iterator(); 559ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian while (iterator.hasNext()) { 560ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian DialerCall call = iterator.next(); 561ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian iterator.remove(); 562ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian finishDisconnectedCall(call); 563ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 564ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 565ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 566ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 567ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Processes an update for a single call. 568ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 569ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param call The call to update. 570ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 5712f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian @VisibleForTesting 5722f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian void onUpdateCall(DialerCall call) { 573ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.d("CallList.onUpdateCall", String.valueOf(call)); 574ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (!mCallById.containsKey(call.getId()) && call.isExternalCall()) { 575ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // When a regular call becomes external, it is removed from the call list, and there may be 576ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // pending updates to Telecom which are queued up on the Telecom call's handler which we no 577ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // longer wish to cause updates to the call in the CallList. Bail here if the list of tracked 578ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // calls doesn't contain the call which received the update. 579ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 580ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 581ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 582ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (updateCallInMap(call)) { 583ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("CallList.onUpdateCall", String.valueOf(call)); 584ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 585ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 586ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 587ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 588ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Sends a generic notification to all listeners that something has changed. It is up to the 589ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * listeners to call back to determine what changed. 590ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 591ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void notifyGenericListeners() { 592ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (Listener listener : mListeners) { 593ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian listener.onCallListChange(this); 594ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 595ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 596ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 597ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void notifyListenersOfDisconnect(DialerCall call) { 598ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (Listener listener : mListeners) { 599ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian listener.onDisconnect(call); 600ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 601ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 602ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 603ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 604ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Updates the call entry in the local map. 605ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 606ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @return false if no call previously existed and no call was added, otherwise true. 607ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 608ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean updateCallInMap(DialerCall call) { 609ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Objects.requireNonNull(call); 610ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 611ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian boolean updated = false; 612ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 613ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call.getState() == DialerCall.State.DISCONNECTED) { 614ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // update existing (but do not add!!) disconnected calls 615ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mCallById.containsKey(call.getId())) { 616ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // For disconnected calls, we want to keep them alive for a few seconds so that the 617ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // UI has a chance to display anything it needs when a call is disconnected. 618ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 619ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Set up a timer to destroy the call after X seconds. 620ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final Message msg = mHandler.obtainMessage(EVENT_DISCONNECTED_TIMEOUT, call); 621ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mHandler.sendMessageDelayed(msg, getDelayForDisconnect(call)); 622ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mPendingDisconnectCalls.add(call); 623ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 624ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCallById.put(call.getId(), call); 625ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCallByTelecomCall.put(call.getTelecomCall(), call); 626ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updated = true; 627ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 628ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else if (!isCallDead(call)) { 629ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCallById.put(call.getId(), call); 630ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCallByTelecomCall.put(call.getTelecomCall(), call); 631ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updated = true; 632ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else if (mCallById.containsKey(call.getId())) { 633ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCallById.remove(call.getId()); 634ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mCallByTelecomCall.remove(call.getTelecomCall()); 635ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updated = true; 636ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 637ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 638ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return updated; 639ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 640ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 641ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private int getDelayForDisconnect(DialerCall call) { 642ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (call.getState() != DialerCall.State.DISCONNECTED) { 643ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian throw new IllegalStateException(); 644ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 645ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 646ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int cause = call.getDisconnectCause().getCode(); 647ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int delay; 648ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian switch (cause) { 649ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case DisconnectCause.LOCAL: 650ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian delay = DISCONNECTED_CALL_SHORT_TIMEOUT_MS; 651ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 652ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case DisconnectCause.REMOTE: 653ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case DisconnectCause.ERROR: 654ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian delay = DISCONNECTED_CALL_MEDIUM_TIMEOUT_MS; 655ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 656ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case DisconnectCause.REJECTED: 657ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case DisconnectCause.MISSED: 658ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian case DisconnectCause.CANCELED: 659ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // no delay for missed/rejected incoming calls and canceled outgoing calls. 660ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian delay = 0; 661ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 662ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian default: 663ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian delay = DISCONNECTED_CALL_LONG_TIMEOUT_MS; 664ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 665ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 666ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 667ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return delay; 668ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 669ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 670ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private boolean isCallDead(DialerCall call) { 671ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian final int state = call.getState(); 672ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return DialerCall.State.IDLE == state || DialerCall.State.INVALID == state; 673ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 674ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 675ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Sets up a call for deletion and notifies listeners of change. */ 676ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private void finishDisconnectedCall(DialerCall call) { 677ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (mPendingDisconnectCalls.contains(call)) { 678ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian mPendingDisconnectCalls.remove(call); 679ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 680ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.setState(DialerCall.State.IDLE); 681ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian updateCallInMap(call); 682ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian notifyGenericListeners(); 683ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 684ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 685ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 686ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Notifies all video calls of a change in device orientation. 687ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 688ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param rotation The new rotation angle (in degrees). 689ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 690ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void notifyCallsOfDeviceRotation(int rotation) { 691ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (DialerCall call : mCallById.values()) { 692d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian call.getVideoTech().setDeviceOrientation(rotation); 693ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 694ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 695ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 696ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onInCallUiShown(boolean forFullScreenIntent) { 697ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (DialerCall call : mCallById.values()) { 698ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian call.getLatencyReport().onInCallUiShown(forFullScreenIntent); 699ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 700ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 701ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 702ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Listener interface for any class that wants to be notified of changes to the call list. */ 703ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public interface Listener { 704ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 705ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 706ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Called when a new incoming call comes in. This is the only method that gets called for 707ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * incoming calls. Listeners that want to perform an action on incoming call should respond in 708ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * this method because {@link #onCallListChange} does not automatically get called for incoming 709ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * calls. 710ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 711ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onIncomingCall(DialerCall call); 712ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 713ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 714ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Called when a new modify call request comes in This is the only method that gets called for 715ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * modify requests. 716ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 717ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onUpgradeToVideo(DialerCall call); 718ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 719ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Called when the session modification state of a call changes. */ 720d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian void onSessionModificationStateChange(DialerCall call); 721ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 722ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 723ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Called anytime there are changes to the call list. The change can be switching call states, 724ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * updating information, etc. This method will NOT be called for new incoming calls and for 725ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * calls that switch to disconnected state. Listeners must add actions to those method 726ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * implementations if they want to deal with those actions. 727ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 728ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onCallListChange(CallList callList); 729ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 730ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 731ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Called when a call switches to the disconnected state. This is the only method that will get 732ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * called upon disconnection. 733ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 734ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onDisconnect(DialerCall call); 735ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 736ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onWiFiToLteHandover(DialerCall call); 737ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 738ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 739ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Called when a user is in a video call and the call is unable to be handed off successfully to 740ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WiFi 741ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 742ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void onHandoverToWifiFailed(DialerCall call); 743c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian 744c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian /** Called when the user initiates a call to an international number while on WiFi. */ 745c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian void onInternationalCallOnWifi(@NonNull DialerCall call); 746ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 747ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 748ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private class DialerCallListenerImpl implements DialerCallListener { 749ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 750c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian @NonNull private final DialerCall mCall; 751ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 752c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian DialerCallListenerImpl(@NonNull DialerCall call) { 753c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian mCall = Assert.isNotNull(call); 754ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 755ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 756ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 757ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDialerCallDisconnect() { 758ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (updateCallInMap(mCall)) { 759ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.i("DialerCallListenerImpl.onDialerCallDisconnect", String.valueOf(mCall)); 760ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // notify those listening for all disconnects 761ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian notifyListenersOfDisconnect(mCall); 762ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 763ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 764ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 765ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 766ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDialerCallUpdate() { 767ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Trace.beginSection("onUpdate"); 768ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian onUpdateCall(mCall); 769ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian notifyGenericListeners(); 770ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Trace.endSection(); 771ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 772ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 773ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 774ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDialerCallChildNumberChange() {} 775ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 776ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 777ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDialerCallLastForwardedNumberChange() {} 778ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 779ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 780ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onDialerCallUpgradeToVideo() { 781ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (Listener listener : mListeners) { 782ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian listener.onUpgradeToVideo(mCall); 783ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 784ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 785ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 786ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 787ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onWiFiToLteHandover() { 788ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (Listener listener : mListeners) { 789ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian listener.onWiFiToLteHandover(mCall); 790ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 791ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 792ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 793ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 794ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public void onHandoverToWifiFailure() { 795ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (Listener listener : mListeners) { 796ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian listener.onHandoverToWifiFailed(mCall); 797ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 798ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 799ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 800ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 801c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian public void onInternationalCallOnWifi() { 802c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian LogUtil.enterBlock("DialerCallListenerImpl.onInternationalCallOnWifi"); 803c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian for (Listener listener : mListeners) { 804c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian listener.onInternationalCallOnWifi(mCall); 805c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian } 806c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian } 807c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian 808c857f90590e7d7fcffa89511982eb33afd34805fEric Erfanian @Override 8092f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian public void onEnrichedCallSessionUpdate() {} 8102f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 8112f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian @Override 812d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian public void onDialerCallSessionModificationStateChange() { 813ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (Listener listener : mListeners) { 814d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian listener.onSessionModificationStateChange(mCall); 815ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 816ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 817ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 818ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian} 819