CallCardPresenter.java revision 9124b77e489772fb7c6aac36f83d86ffdf83748f
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;
37d28fc12696fa706fed70e04698275af7be7fee82Santos Cordonimport android.text.TextUtils;
380dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Leeimport android.view.accessibility.AccessibilityManager;
39be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
40d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonimport com.android.incallui.ContactInfoCache.ContactCacheEntry;
41d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonimport com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
420e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport com.android.incallui.InCallPresenter.InCallDetailsListener;
43350fff554bf7ed5b9e91985935488771156953abTyler Gunnimport com.android.incallui.InCallPresenter.InCallEventListener;
447ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordonimport com.android.incallui.InCallPresenter.InCallState;
457ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordonimport com.android.incallui.InCallPresenter.InCallStateListener;
461c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordonimport com.android.incallui.InCallPresenter.IncomingCallListener;
47f925b504266f80ec0b74212c403475f5cc790ab0Evan Charltonimport com.android.incalluibind.ObjectFactory;
485b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
495b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Leeimport java.lang.ref.WeakReference;
505b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
5142373eb59cbef15ec61ebb5c919031f293291a53Chiao Chengimport com.google.common.base.Preconditions;
52c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
53c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon/**
54c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * Presenter for the Call Card Fragment.
55033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng * <p>
567ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon * This class listens for changes to InCallState and passes it along to the fragment.
57c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon */
58d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonpublic class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
5991a369b019b39c5335a4f5d251691c0cdb657f7dAndrew Lee        implements InCallStateListener, IncomingCallListener, InCallDetailsListener,
60b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        InCallEventListener, CallList.CallUpdateListener {
61be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
6289aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee    public interface EmergencyCallListener {
6389aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee        public void onCallUpdated(BaseFragment fragment, boolean isEmergency);
6489aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee    }
6589aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee
66033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng    private static final String TAG = CallCardPresenter.class.getSimpleName();
679c4226952c74f024c09e0bd381048493993c974eAndrew Lee    private static final long CALL_TIME_UPDATE_INTERVAL_MS = 1000;
688cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
69061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    private final EmergencyCallListener mEmergencyCallListener =
70061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            ObjectFactory.newEmergencyCallListener();
71df3ef3fc3d10573507c6451bffd1f55dfcb475ddAndrew Lee
721b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    private Call mPrimary;
73d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private Call mSecondary;
74d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private ContactCacheEntry mPrimaryContactInfo;
75d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private ContactCacheEntry mSecondaryContactInfo;
7686a7f5639fd0798c3b4500166f97649949237215Andrew Lee    private CallTimer mCallTimer;
773d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private Context mContext;
78b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    private boolean mSpinnerShowing = false;
7981ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn    private boolean mHasShownToast = false;
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;
12481ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn            if (shouldShowNoteSentToast(mPrimary)) {
12581ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn                final CallCardUi ui = getUi();
12681ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn                if (ui != null) {
12781ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn                    ui.showNoteSentToast();
12881ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn                }
12981ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn            }
130b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn            CallList.getInstance().addCallUpdateListener(call.getId(), this);
131656dd4a0d8571b47ecf0ecf3e4c2eeacfd1099b3Chiao Cheng
1324a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng            // start processing lookups right away.
133812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            if (!call.isConferenceCall()) {
134248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                startContactInfoSearch(call, true, call.getState() == Call.State.INCOMING);
135812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            } else {
136017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                updateContactEntry(null, true);
137812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            }
1384a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng        }
139fd0b577edffa5413adfda1503038a3bff3247106Yorke Lee
140fd0b577edffa5413adfda1503038a3bff3247106Yorke Lee        onStateChange(null, InCallPresenter.getInstance().getInCallState(), CallList.getInstance());
141033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng    }
142033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng
143c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    @Override
144c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    public void onUiReady(CallCardUi ui) {
145c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon        super.onUiReady(ui);
1461b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
14742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // Contact search may have completed before ui is ready.
14842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (mPrimaryContactInfo != null) {
149017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updatePrimaryDisplayInfo();
15042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
15142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
1521f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        // Register for call state changes last
1531f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        InCallPresenter.getInstance().addListener(this);
1541c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        InCallPresenter.getInstance().addIncomingCallListener(this);
1550e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        InCallPresenter.getInstance().addDetailsListener(this);
156350fff554bf7ed5b9e91985935488771156953abTyler Gunn        InCallPresenter.getInstance().addInCallEventListener(this);
1571b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    }
1581b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
1591b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    @Override
1601b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    public void onUiUnready(CallCardUi ui) {
1611b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        super.onUiUnready(ui);
1621b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
1631f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        // stop getting call state changes
1641f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        InCallPresenter.getInstance().removeListener(this);
1651c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        InCallPresenter.getInstance().removeIncomingCallListener(this);
1660e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        InCallPresenter.getInstance().removeDetailsListener(this);
167350fff554bf7ed5b9e91985935488771156953abTyler Gunn        InCallPresenter.getInstance().removeInCallEventListener(this);
168b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        if (mPrimary != null) {
169b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn            CallList.getInstance().removeCallUpdateListener(mPrimary.getId(), this);
170b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        }
1711f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon
1721b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        mPrimary = null;
173d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        mPrimaryContactInfo = null;
174d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        mSecondaryContactInfo = null;
175c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    }
176c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
177c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    @Override
178f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen    public void onIncomingCall(InCallState oldState, InCallState newState, Call call) {
1791c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        // same logic should happen as with onStateChange()
180f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        onStateChange(oldState, newState, CallList.getInstance());
1811c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon    }
1821c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon
1831c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon    @Override
184f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen    public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
185f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        Log.d(this, "onStateChange() " + newState);
18675c86b55d45b1725c46ed2e5d77c9c43fcfd93daSantos Cordon        final CallCardUi ui = getUi();
1871b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        if (ui == null) {
1881b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon            return;
1891b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        }
190c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
1917ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        Call primary = null;
1927ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        Call secondary = null;
1937ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
194f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        if (newState == InCallState.INCOMING) {
1957ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon            primary = callList.getIncomingCall();
196f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        } else if (newState == InCallState.PENDING_OUTGOING || newState == InCallState.OUTGOING) {
197950e3df8ac744daf2a890d279566bdba424710f9Santos Cordon            primary = callList.getOutgoingCall();
198f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen            if (primary == null) {
199f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen                primary = callList.getPendingOutgoingCall();
200f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen            }
201950e3df8ac744daf2a890d279566bdba424710f9Santos Cordon
20282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            // getCallToDisplay doesn't go through outgoing or incoming calls. It will return the
20382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            // highest priority call to display as the secondary call.
204d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            secondary = getCallToDisplay(callList, null, true);
205f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen        } else if (newState == InCallState.INCALL) {
206d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            primary = getCallToDisplay(callList, null, false);
207d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            secondary = getCallToDisplay(callList, primary, true);
2087ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        }
2097ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
210a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng        Log.d(this, "Primary call: " + primary);
211a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng        Log.d(this, "Secondary call: " + secondary);
2127ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
213fb008c2423a510a57be251d16bc963f64e98c2daRoshan Pius        final boolean primaryChanged = !(Call.areSame(mPrimary, primary) &&
214fb008c2423a510a57be251d16bc963f64e98c2daRoshan Pius                Call.areSameNumber(mPrimary, primary));
215fb008c2423a510a57be251d16bc963f64e98c2daRoshan Pius        final boolean secondaryChanged = !(Call.areSame(mSecondary, secondary) &&
216fb008c2423a510a57be251d16bc963f64e98c2daRoshan Pius                Call.areSameNumber(mSecondary, secondary));
217061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        final boolean shouldShowCallSubject = shouldShowCallSubject(mPrimary);
2189c98346835b8e902e0c2c11f14a35f4e91578e9fAndrew Lee
219812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        mSecondary = secondary;
220b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        Call previousPrimary = mPrimary;
221812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        mPrimary = primary;
222812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
22381ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn        if (primaryChanged && shouldShowNoteSentToast(primary)) {
22481ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn            ui.showNoteSentToast();
22581ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn        }
22681ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn
2270cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        // Refresh primary call information if either:
2280cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        // 1. Primary call changed.
2290cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        // 2. The call's ability to manage conference has changed.
2300cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        if (mPrimary != null && (primaryChanged ||
231061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                ui.isManageConferenceVisible() != shouldShowManageConference()) ||
232061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                ui.isCallSubjectVisible() != shouldShowCallSubject) {
233812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            // primary call has changed
234b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn            if (previousPrimary != null) {
235b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn                CallList.getInstance().removeCallUpdateListener(previousPrimary.getId(), this);
236b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn            }
237b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn            CallList.getInstance().addCallUpdateListener(mPrimary.getId(), this);
238b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn
239248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            mPrimaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext, mPrimary,
240248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                    mPrimary.getState() == Call.State.INCOMING);
241017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updatePrimaryDisplayInfo();
242812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            maybeStartSearch(mPrimary, true);
2439c4226952c74f024c09e0bd381048493993c974eAndrew Lee            mPrimary.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
24442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
24542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
2462d7bf90875bea954ceacdacd9e52c840200bde37Yorke Lee        if (previousPrimary != null && mPrimary == null) {
2472d7bf90875bea954ceacdacd9e52c840200bde37Yorke Lee            CallList.getInstance().removeCallUpdateListener(previousPrimary.getId(), this);
2482d7bf90875bea954ceacdacd9e52c840200bde37Yorke Lee        }
2492d7bf90875bea954ceacdacd9e52c840200bde37Yorke Lee
250812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        if (mSecondary == null) {
25142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // Secondary call may have ended.  Update the ui.
25242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mSecondaryContactInfo = null;
253017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updateSecondaryDisplayInfo();
254812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        } else if (secondaryChanged) {
255812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            // secondary call has changed
256248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            mSecondaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext, mSecondary,
257248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                    mSecondary.getState() == Call.State.INCOMING);
258017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updateSecondaryDisplayInfo();
259812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            maybeStartSearch(mSecondary, false);
2609c4226952c74f024c09e0bd381048493993c974eAndrew Lee            mSecondary.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
26142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
26242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
2639c4226952c74f024c09e0bd381048493993c974eAndrew Lee        // Start/stop timers.
2648cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        if (isPrimaryCallActive()) {
265a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng            Log.d(this, "Starting the calltime timer");
2669c4226952c74f024c09e0bd381048493993c974eAndrew Lee            mCallTimer.start(CALL_TIME_UPDATE_INTERVAL_MS);
2678cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        } else {
268a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng            Log.d(this, "Canceling the calltime timer");
2698cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            mCallTimer.cancel();
270f0dfbe2e89df0d58efde8b290662072c081e146aNancy Chen            ui.setPrimaryCallElapsedTime(false, 0);
2718cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        }
2728cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
273d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        // Set the call state
2748aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton        int callState = Call.State.IDLE;
275d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        if (mPrimary != null) {
27632027ae1f52232258cc8133d383459f3b4ee57e4Yorke Lee            callState = mPrimary.getState();
277ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            updatePrimaryCallState();
27882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        } else {
2799c4226952c74f024c09e0bd381048493993c974eAndrew Lee            getUi().setCallState(
2809c4226952c74f024c09e0bd381048493993c974eAndrew Lee                    callState,
281678775006531155eec0da47ae6889bf03ad9a710Yorke Lee                    VideoProfile.STATE_AUDIO_ONLY,
2829c4226952c74f024c09e0bd381048493993c974eAndrew Lee                    Call.SessionModificationState.NO_REQUEST,
28350dbb6eeca55cf78e0fd9eb132a26787d293620aAndrew Lee                    new DisconnectCause(DisconnectCause.UNKNOWN),
2849c4226952c74f024c09e0bd381048493993c974eAndrew Lee                    null,
2859c4226952c74f024c09e0bd381048493993c974eAndrew Lee                    null,
28682332c921b8dcef213700822e2404b005adab00cAndrew Lee                    null,
287dc3122e9d7bc0c6f5fef00bed36bb300c40afadfAndrew Lee                    false /* isWifi */,
288dc3122e9d7bc0c6f5fef00bed36bb300c40afadfAndrew Lee                    false /* isConference */);
2898cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee            getUi().showHdAudioIndicator(false);
29082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
291e26b887e90d5e9566a5054a1ccb3ed32ae2eea2dAndrew Lee
2921da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee        maybeShowManageConferenceCallButton();
2931da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee
294c44f654b992c6ab8a4acff9cb5aa2678c58755d9Andrew Lee        // Hide the end call button instantly if we're receiving an incoming call.
295fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        getUi().setEndCallButtonEnabled(shouldShowEndCallButton(mPrimary, callState),
296fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee                callState != Call.State.INCOMING /* animate */);
2970dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee
2980dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        maybeSendAccessibilityEvent(oldState, newState);
2991b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    }
3001b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
3011b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    @Override
3028cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee    public void onDetailsChanged(Call call, Details details) {
303ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        updatePrimaryCallState();
304e0ec202ff354be3cd3bded7af8fca678dea7fb61Andrew Lee
3058cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        if (call.can(Details.CAPABILITY_MANAGE_CONFERENCE) !=
3068cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee                Details.can(details.getCallCapabilities(), Details.CAPABILITY_MANAGE_CONFERENCE)) {
307e0ec202ff354be3cd3bded7af8fca678dea7fb61Andrew Lee            maybeShowManageConferenceCallButton();
308e0ec202ff354be3cd3bded7af8fca678dea7fb61Andrew Lee        }
3090786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton    }
3100786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton
311b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    @Override
312b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    public void onCallChanged(Call call) {
313b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        // No-op; specific call updates handled elsewhere.
314b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    }
315b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn
316b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    /**
317b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     * Handles a change to the session modification state for a call.  Triggers showing the progress
318b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     * spinner, as well as updating the call state label.
319b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     *
320b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     * @param sessionModificationState The new session modification state.
321b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     */
322b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    @Override
323b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    public void onSessionModificationStateChange(int sessionModificationState) {
324b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        Log.d(this, "onSessionModificationStateChange : sessionModificationState = " +
325b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn                sessionModificationState);
326b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn
327b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        if (mPrimary == null) {
328b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn            return;
329b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        }
330b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        maybeShowProgressSpinner(mPrimary.getState(), sessionModificationState);
331b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        getUi().setEndCallButtonEnabled(sessionModificationState !=
332b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn                        Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST,
333b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn                true /* shouldAnimate */);
334b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        updatePrimaryCallState();
335b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    }
336b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn
337061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    /**
338061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     * Handles a change to the last forwarding number by refreshing the primary call info.
339061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     */
340061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    @Override
341061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    public void onLastForwardedNumberChange() {
342061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        Log.v(this, "onLastForwardedNumberChange");
343061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn
344061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        if (mPrimary == null) {
345061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            return;
346061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        }
347061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        updatePrimaryDisplayInfo();
348061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    }
349061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn
3500786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton    private String getSubscriptionNumber() {
3510786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        // If it's an emergency call, and they're not populating the callback number,
3520786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        // then try to fall back to the phone sub info (to hopefully get the SIM's
3530786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        // number directly from the telephony layer).
35476e1b4bfb2e21300068f10cc94922214e62c8f86Evan Charlton        PhoneAccountHandle accountHandle = mPrimary.getAccountHandle();
35576e1b4bfb2e21300068f10cc94922214e62c8f86Evan Charlton        if (accountHandle != null) {
356170e405691a237b74fbecbf41208cbaa5bd36442Nancy Chen            TelecomManager mgr = InCallPresenter.getInstance().getTelecomManager();
357b6f45c2768f5af916ee3257542a3ab03611c1f5eEvan Charlton            PhoneAccount account = mgr.getPhoneAccount(accountHandle);
358b6f45c2768f5af916ee3257542a3ab03611c1f5eEvan Charlton            if (account != null) {
3599e27dca4bc1be09bcb1d283b2fe3ba3d49f0748bAndrew Lee                return getNumberFromHandle(account.getSubscriptionAddress());
360c108b49ad5440fbf381c9a589d8a217da3efcb64Ihab Awad            }
3610e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        }
3620786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        return null;
3630e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    }
3640e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
365ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal    private void updatePrimaryCallState() {
366ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        if (getUi() != null && mPrimary != null) {
367ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            getUi().setCallState(
368ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    mPrimary.getState(),
369ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    mPrimary.getVideoState(),
370ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    mPrimary.getSessionModificationState(),
371ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    mPrimary.getDisconnectCause(),
372ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                    getConnectionLabel(),
3736c3061091e59e9ab06b620c2615b897e2eca233cAndrew Lee                    getCallStateIcon(),
37482332c921b8dcef213700822e2404b005adab00cAndrew Lee                    getGatewayNumber(),
37559585f80dce30e53ea30f08f11089f6cdd6e41fbAndrew Lee                    mPrimary.hasProperty(Details.PROPERTY_WIFI),
376dc3122e9d7bc0c6f5fef00bed36bb300c40afadfAndrew Lee                    mPrimary.isConferenceCall());
3778cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee
378061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            maybeShowHdAudioIcon();
379ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            setCallbackNumber();
380ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        }
381ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal    }
3820786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton
3831da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee    /**
384061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     * Show the HD icon if the call is active and has {@link Details#PROPERTY_HIGH_DEF_AUDIO},
385061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     * except if the call has a last forwarded number (we will show that icon instead).
386061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     */
387061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    private void maybeShowHdAudioIcon() {
388061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        boolean showHdAudioIndicator =
389061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                isPrimaryCallActive() && mPrimary.hasProperty(Details.PROPERTY_HIGH_DEF_AUDIO) &&
390061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                TextUtils.isEmpty(mPrimary.getLastForwardedNumber());
391061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        getUi().showHdAudioIndicator(showHdAudioIndicator);
392061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    }
393061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn
394061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    /**
395289d53ed1c879e983dcb021fa677212ab4566bbdSantos Cordon     * Only show the conference call button if we can manage the conference.
3961da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee     */
3971da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee    private void maybeShowManageConferenceCallButton() {
3980cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        getUi().showManageConferenceCallButton(shouldShowManageConference());
3990cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn    }
4000cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn
401b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    /**
402b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     * Determines if a pending session modification exists for the current call.  If so, the
403b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     * progress spinner is shown, and the call state is updated.
404b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     *
405b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     * @param callState The call state.
406b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     * @param sessionModificationState The session modification state.
407b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn     */
408b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn    private void maybeShowProgressSpinner(int callState, int sessionModificationState) {
409b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        final boolean show = sessionModificationState ==
410b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn                Call.SessionModificationState.WAITING_FOR_RESPONSE
411b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn                && callState == Call.State.ACTIVE;
412b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        if (show != mSpinnerShowing) {
413b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn            getUi().setProgressSpinnerVisible(show);
414b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn            mSpinnerShowing = show;
415b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        }
41655576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee    }
41755576e529a3fa7183a698669374b9c2dd28ad5c5Yorke Lee
4180cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn    /**
4190cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     * Determines if the manage conference button should be visible, based on the current primary
4200cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     * call.
4210cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     *
4220cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     * @return {@code True} if the manage conference button should be visible.
4230cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn     */
4240cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn    private boolean shouldShowManageConference() {
425e16e53167b367656840df665457e71e66bc966deAndrew Lee        if (mPrimary == null) {
4260cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn            return false;
427e16e53167b367656840df665457e71e66bc966deAndrew Lee        }
428e16e53167b367656840df665457e71e66bc966deAndrew Lee
42918c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar        return mPrimary.can(android.telecom.Call.Details.CAPABILITY_MANAGE_CONFERENCE)
43018c0feda76fe333f3db1bf7bd307458a9e6b6005Rekha Kumar                && !mPrimary.isVideoCall(mContext);
4311da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee    }
4321da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee
433ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal    private void setCallbackNumber() {
434ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        String callbackNumber = null;
4350786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton
436c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        // Show the emergency callback number if either:
437c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        // 1. This is an emergency call.
438c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        // 2. The phone is in Emergency Callback Mode, which means we should show the callback
439c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        //    number.
44059585f80dce30e53ea30f08f11089f6cdd6e41fbAndrew Lee        boolean showCallbackNumber = mPrimary.hasProperty(Details.PROPERTY_EMERGENCY_CALLBACK_MODE);
441c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn
44293a6fd8d4a6f3ff4732cb4fb3b9df7c522b92823Tyler Gunn        if (mPrimary.isEmergencyCall() || showCallbackNumber) {
443ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            callbackNumber = getSubscriptionNumber();
444ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        } else {
4459124b77e489772fb7c6aac36f83d86ffdf83748fJay Shrauner            StatusHints statusHints = mPrimary.getTelecomCall().getDetails().getStatusHints();
446ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            if (statusHints != null) {
447ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                Bundle extras = statusHints.getExtras();
448ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                if (extras != null) {
4494b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunn                    callbackNumber = extras.getString(TelecomManager.EXTRA_CALL_BACK_NUMBER);
4500786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton                }
4510e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton            }
4520786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        }
4530786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton
4546dfd1963ecc89ecb2c76793ab40af26e35654285Nancy Chen        TelecomManager mgr = InCallPresenter.getInstance().getTelecomManager();
4556dfd1963ecc89ecb2c76793ab40af26e35654285Nancy Chen        String simNumber = mgr.getLine1Number(mPrimary.getAccountHandle());
456c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn        if (!showCallbackNumber && PhoneNumberUtils.compare(callbackNumber, simNumber)) {
457c4fac46c65d20da815b37f3d1dbe2ff748fa1f00Tyler Gunn            Log.d(this, "Numbers are the same (and callback number is not being forced to show);" +
4583326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn                    " not showing the callback number");
459ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            callbackNumber = null;
4600786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        }
461ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal
46293a6fd8d4a6f3ff4732cb4fb3b9df7c522b92823Tyler Gunn        getUi().setCallbackNumber(callbackNumber, mPrimary.isEmergencyCall() || showCallbackNumber);
4630e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    }
4640e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
4658cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon    public void updateCallTime() {
4668cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        final CallCardUi ui = getUi();
4678cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
4688cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        if (ui == null) {
4698cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee            mCallTimer.cancel();
4708cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        } else if (!isPrimaryCallActive()) {
4718cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee            ui.setPrimaryCallElapsedTime(false, 0);
4728cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            mCallTimer.cancel();
473899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon        } else {
474c6f4e50a4130fb8f7247f5eab6849829701ad484Sailesh Nepal            final long callStart = mPrimary.getConnectTimeMillis();
475899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon            final long duration = System.currentTimeMillis() - callStart;
476f0dfbe2e89df0d58efde8b290662072c081e146aNancy Chen            ui.setPrimaryCallElapsedTime(true, duration);
4778cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        }
4788cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon    }
4798cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
480f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton    public void onCallStateButtonTouched() {
48171afa1c7d1e1f49af56c24bdc64d30d80cf1ea68Evan Charlton        Intent broadcastIntent = ObjectFactory.getCallStateButtonBroadcastIntent(mContext);
482f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton        if (broadcastIntent != null) {
483f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton            Log.d(this, "Sending call state button broadcast: ", broadcastIntent);
484f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton            mContext.sendBroadcast(broadcastIntent, Manifest.permission.READ_PHONE_STATE);
485f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton        }
486f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton    }
487f925b504266f80ec0b74212c403475f5cc790ab0Evan Charlton
4883326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn    /**
4893326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn     * Handles click on the contact photo by toggling fullscreen mode if the current call is a video
4903326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn     * call.
4913326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn     */
4923326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn    public void onContactPhotoClick() {
4933326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn        if (mPrimary != null && mPrimary.isVideoCall(mContext)) {
4943326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn            InCallPresenter.getInstance().toggleFullscreenMode();
4953326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn        }
4963326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn    }
4973326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn
498812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    private void maybeStartSearch(Call call, boolean isPrimary) {
499812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        // no need to start search for conference calls which show generic info.
500812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        if (call != null && !call.isConferenceCall()) {
501248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            startContactInfoSearch(call, isPrimary, call.getState() == Call.State.INCOMING);
502812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        }
503812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    }
504812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
50582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon    /**
506d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon     * Starts a query for more contact data for the save primary and secondary calls.
507d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon     */
508248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal    private void startContactInfoSearch(final Call call, final boolean isPrimary,
509248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            boolean isIncoming) {
51042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        final ContactInfoCache cache = ContactInfoCache.getInstance(mContext);
51142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
5125b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        cache.findInfo(call, isIncoming, new ContactLookupCallback(this, isPrimary));
5135b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    }
5147d2fb8620b808c28c49bde99dc54f6de46fdcb44Chiao Cheng
5155b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    private void onContactInfoComplete(String callId, ContactCacheEntry entry, boolean isPrimary) {
516017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        updateContactEntry(entry, isPrimary);
5175b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        if (entry.name != null) {
5185b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            Log.d(TAG, "Contact found: " + entry);
5195b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
5205b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        if (entry.contactUri != null) {
5215b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            CallerInfoUtils.sendViewNotification(mContext, entry.contactUri);
5225b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
5235b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    }
5245b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee
5255b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee    private void onImageLoadComplete(String callId, ContactCacheEntry entry) {
5265b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        if (getUi() == null) {
5275b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            return;
5285b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
529f003346e5f9ba29e869a881bcca2e59d6ea8e0f6Nancy Chen
5305b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        if (entry.photo != null) {
5315b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            if (mPrimary != null && callId.equals(mPrimary.getId())) {
532fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                boolean showContactPhoto = !VideoCallPresenter.showIncomingVideo(
533fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                        mPrimary.getVideoState(), mPrimary.getState());
534fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                getUi().setPrimaryImage(entry.photo, showContactPhoto);
5355b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee            }
5365b3f5ed7d9ffa02c2255a68e6a4be969f0116104Yorke Lee        }
53742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    }
53842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
539017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private void updateContactEntry(ContactCacheEntry entry, boolean isPrimary) {
54042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (isPrimary) {
54142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mPrimaryContactInfo = entry;
542017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updatePrimaryDisplayInfo();
543d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        } else {
54442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mSecondaryContactInfo = entry;
545017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            updateSecondaryDisplayInfo();
546d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        }
547d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    }
548d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon
549d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    /**
55082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * Get the highest priority call to display.
55182f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * Goes through the calls and chooses which to return based on priority of which type of call
55282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * to display to the user. Callers can use the "ignore" feature to get the second best call
55382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * by passing a previously found primary call as ignore.
55482f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     *
55582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * @param ignore A call to ignore if found.
55682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     */
557d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private Call getCallToDisplay(CallList callList, Call ignore, boolean skipDisconnected) {
558d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // Active calls come second.  An active call always gets precedent.
559d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        Call retval = callList.getActiveCall();
56082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        if (retval != null && retval != ignore) {
56182f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            return retval;
56282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
56382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
564d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // Disconnected calls get primary position if there are no active calls
565d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // to let user know quickly what call has disconnected. Disconnected
566d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // calls are very short lived.
567d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (!skipDisconnected) {
5686258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            retval = callList.getDisconnectingCall();
5696258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            if (retval != null && retval != ignore) {
5706258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen                return retval;
5716258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            }
572d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            retval = callList.getDisconnectedCall();
573d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            if (retval != null && retval != ignore) {
574d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon                return retval;
575d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            }
57682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
57782f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
57882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        // Then we go to background call (calls on hold)
57982f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        retval = callList.getBackgroundCall();
58082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        if (retval != null && retval != ignore) {
58182f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            return retval;
58282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
58382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
58482f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        // Lastly, we go to a second background call.
58582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        retval = callList.getSecondBackgroundCall();
58682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
58782f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        return retval;
58882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon    }
58982f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
590017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private void updatePrimaryDisplayInfo() {
5916d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        final CallCardUi ui = getUi();
592d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        if (ui == null) {
59342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // TODO: May also occur if search result comes back after ui is destroyed. Look into
59442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // removing that case completely.
59542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            Log.d(TAG, "updatePrimaryDisplayInfo called but ui is null!");
596d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon            return;
5976d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        }
598be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
599017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        if (mPrimary == null) {
600017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            // Clear the primary display info.
601fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn            ui.setPrimary(null, null, false, null, null, false, false);
602017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            return;
603017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        }
604017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
605fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn        // Hide the contact photo if we are in a video call and the incoming video surface is
606fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn        // showing.
607fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn        boolean showContactPhoto = !VideoCallPresenter
608fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                .showIncomingVideo(mPrimary.getVideoState(), mPrimary.getState());
609fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn
610017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        if (mPrimary.isConferenceCall()) {
611017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            Log.d(TAG, "Update primary display info for conference call.");
612017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
613017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setPrimary(
614017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    null /* number */,
615017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getConferenceString(mPrimary),
616017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    false /* nameIsNumber */,
617017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    null /* label */,
618017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getConferencePhoto(mPrimary),
619fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                    false /* isSipCall */,
620fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                    showContactPhoto);
621017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        } else if (mPrimaryContactInfo != null) {
622017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            Log.d(TAG, "Update primary display info for " + mPrimaryContactInfo);
623017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
624017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            String name = getNameForCall(mPrimaryContactInfo);
625460ac2da6d15bd94fe31c1a30d12418d01d8976aTyler Gunn            String number;
626460ac2da6d15bd94fe31c1a30d12418d01d8976aTyler Gunn
627460ac2da6d15bd94fe31c1a30d12418d01d8976aTyler Gunn            boolean isChildNumberShown = !TextUtils.isEmpty(mPrimary.getChildNumber());
628061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            boolean isForwardedNumberShown = !TextUtils.isEmpty(mPrimary.getLastForwardedNumber());
629061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            boolean isCallSubjectShown = shouldShowCallSubject(mPrimary);
630061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn
631061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            if (isCallSubjectShown) {
632061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                ui.setCallSubject(mPrimary.getCallSubject());
633061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            } else {
634061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                ui.setCallSubject(null);
635061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            }
636061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn
637061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            if (isCallSubjectShown) {
638061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                number = null;
639061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            } else if (isChildNumberShown) {
640460ac2da6d15bd94fe31c1a30d12418d01d8976aTyler Gunn                number = mContext.getString(R.string.child_number, mPrimary.getChildNumber());
641061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            } else if (isForwardedNumberShown) {
642061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                // Use last forwarded number instead of second line, if present.
643061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                number = mPrimary.getLastForwardedNumber();
644460ac2da6d15bd94fe31c1a30d12418d01d8976aTyler Gunn            } else {
645460ac2da6d15bd94fe31c1a30d12418d01d8976aTyler Gunn                number = getNumberForCall(mPrimaryContactInfo);
646460ac2da6d15bd94fe31c1a30d12418d01d8976aTyler Gunn            }
647460ac2da6d15bd94fe31c1a30d12418d01d8976aTyler Gunn
648061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            ui.showForwardIndicator(isForwardedNumberShown);
649061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            maybeShowHdAudioIcon();
650061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn
651017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            boolean nameIsNumber = name != null && name.equals(mPrimaryContactInfo.number);
652017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setPrimary(
653017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    number,
654017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    name,
655017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    nameIsNumber,
656061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                    isChildNumberShown || isCallSubjectShown ? null : mPrimaryContactInfo.label,
657017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    mPrimaryContactInfo.photo,
658fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                    mPrimaryContactInfo.isSipCall,
659fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                    showContactPhoto);
6606d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        } else {
661017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            // Clear the primary display info.
662fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn            ui.setPrimary(null, null, false, null, null, false, false);
663d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        }
664d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon
66589aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee        if (mEmergencyCallListener != null) {
66693a6fd8d4a6f3ff4732cb4fb3b9df7c522b92823Tyler Gunn            boolean isEmergencyCall = mPrimary.isEmergencyCall();
66789aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee            mEmergencyCallListener.onCallUpdated((BaseFragment) ui, isEmergencyCall);
66889aad4adce9cc66294f15391fa3e10f3123d3d92Andrew Lee        }
669d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    }
670d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon
671017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private void updateSecondaryDisplayInfo() {
67242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        final CallCardUi ui = getUi();
67342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (ui == null) {
67442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            return;
67542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
67642373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
677017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        if (mSecondary == null) {
678017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            // Clear the secondary display info.
679e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn            ui.setSecondary(false, null, false, null, null, false /* isConference */,
680c59f080516998219356ecda39efa7b1c7539ccaeEtan Cohen                    false /* isVideoCall */);
681017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            return;
682017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        }
683c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee
684017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        if (mSecondary.isConferenceCall()) {
685017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setSecondary(
686017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    true /* show */,
687017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getConferenceString(mSecondary),
688017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    false /* nameIsNumber */,
689017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    null /* label */,
690017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getCallProviderLabel(mSecondary),
691e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                    true /* isConference */,
692c59f080516998219356ecda39efa7b1c7539ccaeEtan Cohen                    mSecondary.isVideoCall(mContext));
693017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        } else if (mSecondaryContactInfo != null) {
694017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            Log.d(TAG, "updateSecondaryDisplayInfo() " + mSecondaryContactInfo);
695017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            String name = getNameForCall(mSecondaryContactInfo);
696017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            boolean nameIsNumber = name != null && name.equals(mSecondaryContactInfo.number);
697017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            ui.setSecondary(
698017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    true /* show */,
699017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    name,
700017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    nameIsNumber,
701017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    mSecondaryContactInfo.label,
702017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                    getCallProviderLabel(mSecondary),
703e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn                    false /* isConference */,
704c59f080516998219356ecda39efa7b1c7539ccaeEtan Cohen                    mSecondary.isVideoCall(mContext));
70542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        } else {
706017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee            // Clear the secondary display info.
707e96c83ad0a8f52a060d0ba7eac2290eb95b3b1c5Tyler Gunn            ui.setSecondary(false, null, false, null, null, false /* isConference */,
708c59f080516998219356ecda39efa7b1c7539ccaeEtan Cohen                    false /* isVideoCall */);
70942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
71042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    }
71142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
7128a80413884d1afbd7e021d581546c2245f068619Nancy Chen
7138a80413884d1afbd7e021d581546c2245f068619Nancy Chen    /**
7148a80413884d1afbd7e021d581546c2245f068619Nancy Chen     * Gets the phone account to display for a call.
7158a80413884d1afbd7e021d581546c2245f068619Nancy Chen     */
7168a80413884d1afbd7e021d581546c2245f068619Nancy Chen    private PhoneAccount getAccountForCall(Call call) {
7178a80413884d1afbd7e021d581546c2245f068619Nancy Chen        PhoneAccountHandle accountHandle = call.getAccountHandle();
7188a80413884d1afbd7e021d581546c2245f068619Nancy Chen        if (accountHandle == null) {
7198a80413884d1afbd7e021d581546c2245f068619Nancy Chen            return null;
7208a80413884d1afbd7e021d581546c2245f068619Nancy Chen        }
721170e405691a237b74fbecbf41208cbaa5bd36442Nancy Chen        return InCallPresenter.getInstance().getTelecomManager().getPhoneAccount(accountHandle);
7228a80413884d1afbd7e021d581546c2245f068619Nancy Chen    }
7238a80413884d1afbd7e021d581546c2245f068619Nancy Chen
7243d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    /**
7253d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     * Returns the gateway number for any existing outgoing call.
7263d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     */
7273d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private String getGatewayNumber() {
7283d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        if (hasOutgoingGatewayCall()) {
72907fd3fd3ac627faf1771ba4699fe53a0479f2293Nancy Chen            return getNumberFromHandle(mPrimary.getGatewayInfo().getGatewayAddress());
7303d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        }
7313d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        return null;
7323d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
7333d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
7343d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    /**
7358a80413884d1afbd7e021d581546c2245f068619Nancy Chen     * Return the string label to represent the call provider
7368a80413884d1afbd7e021d581546c2245f068619Nancy Chen     */
7378a80413884d1afbd7e021d581546c2245f068619Nancy Chen    private String getCallProviderLabel(Call call) {
7388a80413884d1afbd7e021d581546c2245f068619Nancy Chen        PhoneAccount account = getAccountForCall(call);
739170e405691a237b74fbecbf41208cbaa5bd36442Nancy Chen        TelecomManager mgr = InCallPresenter.getInstance().getTelecomManager();
74015b3fb7207bc356b2ee6ce1e8264d8242bb092ecJay Shrauner        if (account != null && !TextUtils.isEmpty(account.getLabel())
7415b592ce22da61660c21752122d8172f7dbc0c796Yorke Lee                && mgr.getCallCapablePhoneAccounts().size() > 1) {
7428a80413884d1afbd7e021d581546c2245f068619Nancy Chen            return account.getLabel().toString();
743bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        }
744bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        return null;
745bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    }
746bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen
747bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    /**
748bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen     * Returns the label (line of text above the number/name) for any given call.
749f8b0677bed382046cb26e38a8442a9509d1e835cSailesh Nepal     * For example, "calling via [Account/Google Voice]" for outgoing calls.
7503d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     */
751bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    private String getConnectionLabel() {
7529124b77e489772fb7c6aac36f83d86ffdf83748fJay Shrauner        StatusHints statusHints = mPrimary.getTelecomCall().getDetails().getStatusHints();
753ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        if (statusHints != null && !TextUtils.isEmpty(statusHints.getLabel())) {
754ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            return statusHints.getLabel().toString();
755ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        }
756ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal
7573d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        if (hasOutgoingGatewayCall() && getUi() != null) {
758bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen            // Return the label for the gateway app on outgoing calls.
7593d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            final PackageManager pm = mContext.getPackageManager();
7603d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            try {
761ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                ApplicationInfo info = pm.getApplicationInfo(
762ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                        mPrimary.getGatewayInfo().getGatewayProviderPackageName(), 0);
763bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                return pm.getApplicationLabel(info).toString();
7643d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            } catch (PackageManager.NameNotFoundException e) {
765bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                Log.e(this, "Gateway Application Not Found.", e);
766bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                return null;
7673d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            }
7683d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        }
7698a80413884d1afbd7e021d581546c2245f068619Nancy Chen        return getCallProviderLabel(mPrimary);
7703d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
7713d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
7726c3061091e59e9ab06b620c2615b897e2eca233cAndrew Lee    private Drawable getCallStateIcon() {
7736c3061091e59e9ab06b620c2615b897e2eca233cAndrew Lee        // Return connection icon if one exists.
7749124b77e489772fb7c6aac36f83d86ffdf83748fJay Shrauner        StatusHints statusHints = mPrimary.getTelecomCall().getDetails().getStatusHints();
77518aaec1d250a5c5239ec5f06363f6fbb2519c55eIhab Awad        if (statusHints != null && statusHints.getIcon() != null) {
77618aaec1d250a5c5239ec5f06363f6fbb2519c55eIhab Awad            Drawable icon = statusHints.getIcon().loadDrawable(mContext);
777ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            if (icon != null) {
778ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal                return icon;
779ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal            }
780ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal        }
7816c3061091e59e9ab06b620c2615b897e2eca233cAndrew Lee
782ab86f04c5ed385eafcd9099fa4ca50fd2f4c5c33Nancy Chen        return null;
783ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal    }
784ee9ec0928055307dc5d1f5c7509c301951a444a5Sailesh Nepal
7853d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private boolean hasOutgoingGatewayCall() {
786b040158d7bb2f5c7d06bd2c1db5e96adafbcff3eTyler Gunn        // We only display the gateway information while STATE_DIALING so return false for any other
7873d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        // call state.
78842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // TODO: mPrimary can be null because this is called from updatePrimaryDisplayInfo which
78942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // is also called after a contact search completes (call is not present yet).  Split the
79042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // UI update so it can receive independent updates.
79142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (mPrimary == null) {
79242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            return false;
79342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
794ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal        return Call.State.isDialing(mPrimary.getState()) && mPrimary.getGatewayInfo() != null &&
795ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                !mPrimary.getGatewayInfo().isEmpty();
7963d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
7973d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
798d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    /**
799d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     * Gets the name to display for the call.
800d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     */
801d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private static String getNameForCall(ContactCacheEntry contactInfo) {
802d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (TextUtils.isEmpty(contactInfo.name)) {
803d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            return contactInfo.number;
8046d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        }
805d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        return contactInfo.name;
806d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    }
8076d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
808d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    /**
809d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     * Gets the number to display for a call.
810d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     */
811d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private static String getNumberForCall(ContactCacheEntry contactInfo) {
812d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // If the name is empty, we use the number for the name...so dont show a second
813d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // number in the number field
814d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (TextUtils.isEmpty(contactInfo.name)) {
8151c6bb983216392b5ceb36cea42a46631f68a3dd6Jay Shrauner            return contactInfo.location;
816d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        }
817d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        return contactInfo.number;
818d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    }
8196d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
820e5c0d8bdf8269f9435e0381889e4870f36a43f07Andrew Lee    public void secondaryInfoClicked() {
82180c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee        if (mSecondary == null) {
8228b514c9571c587b2e87edfffa38afde4f0458579Nancy Chen            Log.w(this, "Secondary info clicked but no secondary call.");
82380c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee            return;
82480c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee        }
82580c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee
826248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal        Log.i(this, "Swapping call to foreground: " + mSecondary);
8274b293f0f08030c97e1bb54d2f79ac2fb1a6e29aeTyler Gunn        TelecomAdapter.getInstance().unholdCall(mSecondary.getId());
82890995fcb6778a9cb6dc35be12aeb1a5d0dcbb5aeYorke Lee    }
82990995fcb6778a9cb6dc35be12aeb1a5d0dcbb5aeYorke Lee
8307e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee    public void endCallClicked() {
8317e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee        if (mPrimary == null) {
8327e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee            return;
8337e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee        }
8347e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee
835cb2f51bf1acf387f391ca9c8cae8a2344eb2936aEvan Charlton        Log.i(this, "Disconnecting call: " + mPrimary);
836d274e92414988c72708af270e3799b83b4e3b40cJay Shrauner        final String callId = mPrimary.getId();
83733478eae2d380adfcc7ef3f51816ff391a42ebb7Ihab Awad        mPrimary.setState(Call.State.DISCONNECTING);
83833478eae2d380adfcc7ef3f51816ff391a42ebb7Ihab Awad        CallList.getInstance().onUpdate(mPrimary);
839d274e92414988c72708af270e3799b83b4e3b40cJay Shrauner        TelecomAdapter.getInstance().disconnectCall(callId);
8407e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee    }
8417e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee
842da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordon    private String getNumberFromHandle(Uri handle) {
843da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordon        return handle == null ? "" : handle.getSchemeSpecificPart();
844da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordon    }
845da7f422a46db4bfe5cf76312d23b44e60fa9d806Santos Cordon
846350fff554bf7ed5b9e91985935488771156953abTyler Gunn    /**
8473326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn     * Handles a change to the fullscreen mode of the in-call UI.
848350fff554bf7ed5b9e91985935488771156953abTyler Gunn     *
8493326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn     * @param isFullscreenMode {@code True} if the in-call UI is entering full screen mode.
850350fff554bf7ed5b9e91985935488771156953abTyler Gunn     */
851350fff554bf7ed5b9e91985935488771156953abTyler Gunn    @Override
8523326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn    public void onFullscreenModeChanged(boolean isFullscreenMode) {
853350fff554bf7ed5b9e91985935488771156953abTyler Gunn        final CallCardUi ui = getUi();
854350fff554bf7ed5b9e91985935488771156953abTyler Gunn        if (ui == null) {
855350fff554bf7ed5b9e91985935488771156953abTyler Gunn            return;
856350fff554bf7ed5b9e91985935488771156953abTyler Gunn        }
8573326f42f13f6f8cd8934aec615078a8890212402Tyler Gunn        ui.setCallCardVisible(!isFullscreenMode);
858350fff554bf7ed5b9e91985935488771156953abTyler Gunn    }
859350fff554bf7ed5b9e91985935488771156953abTyler Gunn
8608cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee    private boolean isPrimaryCallActive() {
8618cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        return mPrimary != null && mPrimary.getState() == Call.State.ACTIVE;
8628cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee    }
8638cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee
864017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private String getConferenceString(Call call) {
86559585f80dce30e53ea30f08f11089f6cdd6e41fbAndrew Lee        boolean isGenericConference = call.hasProperty(Details.PROPERTY_GENERIC_CONFERENCE);
866017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        Log.v(this, "getConferenceString: " + isGenericConference);
867017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
868017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        final int resId = isGenericConference
869017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                ? R.string.card_title_in_call : R.string.card_title_conf_call;
870017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        return mContext.getResources().getString(resId);
871017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    }
872017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
873017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    private Drawable getConferencePhoto(Call call) {
87459585f80dce30e53ea30f08f11089f6cdd6e41fbAndrew Lee        boolean isGenericConference = call.hasProperty(Details.PROPERTY_GENERIC_CONFERENCE);
875017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        Log.v(this, "getConferencePhoto: " + isGenericConference);
876017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
877017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        final int resId = isGenericConference
878017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee                ? R.drawable.img_phone : R.drawable.img_conference;
879017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        Drawable photo = mContext.getResources().getDrawable(resId);
880017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        photo.setAutoMirrored(true);
881017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee        return photo;
882017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee    }
883017ebaba75180c0a8deb9de3f819cbae92d45e72Andrew Lee
884fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee    private boolean shouldShowEndCallButton(Call primary, int callState) {
885fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        if (primary == null) {
886fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee            return false;
887fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        }
8884c058612097eba72b33d83f5612012a90167957aYorke Lee        if ((!Call.State.isConnectingOrConnected(callState)
8894c058612097eba72b33d83f5612012a90167957aYorke Lee                && callState != Call.State.DISCONNECTING) || callState == Call.State.INCOMING) {
890fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee            return false;
891fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        }
892fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        if (mPrimary.getSessionModificationState()
893fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee                == Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) {
894fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee            return false;
895fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        }
896fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee        return true;
897fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee    }
898fdf53779ba6d68e28e005e3645378aea7bd76ec0Yorke Lee
8990dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee    private void maybeSendAccessibilityEvent(InCallState oldState, InCallState newState) {
9000dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        if (mContext == null) {
9010dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee            return;
9020dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        }
9030dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        final AccessibilityManager am = (AccessibilityManager) mContext.getSystemService(
9040dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee                Context.ACCESSIBILITY_SERVICE);
9050dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        if (!am.isEnabled()) {
9060dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee            return;
9070dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        }
9080dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        if ((oldState != InCallState.OUTGOING && newState == InCallState.OUTGOING)
9090dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee                || (oldState != InCallState.INCOMING && newState == InCallState.INCOMING)) {
9100dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee            if (getUi() != null) {
9110dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee                getUi().sendAccessibilityAnnouncement();
9120dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee            }
9130dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        }
9140dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee    }
9150dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee
916061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    /**
917061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     * Determines whether the call subject should be visible on the UI.  For the call subject to be
918061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     * visible, the call has to be in an incoming or waiting state, and the subject must not be
919061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     * empty.
920061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     *
921061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     * @param call The call.
922061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     * @return {@code true} if the subject should be shown, {@code false} otherwise.
923061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn     */
924061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    private boolean shouldShowCallSubject(Call call) {
925061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        if (call == null) {
926061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn            return false;
927061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        }
928061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn
929061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        boolean isIncomingOrWaiting = mPrimary.getState() == Call.State.INCOMING ||
930061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn                mPrimary.getState() == Call.State.CALL_WAITING;
931061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        return isIncomingOrWaiting && !TextUtils.isEmpty(call.getCallSubject());
932061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn    }
933061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn
93481ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn    /**
93581ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn     * Determines whether the "note sent" toast should be shown.  It should be shown for a new
93681ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn     * outgoing call with a subject.
93781ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn     *
93881ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn     * @param call The call
93981ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn     * @return {@code true} if the toast should be shown, {@code false} otherwise.
94081ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn     */
94181ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn    private boolean shouldShowNoteSentToast(Call call) {
94281ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn        return call != null && !TextUtils
9439124b77e489772fb7c6aac36f83d86ffdf83748fJay Shrauner                .isEmpty(call.getTelecomCall().getDetails().getIntentExtras().getString(
94481ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn                        TelecomManager.EXTRA_CALL_SUBJECT)) &&
94581ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn                (call.getState() == Call.State.DIALING || call.getState() == Call.State.CONNECTING);
94681ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn    }
94781ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn
948d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    public interface CallCardUi extends Ui {
949d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        void setVisible(boolean on);
950350fff554bf7ed5b9e91985935488771156953abTyler Gunn        void setCallCardVisible(boolean visible);
951d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        void setPrimary(String number, String name, boolean nameIsNumber, String label,
952fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn                Drawable photo, boolean isSipCall, boolean isContactPhotoShown);
953c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee        void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
954c59f080516998219356ecda39efa7b1c7539ccaeEtan Cohen                String providerLabel, boolean isConference, boolean isVideoCall);
95550dbb6eeca55cf78e0fd9eb132a26787d293620aAndrew Lee        void setCallState(int state, int videoState, int sessionModificationState,
95650dbb6eeca55cf78e0fd9eb132a26787d293620aAndrew Lee                DisconnectCause disconnectCause, String connectionLabel,
957dc3122e9d7bc0c6f5fef00bed36bb300c40afadfAndrew Lee                Drawable connectionIcon, String gatewayNumber, boolean isWifi,
958dc3122e9d7bc0c6f5fef00bed36bb300c40afadfAndrew Lee                boolean isConference);
959f0dfbe2e89df0d58efde8b290662072c081e146aNancy Chen        void setPrimaryCallElapsedTime(boolean show, long duration);
96042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryName(String name, boolean nameIsNumber);
961fd640ab7b1efe30574c96a12b06627f365d0432aTyler Gunn        void setPrimaryImage(Drawable image, boolean isVisible);
96242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryPhoneNumber(String phoneNumber);
96342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryLabel(String label);
964c44f654b992c6ab8a4acff9cb5aa2678c58755d9Andrew Lee        void setEndCallButtonEnabled(boolean enabled, boolean animate);
9650786dba0baa54fd12697b4795e7c646cfe4ae5c3Evan Charlton        void setCallbackNumber(String number, boolean isEmergencyCalls);
966061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        void setCallSubject(String callSubject);
967350fff554bf7ed5b9e91985935488771156953abTyler Gunn        void setProgressSpinnerVisible(boolean visible);
9688cdac35f2aa80d1732dfc5fdaee1a21035a1bfcbAndrew Lee        void showHdAudioIndicator(boolean visible);
969061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        void showForwardIndicator(boolean visible);
9701da81ce59cfbebd4e53fdfd2011e859069120de7Andrew Lee        void showManageConferenceCallButton(boolean visible);
9710cff18feff43a6915919ac8e32fa44502aa6c320Tyler Gunn        boolean isManageConferenceVisible();
972061fc22101930c3c69f454c85fbb85ff2c5c92fbTyler Gunn        boolean isCallSubjectVisible();
9736596e1be9d3e15e2cbe4a5e9c3824ee47a0e2744Yorke Lee        void animateForNewOutgoingCall();
9740dbdccd2aa0e6828e1332adf83e630a74527a248Yorke Lee        void sendAccessibilityAnnouncement();
97581ae21863de1fe836f5e62aa5e324a35a8eb7d06Tyler Gunn        void showNoteSentToast();
976be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee    }
977c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon}
978