1a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon/*
2a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * Copyright (C) 2013 The Android Open Source Project
3a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon *
4a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
5a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * you may not use this file except in compliance with the License.
6a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * You may obtain a copy of the License at
7a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon *
8a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
9a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon *
10a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * Unless required by applicable law or agreed to in writing, software
11a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
12a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * See the License for the specific language governing permissions and
14a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * limitations under the License
15a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon */
16a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
17a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordonpackage com.android.incallui;
18a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
19f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charltonimport android.Manifest;
203d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordonimport android.content.Context;
21f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charltonimport android.content.Intent;
223d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordonimport android.content.pm.ApplicationInfo;
233d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordonimport android.content.pm.PackageManager;
24988d06b64b99a13f4f060dc82594edcb738d9113Yorke Leeimport android.graphics.drawable.Drawable;
25e038ead8b0e520787b41e5dbd6f4c534881e10d5Santos Cordonimport android.net.Uri;
263f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charltonimport android.os.Bundle;
27017f23c5f9ee2585454b43ae15c14c98e48e8f17Andrew Leeimport android.os.Handler;
28017f23c5f9ee2585454b43ae15c14c98e48e8f17Andrew Leeimport android.telecom.DisconnectCause;
296cddf46812634fadc194830774110780f14e9462Tyler Gunnimport android.telecom.PhoneCapabilities;
306cddf46812634fadc194830774110780f14e9462Tyler Gunnimport android.telecom.PhoneAccount;
316cddf46812634fadc194830774110780f14e9462Tyler Gunnimport android.telecom.PhoneAccountHandle;
326cddf46812634fadc194830774110780f14e9462Tyler Gunnimport android.telecom.StatusHints;
336cddf46812634fadc194830774110780f14e9462Tyler Gunnimport android.telecom.TelecomManager;
346cddf46812634fadc194830774110780f14e9462Tyler Gunnimport android.telecom.VideoProfile;
353f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charltonimport android.telephony.PhoneNumberUtils;
364940f9ff450d1054ed4ad0e61179196007ad5531Evan Charltonimport android.telephony.TelephonyManager;
371df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordonimport android.text.TextUtils;
3888dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordonimport android.text.format.DateUtils;
397ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
404bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordonimport com.android.incallui.ContactInfoCache.ContactCacheEntry;
414bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordonimport com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
423f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charltonimport com.android.incallui.InCallPresenter.InCallDetailsListener;
4315a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunnimport com.android.incallui.InCallPresenter.InCallEventListener;
44671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordonimport com.android.incallui.InCallPresenter.InCallState;
45671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordonimport com.android.incallui.InCallPresenter.InCallStateListener;
461ee82fcea79556c90eec0f55ea2e2ab5c6dfaddaSantos Cordonimport com.android.incallui.InCallPresenter.IncomingCallListener;
47f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charltonimport com.android.incalluibind.ObjectFactory;
48e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee
49e89ee6f3c48374bfdea5450d6311763bc061885fYorke Leeimport java.lang.ref.WeakReference;
50e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee
518b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Chengimport com.google.common.base.Preconditions;
52a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
53a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon/**
54a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon * Presenter for the Call Card Fragment.
551fa0782281ef7774ddcdfdf8efb7d8f65cf589e7Chiao Cheng * <p>
56671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon * This class listens for changes to InCallState and passes it along to the fragment.
57a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon */
584bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordonpublic class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
594b0d86229cf80a4d85652ca097b0f3bcf902b4acAndrew Lee        implements InCallStateListener, IncomingCallListener, InCallDetailsListener,
60fe4982c221c8ee734afedc4d005661d9c6c1ac31Andrew Lee        InCallEventListener {
617ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
621fa0782281ef7774ddcdfdf8efb7d8f65cf589e7Chiao Cheng    private static final String TAG = CallCardPresenter.class.getSimpleName();
63aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee    private static final long CALL_TIME_UPDATE_INTERVAL_MS = 1000;
6488dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon
65b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon    private Call mPrimary;
664bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon    private Call mSecondary;
674bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon    private ContactCacheEntry mPrimaryContactInfo;
684bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon    private ContactCacheEntry mSecondaryContactInfo;
6978b97bbc961a2d11c108c11b68d30d916fedd4ccAndrew Lee    private CallTimer mCallTimer;
703d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon    private Context mContext;
716cddf46812634fadc194830774110780f14e9462Tyler Gunn    private TelecomManager mTelecomManager;
72988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee
73e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee    public static class ContactLookupCallback implements ContactInfoCacheCallback {
74e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        private final WeakReference<CallCardPresenter> mCallCardPresenter;
75e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        private final boolean mIsPrimary;
76e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee
77e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        public ContactLookupCallback(CallCardPresenter callCardPresenter, boolean isPrimary) {
78e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            mCallCardPresenter = new WeakReference<CallCardPresenter>(callCardPresenter);
79e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            mIsPrimary = isPrimary;
80e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        }
81e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee
82e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        @Override
83e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        public void onContactInfoComplete(String callId, ContactCacheEntry entry) {
84e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            CallCardPresenter presenter = mCallCardPresenter.get();
85e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            if (presenter != null) {
86e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee                presenter.onContactInfoComplete(callId, entry, mIsPrimary);
87e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            }
88e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        }
89e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee
90e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        @Override
91e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        public void onImageLoadComplete(String callId, ContactCacheEntry entry) {
92e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            CallCardPresenter presenter = mCallCardPresenter.get();
93e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            if (presenter != null) {
94e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee                presenter.onImageLoadComplete(callId, entry);
95e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            }
96e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        }
97e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee
98e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee    }
99e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee
1009de3d7c5188c02cabf03799f87d494ee7dc702cbSantos Cordon    public CallCardPresenter() {
10188dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        // create the call timer
10288dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        mCallTimer = new CallTimer(new Runnable() {
10388dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon            @Override
10488dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon            public void run() {
10588dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon                updateCallTime();
10688dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon            }
10788dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        });
108988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee    }
109988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee
110101bed44998ff35c3a56f431345fac5c8229ec0eJay Shrauner    public void init(Context context, Call call) {
1118b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        mContext = Preconditions.checkNotNull(context);
1128b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
113bf62e69f8f029b616726577df7aa100c0900d6e5Chiao Cheng        // Call may be null if disconnect happened already.
114bf62e69f8f029b616726577df7aa100c0900d6e5Chiao Cheng        if (call != null) {
11541457dce3ca531178ca07946868afb0cc1579a6bChiao Cheng            mPrimary = call;
11641457dce3ca531178ca07946868afb0cc1579a6bChiao Cheng
117bf62e69f8f029b616726577df7aa100c0900d6e5Chiao Cheng            // start processing lookups right away.
118625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            if (!call.isConferenceCall()) {
119fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal                startContactInfoSearch(call, true, call.getState() == Call.State.INCOMING);
120625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            } else {
121625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon                updateContactEntry(null, true, true);
122625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            }
123bf62e69f8f029b616726577df7aa100c0900d6e5Chiao Cheng        }
1241fa0782281ef7774ddcdfdf8efb7d8f65cf589e7Chiao Cheng    }
1251fa0782281ef7774ddcdfdf8efb7d8f65cf589e7Chiao Cheng
126a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    @Override
127a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    public void onUiReady(CallCardUi ui) {
128a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon        super.onUiReady(ui);
129b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon
1308b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        // Contact search may have completed before ui is ready.
1318b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (mPrimaryContactInfo != null) {
1326d93245c0c9067d7a6ff30fd6fb79431da124946Christine Chen            updatePrimaryDisplayInfo(mPrimaryContactInfo, isConference(mPrimary));
1338b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
1348b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
135b0d08a16da088e01f416f52a7b74ee9630c1493aSantos Cordon        // Register for call state changes last
136b0d08a16da088e01f416f52a7b74ee9630c1493aSantos Cordon        InCallPresenter.getInstance().addListener(this);
1371ee82fcea79556c90eec0f55ea2e2ab5c6dfaddaSantos Cordon        InCallPresenter.getInstance().addIncomingCallListener(this);
1383f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charlton        InCallPresenter.getInstance().addDetailsListener(this);
13915a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        InCallPresenter.getInstance().addInCallEventListener(this);
140b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon    }
141b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon
142b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon    @Override
143b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon    public void onUiUnready(CallCardUi ui) {
144b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon        super.onUiUnready(ui);
145b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon
146b0d08a16da088e01f416f52a7b74ee9630c1493aSantos Cordon        // stop getting call state changes
147b0d08a16da088e01f416f52a7b74ee9630c1493aSantos Cordon        InCallPresenter.getInstance().removeListener(this);
1481ee82fcea79556c90eec0f55ea2e2ab5c6dfaddaSantos Cordon        InCallPresenter.getInstance().removeIncomingCallListener(this);
1493f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charlton        InCallPresenter.getInstance().removeDetailsListener(this);
15015a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        InCallPresenter.getInstance().removeInCallEventListener(this);
151b0d08a16da088e01f416f52a7b74ee9630c1493aSantos Cordon
152b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon        mPrimary = null;
1534bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        mPrimaryContactInfo = null;
1544bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        mSecondaryContactInfo = null;
155a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    }
156a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
157a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon    @Override
158f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen    public void onIncomingCall(InCallState oldState, InCallState newState, Call call) {
1591ee82fcea79556c90eec0f55ea2e2ab5c6dfaddaSantos Cordon        // same logic should happen as with onStateChange()
160f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen        onStateChange(oldState, newState, CallList.getInstance());
1611ee82fcea79556c90eec0f55ea2e2ab5c6dfaddaSantos Cordon    }
1621ee82fcea79556c90eec0f55ea2e2ab5c6dfaddaSantos Cordon
1631ee82fcea79556c90eec0f55ea2e2ab5c6dfaddaSantos Cordon    @Override
164f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen    public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
165f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen        Log.d(this, "onStateChange() " + newState);
166150a5c58c67f230c8fd7293b180bbf50aa761480Santos Cordon        final CallCardUi ui = getUi();
167b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon        if (ui == null) {
168b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon            return;
169b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon        }
170a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon
171671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon        Call primary = null;
172671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon        Call secondary = null;
173671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon
174f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen        if (newState == InCallState.INCOMING) {
175671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon            primary = callList.getIncomingCall();
176f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen        } else if (newState == InCallState.PENDING_OUTGOING || newState == InCallState.OUTGOING) {
177e7be13fb0556e62b07bc271b130412d82d7f7521Santos Cordon            primary = callList.getOutgoingCall();
178f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen            if (primary == null) {
179f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen                primary = callList.getPendingOutgoingCall();
180f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen            }
181e7be13fb0556e62b07bc271b130412d82d7f7521Santos Cordon
182a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon            // getCallToDisplay doesn't go through outgoing or incoming calls. It will return the
183a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon            // highest priority call to display as the secondary call.
1841df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            secondary = getCallToDisplay(callList, null, true);
185f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen        } else if (newState == InCallState.INCALL) {
1861df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            primary = getCallToDisplay(callList, null, false);
1871df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            secondary = getCallToDisplay(callList, primary, true);
188671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon        }
189671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon
1901a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng        Log.d(this, "Primary call: " + primary);
1911a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng        Log.d(this, "Secondary call: " + secondary);
192671b221ccadea34fb9327ef5342b26419eb5ca99Santos Cordon
193fe4982c221c8ee734afedc4d005661d9c6c1ac31Andrew Lee        final boolean primaryChanged = !Call.areSame(mPrimary, primary);
194fe4982c221c8ee734afedc4d005661d9c6c1ac31Andrew Lee        final boolean secondaryChanged = !Call.areSame(mSecondary, secondary);
195fe4982c221c8ee734afedc4d005661d9c6c1ac31Andrew Lee
196625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        mSecondary = secondary;
197625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        mPrimary = primary;
198625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon
199625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        if (primaryChanged && mPrimary != null) {
200625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            // primary call has changed
201fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal            mPrimaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext, mPrimary,
202fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal                    mPrimary.getState() == Call.State.INCOMING);
203625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            updatePrimaryDisplayInfo(mPrimaryContactInfo, isConference(mPrimary));
204625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            maybeStartSearch(mPrimary, true);
205aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee            mPrimary.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
2068b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
2078b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
208625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        if (mSecondary == null) {
2098b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            // Secondary call may have ended.  Update the ui.
2108b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            mSecondaryContactInfo = null;
2110f09a02be361d5bb36fac6981649204f5d6987faChristine Chen            updateSecondaryDisplayInfo(false);
212625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        } else if (secondaryChanged) {
213625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            // secondary call has changed
214fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal            mSecondaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext, mSecondary,
215fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal                    mSecondary.getState() == Call.State.INCOMING);
216625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            updateSecondaryDisplayInfo(mSecondary.isConferenceCall());
217625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon            maybeStartSearch(mSecondary, false);
218aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee            mSecondary.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
2198b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
2208b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
221aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee        // Start/stop timers.
22288dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        if (mPrimary != null && mPrimary.getState() == Call.State.ACTIVE) {
2231a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng            Log.d(this, "Starting the calltime timer");
224aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee            mCallTimer.start(CALL_TIME_UPDATE_INTERVAL_MS);
22588dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        } else {
2261a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng            Log.d(this, "Canceling the calltime timer");
22788dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon            mCallTimer.cancel();
22888dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon            ui.setPrimaryCallElapsedTime(false, null);
22988dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        }
23088dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon
2314bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        // Set the call state
232776d937b539b9e9b3672a1d860adec309f65d0adEvan Charlton        int callState = Call.State.IDLE;
2334bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        if (mPrimary != null) {
23429d9a2f4f60715267c73044e327f65f812dfc2cdYorke Lee            callState = mPrimary.getState();
23516cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            updatePrimaryCallState();
236a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        } else {
237aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee            getUi().setCallState(
238aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee                    callState,
23943f3e6e0760ea774e479935733d8a30b724457cdIhab Awad                    VideoProfile.VideoState.AUDIO_ONLY,
240aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee                    Call.SessionModificationState.NO_REQUEST,
241017f23c5f9ee2585454b43ae15c14c98e48e8f17Andrew Lee                    new DisconnectCause(DisconnectCause.UNKNOWN),
242aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee                    null,
243aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee                    null,
244aed98fccfc2af12f8c24f93242fecdab23758c8dAndrew Lee                    null);
245a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        }
2464c3e9e8e45ecafcb9aaf0da9901a5e9cebc59bc4Andrew Lee
24715a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        // Hide/show the contact photo based on the video state.
24815a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        // If the primary call is a video call on hold, still show the contact photo.
24915a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        // If the primary call is an active video call, hide the contact photo.
250e59cd0f067d5630742ffe4724f18720c94053194Tyler Gunn        if (mPrimary != null) {
25135224e8ff0e3707b92626767f048f1bf83352a2dTyler Gunn            getUi().setPhotoVisible(!(mPrimary.isVideoCall(mContext) &&
25235224e8ff0e3707b92626767f048f1bf83352a2dTyler Gunn                    callState != Call.State.ONHOLD));
253e59cd0f067d5630742ffe4724f18720c94053194Tyler Gunn        }
254e59cd0f067d5630742ffe4724f18720c94053194Tyler Gunn
255cb6f599ecb7c30e00ed8b07c5c10505322aae89cAndrew Lee        maybeShowManageConferenceCallButton();
256cb6f599ecb7c30e00ed8b07c5c10505322aae89cAndrew Lee
257f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen        final boolean enableEndCallButton = Call.State.isConnectingOrConnected(callState) &&
258776d937b539b9e9b3672a1d860adec309f65d0adEvan Charlton                callState != Call.State.INCOMING && mPrimary != null;
259b8249f3727e4d233215f4cfbecdd7ed175ce5231Andrew Lee        // Hide the end call button instantly if we're receiving an incoming call.
260b8249f3727e4d233215f4cfbecdd7ed175ce5231Andrew Lee        getUi().setEndCallButtonEnabled(
261b8249f3727e4d233215f4cfbecdd7ed175ce5231Andrew Lee                enableEndCallButton, callState != Call.State.INCOMING /* animate */);
262b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon    }
263b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon
264b70af18a174fa334d15b28a2cdaa617f9ba2a4b7Santos Cordon    @Override
2656cddf46812634fadc194830774110780f14e9462Tyler Gunn    public void onDetailsChanged(Call call, android.telecom.Call.Details details) {
26616cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        updatePrimaryCallState();
2674940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton    }
2684940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton
2694940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton    private String getSubscriptionNumber() {
2704940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton        // If it's an emergency call, and they're not populating the callback number,
2714940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton        // then try to fall back to the phone sub info (to hopefully get the SIM's
2724940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton        // number directly from the telephony layer).
2732b22a35ee4c94adae074b1dd720fa8734d8461b7Evan Charlton        PhoneAccountHandle accountHandle = mPrimary.getAccountHandle();
2742b22a35ee4c94adae074b1dd720fa8734d8461b7Evan Charlton        if (accountHandle != null) {
2756cddf46812634fadc194830774110780f14e9462Tyler Gunn            TelecomManager mgr =
2766cddf46812634fadc194830774110780f14e9462Tyler Gunn                    (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
277bfb48c19b99fb1e2412f9c722f6f55a967c45233Evan Charlton            PhoneAccount account = mgr.getPhoneAccount(accountHandle);
278bfb48c19b99fb1e2412f9c722f6f55a967c45233Evan Charlton            if (account != null) {
2798612291d139f5afb35761bcbc729c096eda910bfAndrew Lee                return getNumberFromHandle(account.getSubscriptionAddress());
280856194f36d7e8048f7f83e5e6025ff45d89de980Ihab Awad            }
2813f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charlton        }
2824940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton        return null;
2833f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charlton    }
2843f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charlton
28516cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal    private void updatePrimaryCallState() {
28616cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        if (getUi() != null && mPrimary != null) {
28716cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            getUi().setCallState(
28816cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                    mPrimary.getState(),
28916cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                    mPrimary.getVideoState(),
29016cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                    mPrimary.getSessionModificationState(),
29116cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                    mPrimary.getDisconnectCause(),
29216cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                    getConnectionLabel(),
29316cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                    getConnectionIcon(),
29416cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                    getGatewayNumber());
29516cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            setCallbackNumber();
29616cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        }
29716cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal    }
2984940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton
299cb6f599ecb7c30e00ed8b07c5c10505322aae89cAndrew Lee    /**
30052c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon     * Only show the conference call button if we can manage the conference.
301cb6f599ecb7c30e00ed8b07c5c10505322aae89cAndrew Lee     */
302cb6f599ecb7c30e00ed8b07c5c10505322aae89cAndrew Lee    private void maybeShowManageConferenceCallButton() {
30383e061107b3f0b6f3b2f82151dd585234173ceb7Andrew Lee        if (mPrimary == null) {
30483e061107b3f0b6f3b2f82151dd585234173ceb7Andrew Lee            getUi().showManageConferenceCallButton(false);
30583e061107b3f0b6f3b2f82151dd585234173ceb7Andrew Lee            return;
30683e061107b3f0b6f3b2f82151dd585234173ceb7Andrew Lee        }
30783e061107b3f0b6f3b2f82151dd585234173ceb7Andrew Lee
30852c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon        final boolean canManageConference = mPrimary.can(PhoneCapabilities.MANAGE_CONFERENCE);
30952c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon        getUi().showManageConferenceCallButton(mPrimary.isConferenceCall() && canManageConference);
310cb6f599ecb7c30e00ed8b07c5c10505322aae89cAndrew Lee    }
311cb6f599ecb7c30e00ed8b07c5c10505322aae89cAndrew Lee
31216cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal    private void setCallbackNumber() {
31316cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        String callbackNumber = null;
3144940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton
31516cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        boolean isEmergencyCall = PhoneNumberUtils.isEmergencyNumber(
31616cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                getNumberFromHandle(mPrimary.getHandle()));
31716cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        if (isEmergencyCall) {
31816cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            callbackNumber = getSubscriptionNumber();
31916cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        } else {
32016cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            StatusHints statusHints = mPrimary.getTelecommCall().getDetails().getStatusHints();
32116cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            if (statusHints != null) {
32216cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                Bundle extras = statusHints.getExtras();
32316cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                if (extras != null) {
3246cddf46812634fadc194830774110780f14e9462Tyler Gunn                    callbackNumber = extras.getString(TelecomManager.EXTRA_CALL_BACK_NUMBER);
3254940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton                }
3263f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charlton            }
3274940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton        }
3284940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton
32916cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        TelephonyManager telephonyManager =
3308e98c93f1806e1a23da1b1b3e67b996b233b0ed3Yorke Lee                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
3318e98c93f1806e1a23da1b1b3e67b996b233b0ed3Yorke Lee        String simNumber = telephonyManager.getLine1Number();
33216cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        if (PhoneNumberUtils.compare(callbackNumber, simNumber)) {
3334940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton            Log.d(this, "Numbers are the same; not showing the callback number");
33416cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            callbackNumber = null;
3354940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton        }
33616cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal
3374940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton        getUi().setCallbackNumber(callbackNumber, isEmergencyCall);
3383f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charlton    }
3393f4f33bc27ee1c9a12c9e55856b29079301c8a08Evan Charlton
34088dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon    public void updateCallTime() {
34188dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        final CallCardUi ui = getUi();
34288dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon
34388dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        if (ui == null || mPrimary == null || mPrimary.getState() != Call.State.ACTIVE) {
3440b77eb307c0a99bfb6aca0e38990c2d03a879bfcSantos Cordon            if (ui != null) {
3450b77eb307c0a99bfb6aca0e38990c2d03a879bfcSantos Cordon                ui.setPrimaryCallElapsedTime(false, null);
3460b77eb307c0a99bfb6aca0e38990c2d03a879bfcSantos Cordon            }
34788dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon            mCallTimer.cancel();
3480b77eb307c0a99bfb6aca0e38990c2d03a879bfcSantos Cordon        } else {
349a481914300fbe10a76635242eb778e1976947065Sailesh Nepal            final long callStart = mPrimary.getConnectTimeMillis();
3500b77eb307c0a99bfb6aca0e38990c2d03a879bfcSantos Cordon            final long duration = System.currentTimeMillis() - callStart;
3510b77eb307c0a99bfb6aca0e38990c2d03a879bfcSantos Cordon            ui.setPrimaryCallElapsedTime(true, DateUtils.formatElapsedTime(duration / 1000));
35288dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        }
35388dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon    }
35488dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon
355f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charlton    public void onCallStateButtonTouched() {
3566bfbae405c734c3000320d5b2d65654b2caa8d4eEvan Charlton        Intent broadcastIntent = ObjectFactory.getCallStateButtonBroadcastIntent(mContext);
357f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charlton        if (broadcastIntent != null) {
358f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charlton            Log.d(this, "Sending call state button broadcast: ", broadcastIntent);
359f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charlton            mContext.sendBroadcast(broadcastIntent, Manifest.permission.READ_PHONE_STATE);
360f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charlton        }
361f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charlton    }
362f2b1401b9680fa4344cec18a01b11fc9e100ae17Evan Charlton
363625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon    private void maybeStartSearch(Call call, boolean isPrimary) {
364625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        // no need to start search for conference calls which show generic info.
365625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        if (call != null && !call.isConferenceCall()) {
366fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal            startContactInfoSearch(call, isPrimary, call.getState() == Call.State.INCOMING);
367625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        }
368625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon    }
369625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon
370a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    /**
3714bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon     * Starts a query for more contact data for the save primary and secondary calls.
3724bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon     */
373fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal    private void startContactInfoSearch(final Call call, final boolean isPrimary,
374fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal            boolean isIncoming) {
3758b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        final ContactInfoCache cache = ContactInfoCache.getInstance(mContext);
3768b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
377e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        cache.findInfo(call, isIncoming, new ContactLookupCallback(this, isPrimary));
378e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee    }
379af2589a6aa68d9906fe46b31ffaf214010632c02Chiao Cheng
380e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee    private void onContactInfoComplete(String callId, ContactCacheEntry entry, boolean isPrimary) {
381e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        updateContactEntry(entry, isPrimary, false);
382e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        if (entry.name != null) {
383e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            Log.d(TAG, "Contact found: " + entry);
384e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        }
385e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        if (entry.contactUri != null) {
386e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            CallerInfoUtils.sendViewNotification(mContext, entry.contactUri);
387e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        }
388e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee    }
389e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee
390e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee    private void onImageLoadComplete(String callId, ContactCacheEntry entry) {
391e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        if (getUi() == null) {
392e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            return;
393e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        }
394f3d0654f2b6d77b7eef8bdcb4c39ee59e55017deNancy Chen
395e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        if (entry.photo != null) {
396e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            if (mPrimary != null && callId.equals(mPrimary.getId())) {
397e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee                getUi().setPrimaryImage(entry.photo);
398e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee            }
399e89ee6f3c48374bfdea5450d6311763bc061885fYorke Lee        }
4008b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
4018b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
402625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon    private static boolean isConference(Call call) {
403625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon        return call != null && call.isConferenceCall();
404625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon    }
405625ac576cb403744ef0baeba8e8993da963461eeSantos Cordon
40652c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon    private static boolean canManageConference(Call call) {
40752c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon        return call != null && call.can(PhoneCapabilities.MANAGE_CONFERENCE);
4088b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
4094bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon
4108b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    private void updateContactEntry(ContactCacheEntry entry, boolean isPrimary,
4118b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            boolean isConference) {
4128b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (isPrimary) {
4138b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            mPrimaryContactInfo = entry;
4148b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            updatePrimaryDisplayInfo(entry, isConference);
4154bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        } else {
4168b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            mSecondaryContactInfo = entry;
4170f09a02be361d5bb36fac6981649204f5d6987faChristine Chen            updateSecondaryDisplayInfo(isConference);
4184bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        }
4194bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon    }
4204bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon
4214bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon    /**
422a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     * Get the highest priority call to display.
423a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     * Goes through the calls and chooses which to return based on priority of which type of call
424a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     * to display to the user. Callers can use the "ignore" feature to get the second best call
425a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     * by passing a previously found primary call as ignore.
426a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     *
427a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     * @param ignore A call to ignore if found.
428a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon     */
4291df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon    private Call getCallToDisplay(CallList callList, Call ignore, boolean skipDisconnected) {
430a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
4311df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        // Active calls come second.  An active call always gets precedent.
4321df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        Call retval = callList.getActiveCall();
433a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        if (retval != null && retval != ignore) {
434a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon            return retval;
435a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        }
436a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
4371df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        // Disconnected calls get primary position if there are no active calls
4381df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        // to let user know quickly what call has disconnected. Disconnected
4391df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        // calls are very short lived.
4401df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        if (!skipDisconnected) {
441ecabb6923e6587e0f0ca98cc895be7d99e694015Christine Chen            retval = callList.getDisconnectingCall();
442ecabb6923e6587e0f0ca98cc895be7d99e694015Christine Chen            if (retval != null && retval != ignore) {
443ecabb6923e6587e0f0ca98cc895be7d99e694015Christine Chen                return retval;
444ecabb6923e6587e0f0ca98cc895be7d99e694015Christine Chen            }
4451df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            retval = callList.getDisconnectedCall();
4461df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            if (retval != null && retval != ignore) {
4471df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon                return retval;
4481df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            }
449a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        }
450a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
451a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        // Then we go to background call (calls on hold)
452a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        retval = callList.getBackgroundCall();
453a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        if (retval != null && retval != ignore) {
454a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon            return retval;
455a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        }
456a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
457a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        // Lastly, we go to a second background call.
458a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        retval = callList.getSecondBackgroundCall();
459a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
460a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon        return retval;
461a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon    }
462a12f2589f424e26c63c8ee5b6fad89e30b69d7fbSantos Cordon
4638b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    private void updatePrimaryDisplayInfo(ContactCacheEntry entry, boolean isConference) {
4648b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        Log.d(TAG, "Update primary display " + entry);
465988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee        final CallCardUi ui = getUi();
4664bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        if (ui == null) {
4678b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            // TODO: May also occur if search result comes back after ui is destroyed. Look into
4688b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            // removing that case completely.
4698b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            Log.d(TAG, "updatePrimaryDisplayInfo called but ui is null!");
4704bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            return;
471988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee        }
4727ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
47352c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon        final boolean canManageConference = canManageConference(mPrimary);
474b6b3df38e14990595bce4bcaec548ee371d21151Yorke Lee        if (entry != null && mPrimary != null) {
4758b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            final String name = getNameForCall(entry);
4768b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            final String number = getNumberForCall(entry);
4778b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            final boolean nameIsNumber = name != null && name.equals(entry.number);
4788b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            ui.setPrimary(number, name, nameIsNumber, entry.label,
47952c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon                    entry.photo, isConference, canManageConference, entry.isSipCall);
480988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee        } else {
48152c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon            ui.setPrimary(null, null, false, null, null, isConference, canManageConference, false);
4821df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        }
4831df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon
4841df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon    }
4851df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon
4860f09a02be361d5bb36fac6981649204f5d6987faChristine Chen    private void updateSecondaryDisplayInfo(boolean isConference) {
4878b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        final CallCardUi ui = getUi();
4888b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (ui == null) {
4898b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            return;
4908b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
4918b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
49252c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon        final boolean canManageConference = canManageConference(mSecondary);
493b6b3df38e14990595bce4bcaec548ee371d21151Yorke Lee        if (mSecondaryContactInfo != null && mSecondary != null) {
4948b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            Log.d(TAG, "updateSecondaryDisplayInfo() " + mSecondaryContactInfo);
4954be1bdd9ee8e9d3afa1aaa765e86b963fb6c7b3dYorke Lee            final String nameForCall = getNameForCall(mSecondaryContactInfo);
4964be1bdd9ee8e9d3afa1aaa765e86b963fb6c7b3dYorke Lee
4974be1bdd9ee8e9d3afa1aaa765e86b963fb6c7b3dYorke Lee            final boolean nameIsNumber = nameForCall != null && nameForCall.equals(
4984be1bdd9ee8e9d3afa1aaa765e86b963fb6c7b3dYorke Lee                    mSecondaryContactInfo.number);
4998e303d6ad3f2a0e99b1d0674b9cf91565511f066Andrew Lee            ui.setSecondary(true /* show */, nameForCall, nameIsNumber, mSecondaryContactInfo.label,
500a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen                    getCallProviderLabel(mSecondary), getCallProviderIcon(mSecondary),
50152c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon                    isConference, canManageConference);
5028b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        } else {
5038b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            // reset to nothing so that it starts off blank next time we use it.
50452c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon            ui.setSecondary(false, null, false, null, null, null, isConference, canManageConference);
5058b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
5068b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng    }
5078b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng
508a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen
509a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen    /**
510a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen     * Gets the phone account to display for a call.
511a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen     */
512a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen    private PhoneAccount getAccountForCall(Call call) {
513a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen        PhoneAccountHandle accountHandle = call.getAccountHandle();
514a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen        if (accountHandle == null) {
515a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen            return null;
516a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen        }
5176cddf46812634fadc194830774110780f14e9462Tyler Gunn        return getTelecomManager().getPhoneAccount(accountHandle);
518a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen    }
519a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen
5203d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon    /**
5213d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon     * Returns the gateway number for any existing outgoing call.
5223d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon     */
5233d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon    private String getGatewayNumber() {
5243d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon        if (hasOutgoingGatewayCall()) {
525e2814d578ed59624f3720302e8a99773d7c6a9c5Nancy Chen            return getNumberFromHandle(mPrimary.getGatewayInfo().getGatewayAddress());
5263d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon        }
5273d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon        return null;
5283d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon    }
5293d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon
5303d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon    /**
5316d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen     * Return the Drawable object of the icon to display to the left of the connection label.
5326d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen     */
533a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen    private Drawable getCallProviderIcon(Call call) {
534a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen        PhoneAccount account = getAccountForCall(call);
535a3584bc7adc64bc271e82bb2533d30b75db27d2fNancy Chen        if (account != null && getTelecomManager().hasMultipleCallCapableAccounts()) {
536a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen            return account.getIcon(mContext);
537a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen        }
538a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen        return null;
539a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen    }
540a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen
541a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen    /**
542a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen     * Return the string label to represent the call provider
543a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen     */
544a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen    private String getCallProviderLabel(Call call) {
545a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen        PhoneAccount account = getAccountForCall(call);
546a3584bc7adc64bc271e82bb2533d30b75db27d2fNancy Chen        if (account != null && getTelecomManager().hasMultipleCallCapableAccounts()) {
547a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen            return account.getLabel().toString();
5486d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen        }
5496d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen        return null;
5506d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen    }
5516d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen
5526d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen    /**
5536d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen     * Returns the label (line of text above the number/name) for any given call.
5546d0f6679a1afb1afa3053bd9511aea8f5945a5d7Sailesh Nepal     * For example, "calling via [Account/Google Voice]" for outgoing calls.
5553d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon     */
5566d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen    private String getConnectionLabel() {
55716cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        StatusHints statusHints = mPrimary.getTelecommCall().getDetails().getStatusHints();
55816cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        if (statusHints != null && !TextUtils.isEmpty(statusHints.getLabel())) {
55916cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            return statusHints.getLabel().toString();
56016cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        }
56116cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal
5623d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon        if (hasOutgoingGatewayCall() && getUi() != null) {
5636d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen            // Return the label for the gateway app on outgoing calls.
5643d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon            final PackageManager pm = mContext.getPackageManager();
5653d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon            try {
56607a822b2ea92dc5b68cd43139be7efe4c6640cd4Sailesh Nepal                ApplicationInfo info = pm.getApplicationInfo(
56707a822b2ea92dc5b68cd43139be7efe4c6640cd4Sailesh Nepal                        mPrimary.getGatewayInfo().getGatewayProviderPackageName(), 0);
5686d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen                return pm.getApplicationLabel(info).toString();
5693d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon            } catch (PackageManager.NameNotFoundException e) {
5706d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen                Log.e(this, "Gateway Application Not Found.", e);
5716d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen                return null;
5723d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon            }
5733d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon        }
574a05e4e2595f4d41eab092f13cdf068b8709ab323Nancy Chen        return getCallProviderLabel(mPrimary);
5753d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon    }
5763d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon
57716cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal    private Drawable getConnectionIcon() {
57816cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        StatusHints statusHints = mPrimary.getTelecommCall().getDetails().getStatusHints();
57943f3e6e0760ea774e479935733d8a30b724457cdIhab Awad        if (statusHints != null && statusHints.getIconResId() != 0) {
58016cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            Drawable icon = statusHints.getIcon(mContext);
58116cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            if (icon != null) {
58216cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal                return icon;
58316cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal            }
58416cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        }
58516cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal        return getCallProviderIcon(mPrimary);
58616cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal    }
58716cadfad5458d6a1095fd23bcd6bf5120de43c98Sailesh Nepal
5883d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon    private boolean hasOutgoingGatewayCall() {
58943f3e6e0760ea774e479935733d8a30b724457cdIhab Awad        // We only display the gateway information while STATE_DIALING so return false for any othe
5903d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon        // call state.
5918b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        // TODO: mPrimary can be null because this is called from updatePrimaryDisplayInfo which
5928b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        // is also called after a contact search completes (call is not present yet).  Split the
5938b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        // UI update so it can receive independent updates.
5948b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        if (mPrimary == null) {
5958b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng            return false;
5968b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        }
59707a822b2ea92dc5b68cd43139be7efe4c6640cd4Sailesh Nepal        return Call.State.isDialing(mPrimary.getState()) && mPrimary.getGatewayInfo() != null &&
59807a822b2ea92dc5b68cd43139be7efe4c6640cd4Sailesh Nepal                !mPrimary.getGatewayInfo().isEmpty();
5993d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon    }
6003d9e39bef65a67b9b04a2584b12f8b655fcc2e7cSantos Cordon
6011df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon    /**
6021df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon     * Gets the name to display for the call.
6031df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon     */
6041df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon    private static String getNameForCall(ContactCacheEntry contactInfo) {
6051df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        if (TextUtils.isEmpty(contactInfo.name)) {
6061df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon            return contactInfo.number;
607988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee        }
6081df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        return contactInfo.name;
6091df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon    }
610988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee
6111df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon    /**
6121df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon     * Gets the number to display for a call.
6131df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon     */
6141df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon    private static String getNumberForCall(ContactCacheEntry contactInfo) {
6151df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        // If the name is empty, we use the number for the name...so dont show a second
6161df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        // number in the number field
6171df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        if (TextUtils.isEmpty(contactInfo.name)) {
618101bed44998ff35c3a56f431345fac5c8229ec0eJay Shrauner            return contactInfo.location;
6191df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        }
6201df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        return contactInfo.number;
6214bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon    }
622988d06b64b99a13f4f060dc82594edcb738d9113Yorke Lee
6238e303d6ad3f2a0e99b1d0674b9cf91565511f066Andrew Lee    public void secondaryInfoClicked() {
6246f767fb5d92b7e07315b86ddf1de1f25e7354bc0Yorke Lee        if (mSecondary == null) {
6258e303d6ad3f2a0e99b1d0674b9cf91565511f066Andrew Lee            Log.wtf(this, "Secondary info clicked but no secondary call.");
6266f767fb5d92b7e07315b86ddf1de1f25e7354bc0Yorke Lee            return;
6276f767fb5d92b7e07315b86ddf1de1f25e7354bc0Yorke Lee        }
6286f767fb5d92b7e07315b86ddf1de1f25e7354bc0Yorke Lee
629fc22ba88566ef70e202128335231c367de6c52afSailesh Nepal        Log.i(this, "Swapping call to foreground: " + mSecondary);
6306cddf46812634fadc194830774110780f14e9462Tyler Gunn        TelecomAdapter.getInstance().unholdCall(mSecondary.getId());
6319240895e9df2fcae8f0baea707eb4d24c6e50997Yorke Lee    }
6329240895e9df2fcae8f0baea707eb4d24c6e50997Yorke Lee
6337b4cfe59218ff0876587933f5f22845881fdbe40Andrew Lee    public void endCallClicked() {
6347b4cfe59218ff0876587933f5f22845881fdbe40Andrew Lee        if (mPrimary == null) {
6357b4cfe59218ff0876587933f5f22845881fdbe40Andrew Lee            return;
6367b4cfe59218ff0876587933f5f22845881fdbe40Andrew Lee        }
6377b4cfe59218ff0876587933f5f22845881fdbe40Andrew Lee
6388a81f277540cd6e7c8da5efd7ecbd342912ae29bEvan Charlton        Log.i(this, "Disconnecting call: " + mPrimary);
639766c1e05845fa4d22b22acb32ad76d4b9e0eecabIhab Awad        mPrimary.setState(Call.State.DISCONNECTING);
640766c1e05845fa4d22b22acb32ad76d4b9e0eecabIhab Awad        CallList.getInstance().onUpdate(mPrimary);
6416cddf46812634fadc194830774110780f14e9462Tyler Gunn        TelecomAdapter.getInstance().disconnectCall(mPrimary.getId());
6427b4cfe59218ff0876587933f5f22845881fdbe40Andrew Lee    }
6437b4cfe59218ff0876587933f5f22845881fdbe40Andrew Lee
644e038ead8b0e520787b41e5dbd6f4c534881e10d5Santos Cordon    private String getNumberFromHandle(Uri handle) {
645e038ead8b0e520787b41e5dbd6f4c534881e10d5Santos Cordon        return handle == null ? "" : handle.getSchemeSpecificPart();
646e038ead8b0e520787b41e5dbd6f4c534881e10d5Santos Cordon    }
647e038ead8b0e520787b41e5dbd6f4c534881e10d5Santos Cordon
64815a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn    /**
64915a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn     * Handles a change to the full screen video state.
65015a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn     *
65115a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn     * @param isFullScreenVideo {@code True} if the application is entering full screen video mode.
65215a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn     */
65315a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn    @Override
65415a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn    public void onFullScreenVideoStateChanged(boolean isFullScreenVideo) {
65515a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        final CallCardUi ui = getUi();
65615a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        if (ui == null) {
65715a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn            return;
65815a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        }
65915a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        ui.setCallCardVisible(!isFullScreenVideo);
66015a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn    }
66115a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn
6624bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon    public interface CallCardUi extends Ui {
6634bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        void setVisible(boolean on);
66415a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        void setCallCardVisible(boolean visible);
6651df52df7a0248814fbd4575103059a8b427f5d9aSantos Cordon        void setPrimary(String number, String name, boolean nameIsNumber, String label,
66652c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon                Drawable photo, boolean isConference, boolean canManageConference,
66752c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon                boolean isSipCall);
6684be1bdd9ee8e9d3afa1aaa765e86b963fb6c7b3dYorke Lee        void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
6696d0ace011dfb4ccfbf87f5e48361767fa6825b75Nancy Chen                String providerLabel, Drawable providerIcon, boolean isConference,
67052c30ebe11e132c5b00a15aabdf4a411355bf0f4Santos Cordon                boolean canManageConference);
671017f23c5f9ee2585454b43ae15c14c98e48e8f17Andrew Lee        void setCallState(int state, int videoState, int sessionModificationState,
672017f23c5f9ee2585454b43ae15c14c98e48e8f17Andrew Lee                DisconnectCause disconnectCause, String connectionLabel,
673017f23c5f9ee2585454b43ae15c14c98e48e8f17Andrew Lee                Drawable connectionIcon, String gatewayNumber);
67488dbc6b3dbf35b322fe09c1a289c7e884e8fba22Santos Cordon        void setPrimaryCallElapsedTime(boolean show, String duration);
6758b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        void setPrimaryName(String name, boolean nameIsNumber);
67614dbc3f0ca3a7998c9c5d28aba637487724f529fSantos Cordon        void setPrimaryImage(Drawable image);
6778b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        void setPrimaryPhoneNumber(String phoneNumber);
6788b6c8d0dbfba6eabe3d835f8cdcec8a13e253d0cChiao Cheng        void setPrimaryLabel(String label);
679b8249f3727e4d233215f4cfbecdd7ed175ce5231Andrew Lee        void setEndCallButtonEnabled(boolean enabled, boolean animate);
6804940f9ff450d1054ed4ad0e61179196007ad5531Evan Charlton        void setCallbackNumber(String number, boolean isEmergencyCalls);
681e59cd0f067d5630742ffe4724f18720c94053194Tyler Gunn        void setPhotoVisible(boolean isVisible);
68215a8e3cb2c01b59b5328a74e6c46144843103205Tyler Gunn        void setProgressSpinnerVisible(boolean visible);
683cb6f599ecb7c30e00ed8b07c5c10505322aae89cAndrew Lee        void showManageConferenceCallButton(boolean visible);
6847ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    }
68527003ad538e84cc3a5bd6f04d9c679afffc455e2Ihab Awad
6866cddf46812634fadc194830774110780f14e9462Tyler Gunn    private TelecomManager getTelecomManager() {
6876cddf46812634fadc194830774110780f14e9462Tyler Gunn        if (mTelecomManager == null) {
6886cddf46812634fadc194830774110780f14e9462Tyler Gunn            mTelecomManager =
6896cddf46812634fadc194830774110780f14e9462Tyler Gunn                    (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
69027003ad538e84cc3a5bd6f04d9c679afffc455e2Ihab Awad        }
6916cddf46812634fadc194830774110780f14e9462Tyler Gunn        return mTelecomManager;
69227003ad538e84cc3a5bd6f04d9c679afffc455e2Ihab Awad    }
693a012c22dfbfedffe2e751f9b1ab776baa325a26fSantos Cordon}
694