CallCardPresenter.java revision 89aad4adce9cc66294f15391fa3e10f3123d3d92
1c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon/*
2c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * Copyright (C) 2013 The Android Open Source Project
3c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon *
4c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
5c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * you may not use this file except in compliance with the License.
6c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * You may obtain a copy of the License at
7c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon *
8c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
9c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon *
10c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * Unless required by applicable law or agreed to in writing, software
11c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
12c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * See the License for the specific language governing permissions and
14c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * limitations under the License
15c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon */
16c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
17c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordonpackage com.android.incallui;
18c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
19f925b504266f80ec0b74212c403475f5cc790ab0Evan Charltonimport android.Manifest;
206596e1be9d3e15e2cbe4a5e9c3824ee47a0e2744Yorke Leeimport android.app.Activity;
216596e1be9d3e15e2cbe4a5e9c3824ee47a0e2744Yorke Leeimport android.app.FragmentManager;
223d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordonimport android.content.Context;
23f925b504266f80ec0b74212c403475f5cc790ab0Evan Charltonimport android.content.Intent;
243d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordonimport android.content.pm.ApplicationInfo;
253d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordonimport android.content.pm.PackageManager;
266d231f52e4f00399330d772f2a337283803f3a9dYorke Leeimport android.graphics.drawable.Drawable;
27da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordonimport android.net.Uri;
280e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport android.os.Bundle;
298cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Leeimport android.telecom.Call.Details;
3050dbb6eeca55cf78e0fd9eb132a26787d293620aAndrew Leeimport android.telecom.DisconnectCause;
314b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunnimport android.telecom.PhoneAccount;
324b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunnimport android.telecom.PhoneAccountHandle;
334b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunnimport android.telecom.StatusHints;
344b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunnimport android.telecom.TelecomManager;
354b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunnimport android.telecom.VideoProfile;
360e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport android.telephony.PhoneNumberUtils;
370786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charltonimport android.telephony.TelephonyManager;
38d28fc12696fa706fed70e04698275af7be7fee82Santos Cordonimport android.text.TextUtils;
39be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
406596e1be9d3e15e2cbe4a5e9c3824ee47a0e2744Yorke Leeimport com.android.incallui.CircularRevealFragment.OnCircularRevealCompleteListener;
41d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonimport com.android.incallui.ContactInfoCache.ContactCacheEntry;
42d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonimport com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
430e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport com.android.incallui.InCallPresenter.InCallDetailsListener;
44350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport com.android.incallui.InCallPresenter.InCallEventListener;
457ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordonimport com.android.incallui.InCallPresenter.InCallState;
467ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordonimport com.android.incallui.InCallPresenter.InCallStateListener;
471c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordonimport com.android.incallui.InCallPresenter.IncomingCallListener;
48f925b504266f80ec0b74212c403475f5cc790ab0Evan Charltonimport com.android.incalluibind.ObjectFactory;
495b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
505b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Leeimport java.lang.ref.WeakReference;
515b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
5242373eb59cbef15ec61ebb5c919031f293291a53Chiao Chengimport com.google.common.base.Preconditions;
53c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
54c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon/**
55c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * Presenter for the Call Card Fragment.
56033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng * <p>
577ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon * This class listens for changes to InCallState and passes it along to the fragment.
58c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon */
59d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonpublic class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
6091a369b019b39c5335a4f5d251691c0cdb657f7dAndrew Lee        implements InCallStateListener, IncomingCallListener, InCallDetailsListener,
619c98346835b8e902e0c2c11f14a35f4e91578e9fAndrew Lee        InCallEventListener {
62be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
6389aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee    public interface EmergencyCallListener {
6489aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee        public void onCallUpdated(BaseFragment fragment, boolean isEmergency);
6589aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee    }
6689aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee
6789aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee    private static final EmergencyCallListener mEmergencyCallListener =
6889aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee            ObjectFactory.newEmergencyCallListener();
6989aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee
70033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng    private static final String TAG = CallCardPresenter.class.getSimpleName();
719c4226952c74f024c09e0bd381048493993c974eAndrew Lee    private static final long CALL_TIME_UPDATE_INTERVAL_MS = 1000;
728cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
731b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    private Call mPrimary;
74d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private Call mSecondary;
75d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private ContactCacheEntry mPrimaryContactInfo;
76d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private ContactCacheEntry mSecondaryContactInfo;
7786a7f5639fd0798c3b4500166f97649949237215Andrew Lee    private CallTimer mCallTimer;
788cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee
793d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private Context mContext;
806d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
815b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    public static class ContactLookupCallback implements ContactInfoCacheCallback {
825b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        private final WeakReference<CallCardPresenter> mCallCardPresenter;
835b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        private final boolean mIsPrimary;
845b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
855b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        public ContactLookupCallback(CallCardPresenter callCardPresenter, boolean isPrimary) {
865b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            mCallCardPresenter = new WeakReference<CallCardPresenter>(callCardPresenter);
875b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            mIsPrimary = isPrimary;
885b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
895b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
905b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        @Override
915b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        public void onContactInfoComplete(String callId, ContactCacheEntry entry) {
925b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            CallCardPresenter presenter = mCallCardPresenter.get();
935b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            if (presenter != null) {
945b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee                presenter.onContactInfoComplete(callId, entry, mIsPrimary);
955b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            }
965b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
975b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
985b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        @Override
995b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        public void onImageLoadComplete(String callId, ContactCacheEntry entry) {
1005b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            CallCardPresenter presenter = mCallCardPresenter.get();
1015b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            if (presenter != null) {
1025b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee                presenter.onImageLoadComplete(callId, entry);
1035b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            }
1045b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
1055b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
1065b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    }
1075b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
108b8eedb3b9796873eaa22847205239a51092f1a43Santos Cordon    public CallCardPresenter() {
1098cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        // create the call timer
1108cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        mCallTimer = new CallTimer(new Runnable() {
1118cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            @Override
1128cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            public void run() {
1138cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon                updateCallTime();
1148cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            }
1158cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        });
1166d231f52e4f00399330d772f2a337283803f3a9dYorke Lee    }
1176d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
1181c6bb983216392b5ceb36cea42a46631f68a3dd6Jay Shrauner    public void init(Context context, Call call) {
11942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        mContext = Preconditions.checkNotNull(context);
12042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
1214a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng        // Call may be null if disconnect happened already.
1224a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng        if (call != null) {
123656dd4a0d8571b47ecf0ecf3e4c2eeacfd1099b3Chiao Cheng            mPrimary = call;
124656dd4a0d8571b47ecf0ecf3e4c2eeacfd1099b3Chiao Cheng
1254a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng            // start processing lookups right away.
126812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            if (!call.isConferenceCall()) {
127248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                startContactInfoSearch(call, true, call.getState() == Call.State.INCOMING);
128812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            } else {
129017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                updateContactEntry(null, true);
130812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            }
1314a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng        }
132fd0b577edffa5413adfda1503038a3bff3247106Yorke Lee
133fd0b577edffa5413adfda1503038a3bff3247106Yorke Lee        onStateChange(null, InCallPresenter.getInstance().getInCallState(), CallList.getInstance());
134033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng    }
135033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng
136c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    @Override
137c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    public void onUiReady(CallCardUi ui) {
138c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon        super.onUiReady(ui);
1391b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
14042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // Contact search may have completed before ui is ready.
14142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (mPrimaryContactInfo != null) {
142017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updatePrimaryDisplayInfo();
14342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
14442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
1451f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        // Register for call state changes last
1461f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        InCallPresenter.getInstance().addListener(this);
1471c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        InCallPresenter.getInstance().addIncomingCallListener(this);
1480e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        InCallPresenter.getInstance().addDetailsListener(this);
149350fff554bf7ed5b9e91985935488771156953abTyler Gunn        InCallPresenter.getInstance().addInCallEventListener(this);
1501b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    }
1511b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
1521b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    @Override
1531b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    public void onUiUnready(CallCardUi ui) {
1541b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        super.onUiUnready(ui);
1551b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
1561f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        // stop getting call state changes
1571f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        InCallPresenter.getInstance().removeListener(this);
1581c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        InCallPresenter.getInstance().removeIncomingCallListener(this);
1590e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        InCallPresenter.getInstance().removeDetailsListener(this);
160350fff554bf7ed5b9e91985935488771156953abTyler Gunn        InCallPresenter.getInstance().removeInCallEventListener(this);
1611f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon
1621b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        mPrimary = null;
163d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        mPrimaryContactInfo = null;
164d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        mSecondaryContactInfo = null;
165c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    }
166c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
167c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    @Override
168f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen    public void onIncomingCall(InCallState oldState, InCallState newState, Call call) {
1691c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        // same logic should happen as with onStateChange()
170f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        onStateChange(oldState, newState, CallList.getInstance());
1711c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon    }
1721c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon
1731c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon    @Override
174f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen    public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
175f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        Log.d(this, "onStateChange() " + newState);
17675c86b55d45b1725c46ed2e5d77c9c43fcfd93daSantos Cordon        final CallCardUi ui = getUi();
1771b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        if (ui == null) {
1781b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon            return;
1791b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        }
180c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
1817ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        Call primary = null;
1827ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        Call secondary = null;
1837ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
184f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        if (newState == InCallState.INCOMING) {
1857ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon            primary = callList.getIncomingCall();
186f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        } else if (newState == InCallState.PENDING_OUTGOING || newState == InCallState.OUTGOING) {
187950e3df8ac744daf2a890d279566bdba424710f9Santos Cordon            primary = callList.getOutgoingCall();
188f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen            if (primary == null) {
189f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen                primary = callList.getPendingOutgoingCall();
190f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen            }
191950e3df8ac744daf2a890d279566bdba424710f9Santos Cordon
19282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            // getCallToDisplay doesn't go through outgoing or incoming calls. It will return the
19382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            // highest priority call to display as the secondary call.
194d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            secondary = getCallToDisplay(callList, null, true);
195f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        } else if (newState == InCallState.INCALL) {
196d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            primary = getCallToDisplay(callList, null, false);
197d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            secondary = getCallToDisplay(callList, primary, true);
1987ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        }
1997ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
200a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng        Log.d(this, "Primary call: " + primary);
201a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng        Log.d(this, "Secondary call: " + secondary);
2027ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
2039c98346835b8e902e0c2c11f14a35f4e91578e9fAndrew Lee        final boolean primaryChanged = !Call.areSame(mPrimary, primary);
2049c98346835b8e902e0c2c11f14a35f4e91578e9fAndrew Lee        final boolean secondaryChanged = !Call.areSame(mSecondary, secondary);
2059c98346835b8e902e0c2c11f14a35f4e91578e9fAndrew Lee
206812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        mSecondary = secondary;
207812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        mPrimary = primary;
208812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
2090cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        // Refresh primary call information if either:
2100cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        // 1. Primary call changed.
2110cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        // 2. The call's ability to manage conference has changed.
2120cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        if (mPrimary != null && (primaryChanged ||
2130cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn                ui.isManageConferenceVisible() != shouldShowManageConference())) {
214812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            // primary call has changed
215248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            mPrimaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext, mPrimary,
216248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                    mPrimary.getState() == Call.State.INCOMING);
217017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updatePrimaryDisplayInfo();
218812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            maybeStartSearch(mPrimary, true);
2199c4226952c74f024c09e0bd381048493993c974eAndrew Lee            mPrimary.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
22042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
22142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
222812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        if (mSecondary == null) {
22342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // Secondary call may have ended.  Update the ui.
22442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mSecondaryContactInfo = null;
225017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updateSecondaryDisplayInfo();
226812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        } else if (secondaryChanged) {
227812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            // secondary call has changed
228248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            mSecondaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext, mSecondary,
229248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                    mSecondary.getState() == Call.State.INCOMING);
230017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updateSecondaryDisplayInfo();
231812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            maybeStartSearch(mSecondary, false);
2329c4226952c74f024c09e0bd381048493993c974eAndrew Lee            mSecondary.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
23342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
23442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
2359c4226952c74f024c09e0bd381048493993c974eAndrew Lee        // Start/stop timers.
2368cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        if (isPrimaryCallActive()) {
237a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng            Log.d(this, "Starting the calltime timer");
2389c4226952c74f024c09e0bd381048493993c974eAndrew Lee            mCallTimer.start(CALL_TIME_UPDATE_INTERVAL_MS);
2398cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        } else {
240a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng            Log.d(this, "Canceling the calltime timer");
2418cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            mCallTimer.cancel();
242f0dfbe2e89df0d58efde8b290662072c081e146aNancy Chen            ui.setPrimaryCallElapsedTime(false, 0);
2438cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        }
2448cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
245d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        // Set the call state
2468aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton        int callState = Call.State.IDLE;
247d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        if (mPrimary != null) {
24832027ae1f52232258cc8133d383459f3b4ee57e4Yorke Lee            callState = mPrimary.getState();
249ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            updatePrimaryCallState();
25082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        } else {
2519c4226952c74f024c09e0bd381048493993c974eAndrew Lee            getUi().setCallState(
2529c4226952c74f024c09e0bd381048493993c974eAndrew Lee                    callState,
2533718dcb345e77e421ab18a760e48f0c3a760fccaIhab Awad                    VideoProfile.VideoState.AUDIO_ONLY,
2549c4226952c74f024c09e0bd381048493993c974eAndrew Lee                    Call.SessionModificationState.NO_REQUEST,
25550dbb6eeca55cf78e0fd9eb132a26787d293620aAndrew Lee                    new DisconnectCause(DisconnectCause.UNKNOWN),
2569c4226952c74f024c09e0bd381048493993c974eAndrew Lee                    null,
2579c4226952c74f024c09e0bd381048493993c974eAndrew Lee                    null,
25882332c921b8dcef213700822e2404b005adab00cAndrew Lee                    null,
25982332c921b8dcef213700822e2404b005adab00cAndrew Lee                    false /* isWifi */);
2608cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee            getUi().showHdAudioIndicator(false);
26182f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
262e26b887e90d5e9566a5054a1ccb3ed32ae2eea2dAndrew Lee
2631da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee        maybeShowManageConferenceCallButton();
26455576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee        maybeShowProgressSpinner();
2651da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee
266c44f654b992c6ab8a4acff9cb5aa2678c58755d9Andrew Lee        // Hide the end call button instantly if we're receiving an incoming call.
267fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        getUi().setEndCallButtonEnabled(shouldShowEndCallButton(mPrimary, callState),
268fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee                callState != Call.State.INCOMING /* animate */);
2691b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    }
2701b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
2711b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    @Override
2728cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee    public void onDetailsChanged(Call call, Details details) {
273ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        updatePrimaryCallState();
274e0ec202ff354be3cd3bded7af8fca678dea7fb61Andrew Lee
2758cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        if (call.can(Details.CAPABILITY_MANAGE_CONFERENCE) !=
2768cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee                Details.can(details.getCallCapabilities(), Details.CAPABILITY_MANAGE_CONFERENCE)) {
277e0ec202ff354be3cd3bded7af8fca678dea7fb61Andrew Lee            maybeShowManageConferenceCallButton();
278e0ec202ff354be3cd3bded7af8fca678dea7fb61Andrew Lee        }
2790786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton    }
2800786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton
2810786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton    private String getSubscriptionNumber() {
2820786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        // If it's an emergency call, and they're not populating the callback number,
2830786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        // then try to fall back to the phone sub info (to hopefully get the SIM's
2840786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        // number directly from the telephony layer).
28576e1b4bfb2e21300068f10cc94922214e62c8f86Evan Charlton        PhoneAccountHandle accountHandle = mPrimary.getAccountHandle();
28676e1b4bfb2e21300068f10cc94922214e62c8f86Evan Charlton        if (accountHandle != null) {
287170e405691a237b74fbecbf41208cbaa5bd36442Nancy Chen            TelecomManager mgr = InCallPresenter.getInstance().getTelecomManager();
288b6f45c2768f5af916ee3257542a3ab03611c1f5eEvan Charlton            PhoneAccount account = mgr.getPhoneAccount(accountHandle);
289b6f45c2768f5af916ee3257542a3ab03611c1f5eEvan Charlton            if (account != null) {
2909e27dca4bc1be09bcb1d283b2fe3ba3d49f0748bAndrew Lee                return getNumberFromHandle(account.getSubscriptionAddress());
291c108b49ad5440fbf381c9a589d8a217da3efcb64Ihab Awad            }
2920e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        }
2930786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        return null;
2940e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    }
2950e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
296ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal    private void updatePrimaryCallState() {
297ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        if (getUi() != null && mPrimary != null) {
298ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            getUi().setCallState(
299ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    mPrimary.getState(),
300ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    mPrimary.getVideoState(),
301ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    mPrimary.getSessionModificationState(),
302ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    mPrimary.getDisconnectCause(),
303ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    getConnectionLabel(),
3046c3061091e59e9ab06b620c2615b897e2eca233cAndrew Lee                    getCallStateIcon(),
30582332c921b8dcef213700822e2404b005adab00cAndrew Lee                    getGatewayNumber(),
30682332c921b8dcef213700822e2404b005adab00cAndrew Lee                    primaryCallCan(Details.CAPABILITY_WIFI));
3078cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee
3088cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee            boolean showHdAudioIndicator =
3098cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee                    isPrimaryCallActive() && primaryCallCan(Details.CAPABILITY_HIGH_DEF_AUDIO);
3108cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee            getUi().showHdAudioIndicator(showHdAudioIndicator);
3118cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee
312ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            setCallbackNumber();
313ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        }
314ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal    }
3150786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton
3161da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee    /**
317289d53ed1c879e983dcb021fa677212ab4566bbdSantos Cordon     * Only show the conference call button if we can manage the conference.
3181da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee     */
3191da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee    private void maybeShowManageConferenceCallButton() {
3200cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        getUi().showManageConferenceCallButton(shouldShowManageConference());
3210cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn    }
3220cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn
32355576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee    private void maybeShowProgressSpinner() {
32455576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee        final boolean show = mPrimary != null && mPrimary.getSessionModificationState()
32555576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee                == Call.SessionModificationState.WAITING_FOR_RESPONSE
32655576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee                && mPrimary.getState() == Call.State.ACTIVE;
32755576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee        getUi().setProgressSpinnerVisible(show);
32855576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee    }
32955576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee
3300cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn    /**
3310cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     * Determines if the manage conference button should be visible, based on the current primary
3320cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     * call.
3330cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     *
3340cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     * @return {@code True} if the manage conference button should be visible.
3350cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     */
3360cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn    private boolean shouldShowManageConference() {
337e16e53167b367656840df665457e71e66bc966deAndrew Lee        if (mPrimary == null) {
3380cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn            return false;
339e16e53167b367656840df665457e71e66bc966deAndrew Lee        }
340e16e53167b367656840df665457e71e66bc966deAndrew Lee
34118c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        return mPrimary.can(android.telecom.Call.Details.CAPABILITY_MANAGE_CONFERENCE)
34218c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar                && !mPrimary.isVideoCall(mContext);
3431da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee    }
3441da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee
345ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal    private void setCallbackNumber() {
346ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        String callbackNumber = null;
3470786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton
348c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        // Show the emergency callback number if either:
349c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        // 1. This is an emergency call.
350c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        // 2. The phone is in Emergency Callback Mode, which means we should show the callback
351c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        //    number.
352ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        boolean isEmergencyCall = PhoneNumberUtils.isEmergencyNumber(
353ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                getNumberFromHandle(mPrimary.getHandle()));
354c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        boolean showCallbackNumber = mPrimary.can(Details.CAPABILITY_SHOW_CALLBACK_NUMBER);
355c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn
356c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        if (isEmergencyCall || showCallbackNumber) {
357ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            callbackNumber = getSubscriptionNumber();
358ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        } else {
359ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            StatusHints statusHints = mPrimary.getTelecommCall().getDetails().getStatusHints();
360ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            if (statusHints != null) {
361ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                Bundle extras = statusHints.getExtras();
362ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                if (extras != null) {
3634b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunn                    callbackNumber = extras.getString(TelecomManager.EXTRA_CALL_BACK_NUMBER);
3640786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton                }
3650e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton            }
3660786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        }
3670786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton
3686dfd1963ecc89ecb2c76793ab40af26e35654285Nancy Chen        TelecomManager mgr = InCallPresenter.getInstance().getTelecomManager();
3696dfd1963ecc89ecb2c76793ab40af26e35654285Nancy Chen        String simNumber = mgr.getLine1Number(mPrimary.getAccountHandle());
370c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        if (!showCallbackNumber && PhoneNumberUtils.compare(callbackNumber, simNumber)) {
371c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn            Log.d(this, "Numbers are the same (and callback number is not being forced to show);" +
372c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn                            " not showing the callback number");
373ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            callbackNumber = null;
3740786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        }
375ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal
376c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        getUi().setCallbackNumber(callbackNumber, isEmergencyCall || showCallbackNumber);
3770e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    }
3780e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
3798cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon    public void updateCallTime() {
3808cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        final CallCardUi ui = getUi();
3818cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
3828cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        if (ui == null) {
3838cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee            mCallTimer.cancel();
3848cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        } else if (!isPrimaryCallActive()) {
3858cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee            ui.setPrimaryCallElapsedTime(false, 0);
3868cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            mCallTimer.cancel();
387899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon        } else {
388c6f4e50a4130fb8f7247f5eab6849829701ad484Sailesh Nepal            final long callStart = mPrimary.getConnectTimeMillis();
389899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon            final long duration = System.currentTimeMillis() - callStart;
390f0dfbe2e89df0d58efde8b290662072c081e146aNancy Chen            ui.setPrimaryCallElapsedTime(true, duration);
3918cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        }
3928cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon    }
3938cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
394f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton    public void onCallStateButtonTouched() {
39571afa1c7d1e1f49af56c24bdc64d30d80cf1ea68Evan Charlton        Intent broadcastIntent = ObjectFactory.getCallStateButtonBroadcastIntent(mContext);
396f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton        if (broadcastIntent != null) {
397f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton            Log.d(this, "Sending call state button broadcast: ", broadcastIntent);
398f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton            mContext.sendBroadcast(broadcastIntent, Manifest.permission.READ_PHONE_STATE);
399f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton        }
400f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton    }
401f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton
402812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    private void maybeStartSearch(Call call, boolean isPrimary) {
403812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        // no need to start search for conference calls which show generic info.
404812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        if (call != null && !call.isConferenceCall()) {
405248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            startContactInfoSearch(call, isPrimary, call.getState() == Call.State.INCOMING);
406812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        }
407812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    }
408812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
40982f5d003e675dfd56735c745744c3d968883b23cSantos Cordon    /**
410d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon     * Starts a query for more contact data for the save primary and secondary calls.
411d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon     */
412248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal    private void startContactInfoSearch(final Call call, final boolean isPrimary,
413248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            boolean isIncoming) {
41442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        final ContactInfoCache cache = ContactInfoCache.getInstance(mContext);
41542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
4165b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        cache.findInfo(call, isIncoming, new ContactLookupCallback(this, isPrimary));
4175b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    }
4187d2fb8620b808c28c49bde99dc54f6de46fdcb44Chiao Cheng
4195b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    private void onContactInfoComplete(String callId, ContactCacheEntry entry, boolean isPrimary) {
420017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        updateContactEntry(entry, isPrimary);
4215b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        if (entry.name != null) {
4225b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            Log.d(TAG, "Contact found: " + entry);
4235b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
4245b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        if (entry.contactUri != null) {
4255b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            CallerInfoUtils.sendViewNotification(mContext, entry.contactUri);
4265b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
4275b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    }
4285b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
4295b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    private void onImageLoadComplete(String callId, ContactCacheEntry entry) {
4305b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        if (getUi() == null) {
4315b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            return;
4325b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
433f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen
4345b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        if (entry.photo != null) {
4355b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            if (mPrimary != null && callId.equals(mPrimary.getId())) {
4365b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee                getUi().setPrimaryImage(entry.photo);
4375b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            }
4385b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
43942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    }
44042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
441017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private void updateContactEntry(ContactCacheEntry entry, boolean isPrimary) {
44242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (isPrimary) {
44342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mPrimaryContactInfo = entry;
444017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updatePrimaryDisplayInfo();
445d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        } else {
44642373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mSecondaryContactInfo = entry;
447017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updateSecondaryDisplayInfo();
448d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        }
449d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    }
450d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon
451d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    /**
45282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * Get the highest priority call to display.
45382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * Goes through the calls and chooses which to return based on priority of which type of call
45482f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * to display to the user. Callers can use the "ignore" feature to get the second best call
45582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * by passing a previously found primary call as ignore.
45682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     *
45782f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * @param ignore A call to ignore if found.
45882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     */
459d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private Call getCallToDisplay(CallList callList, Call ignore, boolean skipDisconnected) {
46082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
461d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // Active calls come second.  An active call always gets precedent.
462d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        Call retval = callList.getActiveCall();
46382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        if (retval != null && retval != ignore) {
46482f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            return retval;
46582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
46682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
467d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // Disconnected calls get primary position if there are no active calls
468d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // to let user know quickly what call has disconnected. Disconnected
469d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // calls are very short lived.
470d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (!skipDisconnected) {
4716258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            retval = callList.getDisconnectingCall();
4726258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            if (retval != null && retval != ignore) {
4736258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen                return retval;
4746258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            }
475d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            retval = callList.getDisconnectedCall();
476d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            if (retval != null && retval != ignore) {
477d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon                return retval;
478d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            }
47982f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
48082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
48182f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        // Then we go to background call (calls on hold)
48282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        retval = callList.getBackgroundCall();
48382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        if (retval != null && retval != ignore) {
48482f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            return retval;
48582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
48682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
48782f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        // Lastly, we go to a second background call.
48882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        retval = callList.getSecondBackgroundCall();
48982f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
49082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        return retval;
49182f5d003e675dfd56735c745744c3d968883b23cSantos Cordon    }
49282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
493017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private void updatePrimaryDisplayInfo() {
4946d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        final CallCardUi ui = getUi();
495d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        if (ui == null) {
49642373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // TODO: May also occur if search result comes back after ui is destroyed. Look into
49742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // removing that case completely.
49842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            Log.d(TAG, "updatePrimaryDisplayInfo called but ui is null!");
499d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon            return;
5006d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        }
501be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
502017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        if (mPrimary == null) {
503017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            // Clear the primary display info.
504017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setPrimary(null, null, false, null, null, false);
505017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            return;
506017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        }
507017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
508017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        if (mPrimary.isConferenceCall()) {
509017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            Log.d(TAG, "Update primary display info for conference call.");
510017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
511017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setPrimary(
512017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    null /* number */,
513017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getConferenceString(mPrimary),
514017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    false /* nameIsNumber */,
515017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    null /* label */,
516017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getConferencePhoto(mPrimary),
517017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    false /* isSipCall */);
518017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        } else if (mPrimaryContactInfo != null) {
519017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            Log.d(TAG, "Update primary display info for " + mPrimaryContactInfo);
520017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
521017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            String name = getNameForCall(mPrimaryContactInfo);
522017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            String number = getNumberForCall(mPrimaryContactInfo);
523017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            boolean nameIsNumber = name != null && name.equals(mPrimaryContactInfo.number);
524017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setPrimary(
525017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    number,
526017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    name,
527017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    nameIsNumber,
528017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    mPrimaryContactInfo.label,
529017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    mPrimaryContactInfo.photo,
530017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    mPrimaryContactInfo.isSipCall);
5316d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        } else {
532017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            // Clear the primary display info.
533017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setPrimary(null, null, false, null, null, false);
534d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        }
535d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon
53689aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee        if (mEmergencyCallListener != null) {
53789aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee            boolean isEmergencyCall = PhoneNumberUtils.isEmergencyNumber(
53889aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee                    getNumberFromHandle(mPrimary.getHandle()));
53989aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee            mEmergencyCallListener.onCallUpdated((BaseFragment) ui, isEmergencyCall);
54089aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee        }
541d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    }
542d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon
543017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private void updateSecondaryDisplayInfo() {
54442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        final CallCardUi ui = getUi();
54542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (ui == null) {
54642373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            return;
54742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
54842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
549017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        if (mSecondary == null) {
550017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            // Clear the secondary display info.
551e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn            ui.setSecondary(false, null, false, null, null, false /* isConference */,
552e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                    false /* isVideoCall */);
553017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            return;
554017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        }
555c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee
556017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        if (mSecondary.isConferenceCall()) {
557017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setSecondary(
558017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    true /* show */,
559017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getConferenceString(mSecondary),
560017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    false /* nameIsNumber */,
561017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    null /* label */,
562017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getCallProviderLabel(mSecondary),
563e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                    true /* isConference */,
564e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                    mSecondary.isVideoCall(mContext));
565017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        } else if (mSecondaryContactInfo != null) {
566017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            Log.d(TAG, "updateSecondaryDisplayInfo() " + mSecondaryContactInfo);
567017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            String name = getNameForCall(mSecondaryContactInfo);
568017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            boolean nameIsNumber = name != null && name.equals(mSecondaryContactInfo.number);
569017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setSecondary(
570017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    true /* show */,
571017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    name,
572017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    nameIsNumber,
573017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    mSecondaryContactInfo.label,
574017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getCallProviderLabel(mSecondary),
575e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                    false /* isConference */,
576e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                    mSecondary.isVideoCall(mContext));
57742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        } else {
578017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            // Clear the secondary display info.
579e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn            ui.setSecondary(false, null, false, null, null, false /* isConference */,
580e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                    false /* isVideoCall */);
58142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
58242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    }
58342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
5848a80413884d1afbd7e021d581546c2245f068619Nancy Chen
5858a80413884d1afbd7e021d581546c2245f068619Nancy Chen    /**
5868a80413884d1afbd7e021d581546c2245f068619Nancy Chen     * Gets the phone account to display for a call.
5878a80413884d1afbd7e021d581546c2245f068619Nancy Chen     */
5888a80413884d1afbd7e021d581546c2245f068619Nancy Chen    private PhoneAccount getAccountForCall(Call call) {
5898a80413884d1afbd7e021d581546c2245f068619Nancy Chen        PhoneAccountHandle accountHandle = call.getAccountHandle();
5908a80413884d1afbd7e021d581546c2245f068619Nancy Chen        if (accountHandle == null) {
5918a80413884d1afbd7e021d581546c2245f068619Nancy Chen            return null;
5928a80413884d1afbd7e021d581546c2245f068619Nancy Chen        }
593170e405691a237b74fbecbf41208cbaa5bd36442Nancy Chen        return InCallPresenter.getInstance().getTelecomManager().getPhoneAccount(accountHandle);
5948a80413884d1afbd7e021d581546c2245f068619Nancy Chen    }
5958a80413884d1afbd7e021d581546c2245f068619Nancy Chen
5963d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    /**
5973d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     * Returns the gateway number for any existing outgoing call.
5983d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     */
5993d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private String getGatewayNumber() {
6003d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        if (hasOutgoingGatewayCall()) {
60107fd3fd3ac627faf1771ba4699fe53a0479f2293Nancy Chen            return getNumberFromHandle(mPrimary.getGatewayInfo().getGatewayAddress());
6023d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        }
6033d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        return null;
6043d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
6053d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
6063d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    /**
6078a80413884d1afbd7e021d581546c2245f068619Nancy Chen     * Return the string label to represent the call provider
6088a80413884d1afbd7e021d581546c2245f068619Nancy Chen     */
6098a80413884d1afbd7e021d581546c2245f068619Nancy Chen    private String getCallProviderLabel(Call call) {
6108a80413884d1afbd7e021d581546c2245f068619Nancy Chen        PhoneAccount account = getAccountForCall(call);
611170e405691a237b74fbecbf41208cbaa5bd36442Nancy Chen        TelecomManager mgr = InCallPresenter.getInstance().getTelecomManager();
61215b3fb7207bc356b2ee6ce1e8264d8242bb092ecJay Shrauner        if (account != null && !TextUtils.isEmpty(account.getLabel())
6135b592ce22da61660c21752122d8172f7dbc0c796Yorke Lee                && mgr.getCallCapablePhoneAccounts().size() > 1) {
6148a80413884d1afbd7e021d581546c2245f068619Nancy Chen            return account.getLabel().toString();
615bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        }
616bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        return null;
617bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    }
618bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen
619bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    /**
620bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen     * Returns the label (line of text above the number/name) for any given call.
621f8b0677bed382046cb26e38a8442a9509d1e835cSailesh Nepal     * For example, "calling via [Account/Google Voice]" for outgoing calls.
6223d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     */
623bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    private String getConnectionLabel() {
624ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        StatusHints statusHints = mPrimary.getTelecommCall().getDetails().getStatusHints();
625ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        if (statusHints != null && !TextUtils.isEmpty(statusHints.getLabel())) {
626ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            return statusHints.getLabel().toString();
627ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        }
628ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal
6293d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        if (hasOutgoingGatewayCall() && getUi() != null) {
630bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen            // Return the label for the gateway app on outgoing calls.
6313d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            final PackageManager pm = mContext.getPackageManager();
6323d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            try {
633ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                ApplicationInfo info = pm.getApplicationInfo(
634ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                        mPrimary.getGatewayInfo().getGatewayProviderPackageName(), 0);
635bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                return pm.getApplicationLabel(info).toString();
6363d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            } catch (PackageManager.NameNotFoundException e) {
637bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                Log.e(this, "Gateway Application Not Found.", e);
638bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                return null;
6393d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            }
6403d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        }
6418a80413884d1afbd7e021d581546c2245f068619Nancy Chen        return getCallProviderLabel(mPrimary);
6423d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
6433d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
6446c3061091e59e9ab06b620c2615b897e2eca233cAndrew Lee    private Drawable getCallStateIcon() {
6456c3061091e59e9ab06b620c2615b897e2eca233cAndrew Lee        // Return connection icon if one exists.
646ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        StatusHints statusHints = mPrimary.getTelecommCall().getDetails().getStatusHints();
6473718dcb345e77e421ab18a760e48f0c3a760fccaIhab Awad        if (statusHints != null && statusHints.getIconResId() != 0) {
648ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            Drawable icon = statusHints.getIcon(mContext);
649ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            if (icon != null) {
650ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                return icon;
651ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            }
652ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        }
6536c3061091e59e9ab06b620c2615b897e2eca233cAndrew Lee
654ab86f04c5ed385eafcd9099fa4ca50fd2f4c5c33Nancy Chen        return null;
655ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal    }
656ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal
6573d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private boolean hasOutgoingGatewayCall() {
6583718dcb345e77e421ab18a760e48f0c3a760fccaIhab Awad        // We only display the gateway information while STATE_DIALING so return false for any othe
6593d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        // call state.
66042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // TODO: mPrimary can be null because this is called from updatePrimaryDisplayInfo which
66142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // is also called after a contact search completes (call is not present yet).  Split the
66242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // UI update so it can receive independent updates.
66342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (mPrimary == null) {
66442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            return false;
66542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
666ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal        return Call.State.isDialing(mPrimary.getState()) && mPrimary.getGatewayInfo() != null &&
667ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                !mPrimary.getGatewayInfo().isEmpty();
6683d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
6693d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
670d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    /**
671d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     * Gets the name to display for the call.
672d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     */
673d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private static String getNameForCall(ContactCacheEntry contactInfo) {
674d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (TextUtils.isEmpty(contactInfo.name)) {
675d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            return contactInfo.number;
6766d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        }
677d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        return contactInfo.name;
678d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    }
6796d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
680d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    /**
681d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     * Gets the number to display for a call.
682d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     */
683d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private static String getNumberForCall(ContactCacheEntry contactInfo) {
684d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // If the name is empty, we use the number for the name...so dont show a second
685d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // number in the number field
686d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (TextUtils.isEmpty(contactInfo.name)) {
6871c6bb983216392b5ceb36cea42a46631f68a3dd6Jay Shrauner            return contactInfo.location;
688d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        }
689d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        return contactInfo.number;
690d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    }
6916d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
692e5c0d8bdf8269f9435e0381889e4870f36a43f07Andrew Lee    public void secondaryInfoClicked() {
69380c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee        if (mSecondary == null) {
6948b514c9571c587b2e87edfffa38afde4f0458579Nancy Chen            Log.w(this, "Secondary info clicked but no secondary call.");
69580c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee            return;
69680c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee        }
69780c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee
698248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal        Log.i(this, "Swapping call to foreground: " + mSecondary);
6994b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunn        TelecomAdapter.getInstance().unholdCall(mSecondary.getId());
70090995fcb6778a9cb6dc35be12aeb1a5d0dcbb5aeYorke Lee    }
70190995fcb6778a9cb6dc35be12aeb1a5d0dcbb5aeYorke Lee
7027e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee    public void endCallClicked() {
7037e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee        if (mPrimary == null) {
7047e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee            return;
7057e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee        }
7067e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee
707cb2f51bf1acf387f391ca9c8cae8a2344eb2936aEvan Charlton        Log.i(this, "Disconnecting call: " + mPrimary);
708d274e92414988c72708af270e3799b83b4e3b40cJay Shrauner        final String callId = mPrimary.getId();
70933478eae2d380adfcc7ef3f51816ff391a42ebb7Ihab Awad        mPrimary.setState(Call.State.DISCONNECTING);
71033478eae2d380adfcc7ef3f51816ff391a42ebb7Ihab Awad        CallList.getInstance().onUpdate(mPrimary);
711d274e92414988c72708af270e3799b83b4e3b40cJay Shrauner        TelecomAdapter.getInstance().disconnectCall(callId);
7127e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee    }
7137e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee
714da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordon    private String getNumberFromHandle(Uri handle) {
715da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordon        return handle == null ? "" : handle.getSchemeSpecificPart();
716da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordon    }
717da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordon
718350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
719350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * Handles a change to the full screen video state.
720350fff554bf7ed5b9e91985935488771156953abTyler Gunn     *
721350fff554bf7ed5b9e91985935488771156953abTyler Gunn     * @param isFullScreenVideo {@code True} if the application is entering full screen video mode.
722350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
723350fff554bf7ed5b9e91985935488771156953abTyler Gunn    @Override
724350fff554bf7ed5b9e91985935488771156953abTyler Gunn    public void onFullScreenVideoStateChanged(boolean isFullScreenVideo) {
725350fff554bf7ed5b9e91985935488771156953abTyler Gunn        final CallCardUi ui = getUi();
726350fff554bf7ed5b9e91985935488771156953abTyler Gunn        if (ui == null) {
727350fff554bf7ed5b9e91985935488771156953abTyler Gunn            return;
728350fff554bf7ed5b9e91985935488771156953abTyler Gunn        }
729350fff554bf7ed5b9e91985935488771156953abTyler Gunn        ui.setCallCardVisible(!isFullScreenVideo);
730350fff554bf7ed5b9e91985935488771156953abTyler Gunn    }
731350fff554bf7ed5b9e91985935488771156953abTyler Gunn
7328cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee    private boolean isPrimaryCallActive() {
7338cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        return mPrimary != null && mPrimary.getState() == Call.State.ACTIVE;
7348cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee    }
7358cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee
7368cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee    private boolean primaryCallCan(int capability) {
7378cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        return mPrimary.getTelecommCall().getDetails().can(capability);
7388cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee    }
7398cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee
740017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private String getConferenceString(Call call) {
7418cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        boolean isGenericConference = call.can(Details.CAPABILITY_GENERIC_CONFERENCE);
742017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        Log.v(this, "getConferenceString: " + isGenericConference);
743017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
744017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        final int resId = isGenericConference
745017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                ? R.string.card_title_in_call : R.string.card_title_conf_call;
746017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        return mContext.getResources().getString(resId);
747017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    }
748017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
749017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private Drawable getConferencePhoto(Call call) {
7508cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        boolean isGenericConference = call.can(Details.CAPABILITY_GENERIC_CONFERENCE);
751017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        Log.v(this, "getConferencePhoto: " + isGenericConference);
752017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
753017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        final int resId = isGenericConference
754017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                ? R.drawable.img_phone : R.drawable.img_conference;
755017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        Drawable photo = mContext.getResources().getDrawable(resId);
756017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        photo.setAutoMirrored(true);
757017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        return photo;
758017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    }
759017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
760fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee    private boolean shouldShowEndCallButton(Call primary, int callState) {
761fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        if (primary == null) {
762fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee            return false;
763fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        }
764fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        if (!Call.State.isConnectingOrConnected(callState) || callState == Call.State.INCOMING) {
765fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee            return false;
766fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        }
767fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        if (mPrimary.getSessionModificationState()
768fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee                == Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) {
769fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee            return false;
770fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        }
771fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        return true;
772fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee    }
773fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee
774d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    public interface CallCardUi extends Ui {
775d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        void setVisible(boolean on);
776350fff554bf7ed5b9e91985935488771156953abTyler Gunn        void setCallCardVisible(boolean visible);
777d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        void setPrimary(String number, String name, boolean nameIsNumber, String label,
778017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                Drawable photo, boolean isSipCall);
779c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee        void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
780e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                String providerLabel, boolean isConference, boolean isVideoCall);
78150dbb6eeca55cf78e0fd9eb132a26787d293620aAndrew Lee        void setCallState(int state, int videoState, int sessionModificationState,
78250dbb6eeca55cf78e0fd9eb132a26787d293620aAndrew Lee                DisconnectCause disconnectCause, String connectionLabel,
78382332c921b8dcef213700822e2404b005adab00cAndrew Lee                Drawable connectionIcon, String gatewayNumber, boolean isWifi);
784f0dfbe2e89df0d58efde8b290662072c081e146aNancy Chen        void setPrimaryCallElapsedTime(boolean show, long duration);
78542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryName(String name, boolean nameIsNumber);
78649ff6571403695e81dbbd83e4f61790ce9c75f6dSantos Cordon        void setPrimaryImage(Drawable image);
78742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryPhoneNumber(String phoneNumber);
78842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryLabel(String label);
789c44f654b992c6ab8a4acff9cb5aa2678c58755d9Andrew Lee        void setEndCallButtonEnabled(boolean enabled, boolean animate);
7900786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        void setCallbackNumber(String number, boolean isEmergencyCalls);
791350fff554bf7ed5b9e91985935488771156953abTyler Gunn        void setProgressSpinnerVisible(boolean visible);
7928cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        void showHdAudioIndicator(boolean visible);
7931da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee        void showManageConferenceCallButton(boolean visible);
7940cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        boolean isManageConferenceVisible();
7956596e1be9d3e15e2cbe4a5e9c3824ee47a0e2744Yorke Lee        void animateForNewOutgoingCall();
796be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee    }
797c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon}
798