CallCardPresenter.java revision c108b49ad5440fbf381c9a589d8a217da3efcb64
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
193d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordonimport android.content.Context;
203d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordonimport android.content.pm.ApplicationInfo;
213d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordonimport android.content.pm.PackageManager;
226d231f52e4f00399330d772f2a337283803f3a9dYorke Leeimport android.graphics.drawable.Drawable;
230e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport android.os.Bundle;
24f27342bc5d594dfc32dc2bfafe109dcaa6b6d506Sailesh Nepalimport android.telecomm.CallCapabilities;
25df22018185375d2de96673ee8f16d1520283d662Ihab Awadimport android.telecomm.PhoneAccount;
26a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepalimport android.telecomm.PhoneAccountMetadata;
270e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport android.telecomm.StatusHints;
280e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport android.telecomm.TelecommConstants;
294feb57b986dc6b1edc5dc026a926b4934778716dIhab Awadimport android.telecomm.TelecommManager;
30479c50f6d4fac0fa44210c9bad4346f64dba3f1eAnders Kristensenimport android.telephony.DisconnectCause;
310e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport android.telephony.PhoneNumberUtils;
32d28fc12696fa706fed70e04698275af7be7fee82Santos Cordonimport android.text.TextUtils;
338cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordonimport android.text.format.DateUtils;
34be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
351b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordonimport com.android.incallui.AudioModeProvider.AudioModeListener;
36d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonimport com.android.incallui.ContactInfoCache.ContactCacheEntry;
37d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonimport com.android.incallui.ContactInfoCache.ContactInfoCacheCallback;
380e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charltonimport com.android.incallui.InCallPresenter.InCallDetailsListener;
397ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordonimport com.android.incallui.InCallPresenter.InCallState;
407ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordonimport com.android.incallui.InCallPresenter.InCallStateListener;
411c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordonimport com.android.incallui.InCallPresenter.IncomingCallListener;
42bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen
4342373eb59cbef15ec61ebb5c919031f293291a53Chiao Chengimport com.google.common.base.Preconditions;
44c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
45c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon/**
46c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon * Presenter for the Call Card Fragment.
47033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng * <p>
487ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon * This class listens for changes to InCallState and passes it along to the fragment.
49c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon */
50d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordonpublic class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
510e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        implements InCallStateListener, AudioModeListener, IncomingCallListener,
520e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        InCallDetailsListener {
53be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
54033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng    private static final String TAG = CallCardPresenter.class.getSimpleName();
558cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon    private static final long CALL_TIME_UPDATE_INTERVAL = 1000; // in milliseconds
568cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
571b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    private Call mPrimary;
58d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private Call mSecondary;
59d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private ContactCacheEntry mPrimaryContactInfo;
60d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    private ContactCacheEntry mSecondaryContactInfo;
618cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon    private CallTimer mCallTimer;
623d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private Context mContext;
634feb57b986dc6b1edc5dc026a926b4934778716dIhab Awad    private TelecommManager mTelecommManager;
646d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
65b8eedb3b9796873eaa22847205239a51092f1a43Santos Cordon    public CallCardPresenter() {
668cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        // create the call timer
678cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        mCallTimer = new CallTimer(new Runnable() {
688cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            @Override
698cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            public void run() {
708cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon                updateCallTime();
718cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            }
728cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        });
736d231f52e4f00399330d772f2a337283803f3a9dYorke Lee    }
746d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
7542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
761c6bb983216392b5ceb36cea42a46631f68a3dd6Jay Shrauner    public void init(Context context, Call call) {
7742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        mContext = Preconditions.checkNotNull(context);
7842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
794a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng        // Call may be null if disconnect happened already.
804a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng        if (call != null) {
81656dd4a0d8571b47ecf0ecf3e4c2eeacfd1099b3Chiao Cheng            mPrimary = call;
82656dd4a0d8571b47ecf0ecf3e4c2eeacfd1099b3Chiao Cheng
834a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng            // start processing lookups right away.
84812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            if (!call.isConferenceCall()) {
85248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                startContactInfoSearch(call, true, call.getState() == Call.State.INCOMING);
86812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            } else {
87812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon                updateContactEntry(null, true, true);
88812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            }
894a5339c4a266891ce560dfb6e348c3779a0a3ca1Chiao Cheng        }
90033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng    }
91033ed5926d2924d35b9c82898ab4e835da56b3afChiao Cheng
92c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    @Override
93c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    public void onUiReady(CallCardUi ui) {
94c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon        super.onUiReady(ui);
951b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
961f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        AudioModeProvider.getInstance().addListener(this);
971f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon
9842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // Contact search may have completed before ui is ready.
9942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (mPrimaryContactInfo != null) {
100314b2aaa1fa1ef799270987e964f7df4d983b9eeChristine Chen            updatePrimaryDisplayInfo(mPrimaryContactInfo, isConference(mPrimary));
10142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
10242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
1031f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        // Register for call state changes last
1041f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        InCallPresenter.getInstance().addListener(this);
1051c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        InCallPresenter.getInstance().addIncomingCallListener(this);
1060e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        InCallPresenter.getInstance().addDetailsListener(this);
1071b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    }
1081b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
1091b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    @Override
1101b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    public void onUiUnready(CallCardUi ui) {
1111b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        super.onUiUnready(ui);
1121b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
1131f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        // stop getting call state changes
1141f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        InCallPresenter.getInstance().removeListener(this);
1151c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        InCallPresenter.getInstance().removeIncomingCallListener(this);
1160e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        InCallPresenter.getInstance().removeDetailsListener(this);
1171f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon
1181f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon        AudioModeProvider.getInstance().removeListener(this);
1191f63d2d8e8db3616c16886952813b3d0473216e7Santos Cordon
1201b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        mPrimary = null;
121d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        mPrimaryContactInfo = null;
122d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        mSecondaryContactInfo = null;
123c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    }
124c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
125c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    @Override
1261c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon    public void onIncomingCall(InCallState state, Call call) {
1271c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        // same logic should happen as with onStateChange()
1281c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon        onStateChange(state, CallList.getInstance());
1291c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon    }
1301c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon
1311c22bde38cd15919e91afb0f12c558aa66f0bc91Santos Cordon    @Override
1327ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon    public void onStateChange(InCallState state, CallList callList) {
1337a863a056a96638c32171f721d99c694a1890df8Christine Chen        Log.d(this, "onStateChange() " + state);
13475c86b55d45b1725c46ed2e5d77c9c43fcfd93daSantos Cordon        final CallCardUi ui = getUi();
1351b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        if (ui == null) {
1361b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon            return;
1371b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon        }
138c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
1397ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        Call primary = null;
1407ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        Call secondary = null;
1417ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
1427ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        if (state == InCallState.INCOMING) {
1437ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon            primary = callList.getIncomingCall();
144950e3df8ac744daf2a890d279566bdba424710f9Santos Cordon        } else if (state == InCallState.OUTGOING) {
145950e3df8ac744daf2a890d279566bdba424710f9Santos Cordon            primary = callList.getOutgoingCall();
146950e3df8ac744daf2a890d279566bdba424710f9Santos Cordon
14782f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            // getCallToDisplay doesn't go through outgoing or incoming calls. It will return the
14882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            // highest priority call to display as the secondary call.
149d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            secondary = getCallToDisplay(callList, null, true);
1507ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        } else if (state == InCallState.INCALL) {
151d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            primary = getCallToDisplay(callList, null, false);
152d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            secondary = getCallToDisplay(callList, primary, true);
1537ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon        }
1547ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
155a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng        Log.d(this, "Primary call: " + primary);
156a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng        Log.d(this, "Secondary call: " + secondary);
1577ac6cb331919db2a3a8985e4cb3299b309d9012aSantos Cordon
158812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        final boolean primaryChanged = !areCallsSame(mPrimary, primary);
159812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        final boolean secondaryChanged = !areCallsSame(mSecondary, secondary);
160812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        mSecondary = secondary;
161812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        mPrimary = primary;
162812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
163812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        if (primaryChanged && mPrimary != null) {
164812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            // primary call has changed
165248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            mPrimaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext, mPrimary,
166248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                    mPrimary.getState() == Call.State.INCOMING);
167812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            updatePrimaryDisplayInfo(mPrimaryContactInfo, isConference(mPrimary));
168812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            maybeStartSearch(mPrimary, true);
16942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
17042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
171812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        if (mSecondary == null) {
17242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // Secondary call may have ended.  Update the ui.
17342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mSecondaryContactInfo = null;
1745345442d7238c1db00dc8d55a49f7f5dd713d994Christine Chen            updateSecondaryDisplayInfo(false);
175812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        } else if (secondaryChanged) {
176812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            // secondary call has changed
177248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            mSecondaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext, mSecondary,
178248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal                    mSecondary.getState() == Call.State.INCOMING);
179812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            updateSecondaryDisplayInfo(mSecondary.isConferenceCall());
180812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            maybeStartSearch(mSecondary, false);
18142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
18242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
1838cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        // Start/Stop the call time update timer
1848cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        if (mPrimary != null && mPrimary.getState() == Call.State.ACTIVE) {
185a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng            Log.d(this, "Starting the calltime timer");
1868cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            mCallTimer.start(CALL_TIME_UPDATE_INTERVAL);
1878cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        } else {
188a4bd83ad639b349fa16dbd07225017fcbf6ed550Chiao Cheng            Log.d(this, "Canceling the calltime timer");
1898cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            mCallTimer.cancel();
1908cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            ui.setPrimaryCallElapsedTime(false, null);
1918cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        }
1928cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
193d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        // Set the call state
1948aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton        int callState = Call.State.IDLE;
195d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        if (mPrimary != null) {
19632027ae1f52232258cc8133d383459f3b4ee57e4Yorke Lee            callState = mPrimary.getState();
19746848bb9b89cc5417afae19aaab38fe331a7b474Sailesh Nepal
198a548a7a758928c8c675d93454e6a5c85d8b896cbNancy Chen            getUi().setCallState(callState, mPrimary.getDisconnectCause(), getConnectionLabel(),
199a548a7a758928c8c675d93454e6a5c85d8b896cbNancy Chen                    getConnectionIcon(), getGatewayNumber());
20082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        } else {
201a548a7a758928c8c675d93454e6a5c85d8b896cbNancy Chen            getUi().setCallState(callState, DisconnectCause.NOT_VALID, null, null, null);
20282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
203e26b887e90d5e9566a5054a1ccb3ed32ae2eea2dAndrew Lee
2048aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton        final boolean enableEndCallButton = Call.State.isConnected(callState) &&
2058aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton                callState != Call.State.INCOMING && mPrimary != null;
2069fc169931b9904ee8eac27bacd858ab87753e33dEvan Charlton        getUi().setEndCallButtonEnabled(enableEndCallButton);
2071b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    }
2081b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
2091b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    @Override
2100e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    public void onDetailsChanged(android.telecomm.Call.Details details) {
2110e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        getUi().setCallDetails(details);
2120e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
213c108b49ad5440fbf381c9a589d8a217da3efcb64Ihab Awad        if (mPrimary != null) {
214c108b49ad5440fbf381c9a589d8a217da3efcb64Ihab Awad            String currentNumber = mPrimary.getHandle().getSchemeSpecificPart();
215c108b49ad5440fbf381c9a589d8a217da3efcb64Ihab Awad            if (PhoneNumberUtils.isEmergencyNumber(currentNumber)) {
216c108b49ad5440fbf381c9a589d8a217da3efcb64Ihab Awad                setEmergencyNumberIfSet(details);
217c108b49ad5440fbf381c9a589d8a217da3efcb64Ihab Awad            }
2180e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        }
2190e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    }
2200e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
2210e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    private void setEmergencyNumberIfSet(android.telecomm.Call.Details details) {
2220e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        String callbackNumber = null;
2230e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
2240e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        StatusHints statusHints = details.getStatusHints();
2250e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        if (statusHints != null) {
2260e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton            Bundle extras = statusHints.getExtras();
2270e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton            if (extras != null) {
2280e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton                callbackNumber = extras.getString(
2290e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton                        TelecommConstants.EXTRA_EMERGENCY_CALL_BACK_NUMBER, null);
2300e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton            } else {
2310e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton                Log.d(this, "No extras; not updating callback number");
2320e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton            }
2330e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        } else {
2340e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton            Log.d(this, "No status hints; not updating callback number");
2350e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        }
2360e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
2370e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        getUi().setEmergencyCallbackNumber(callbackNumber);
2380e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    }
2390e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton
2400e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton    @Override
2411b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    public void onAudioMode(int mode) {
2421b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    }
2431b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon
2441b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    @Override
2451b3e3f1056317fca5be4e7535d722da8876b2cbfSantos Cordon    public void onSupportedAudioMode(int mask) {
246c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon    }
247c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon
2488c478132fbc07bd075df6aba85bcfd2990bbd66aSantos Cordon    @Override
2498c478132fbc07bd075df6aba85bcfd2990bbd66aSantos Cordon    public void onMute(boolean muted) {
2508c478132fbc07bd075df6aba85bcfd2990bbd66aSantos Cordon    }
2518c478132fbc07bd075df6aba85bcfd2990bbd66aSantos Cordon
2528cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon    public void updateCallTime() {
2538cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        final CallCardUi ui = getUi();
2548cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
2558cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        if (ui == null || mPrimary == null || mPrimary.getState() != Call.State.ACTIVE) {
256899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon            if (ui != null) {
257899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon                ui.setPrimaryCallElapsedTime(false, null);
258899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon            }
2598cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon            mCallTimer.cancel();
260899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon        } else {
261c6f4e50a4130fb8f7247f5eab6849829701ad484Sailesh Nepal            final long callStart = mPrimary.getConnectTimeMillis();
262899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon            final long duration = System.currentTimeMillis() - callStart;
263899251968ee4ee3cb375032185653ecd888e3f8dSantos Cordon            ui.setPrimaryCallElapsedTime(true, DateUtils.formatElapsedTime(duration / 1000));
2648cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        }
2658cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon    }
2668cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon
267f8b0677bed382046cb26e38a8442a9509d1e835cSailesh Nepal    public void phoneAccountClicked() {
2688aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton        if (mPrimary == null) {
2698aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton            return;
2708aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton        }
2718d38cf6761ae048b1a42504f1b59e872cf43df47Ihab Awad        TelecommAdapter.getInstance().phoneAccountClicked(mPrimary.getId());
2728aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton    }
2738aac1a358f2caf6c21c603bae9c9d4bd075eb155Evan Charlton
274812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    private boolean areCallsSame(Call call1, Call call2) {
275812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        if (call1 == null && call2 == null) {
276812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            return true;
277812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        } else if (call1 == null || call2 == null) {
278812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            return false;
279812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        }
280812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
281812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        // otherwise compare call Ids
2828d38cf6761ae048b1a42504f1b59e872cf43df47Ihab Awad        return call1.getId().equals(call2.getId());
283812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    }
284812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
285812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    private void maybeStartSearch(Call call, boolean isPrimary) {
286812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        // no need to start search for conference calls which show generic info.
287812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        if (call != null && !call.isConferenceCall()) {
288248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            startContactInfoSearch(call, isPrimary, call.getState() == Call.State.INCOMING);
289812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        }
290812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    }
291812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
29282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon    /**
293d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon     * Starts a query for more contact data for the save primary and secondary calls.
294d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon     */
295248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal    private void startContactInfoSearch(final Call call, final boolean isPrimary,
296248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal            boolean isIncoming) {
29742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        final ContactInfoCache cache = ContactInfoCache.getInstance(mContext);
29842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
299248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal        cache.findInfo(call, isIncoming, new ContactInfoCacheCallback() {
30042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng                @Override
3017b2248bfff11c50e208908cb74b5f94b3ad7a3c0Sailesh Nepal                public void onContactInfoComplete(String callId, ContactCacheEntry entry) {
302812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon                    updateContactEntry(entry, isPrimary, false);
3031c6bb983216392b5ceb36cea42a46631f68a3dd6Jay Shrauner                    if (entry.name != null) {
3041c6bb983216392b5ceb36cea42a46631f68a3dd6Jay Shrauner                        Log.d(TAG, "Contact found: " + entry);
30542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng                    }
30676855c20de037a38b02716642cd27be674772f2dMakoto Onuki                    if (entry.contactUri != null) {
30776855c20de037a38b02716642cd27be674772f2dMakoto Onuki                        CallerInfoUtils.sendViewNotification(mContext, entry.contactUri);
3087e7fd2a0642515834a96028937f60ec955edfd91Yorke Lee                    }
30942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng                }
3107d2fb8620b808c28c49bde99dc54f6de46fdcb44Chiao Cheng
3117d2fb8620b808c28c49bde99dc54f6de46fdcb44Chiao Cheng                @Override
3127b2248bfff11c50e208908cb74b5f94b3ad7a3c0Sailesh Nepal                public void onImageLoadComplete(String callId, ContactCacheEntry entry) {
31302ade580384ccd853b6a9909aa0b4423fada84dfChristine Chen                    if (getUi() == null) {
31402ade580384ccd853b6a9909aa0b4423fada84dfChristine Chen                        return;
31502ade580384ccd853b6a9909aa0b4423fada84dfChristine Chen                    }
31649ff6571403695e81dbbd83e4f61790ce9c75f6dSantos Cordon                    if (entry.photo != null) {
3178d38cf6761ae048b1a42504f1b59e872cf43df47Ihab Awad                        if (mPrimary != null && callId.equals(mPrimary.getId())) {
31849ff6571403695e81dbbd83e4f61790ce9c75f6dSantos Cordon                            getUi().setPrimaryImage(entry.photo);
31949ff6571403695e81dbbd83e4f61790ce9c75f6dSantos Cordon                        }
3207d2fb8620b808c28c49bde99dc54f6de46fdcb44Chiao Cheng                    }
3217d2fb8620b808c28c49bde99dc54f6de46fdcb44Chiao Cheng                }
32242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            });
32342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    }
32442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
325812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    private static boolean isConference(Call call) {
326812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        return call != null && call.isConferenceCall();
327812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    }
328812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon
329812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon    private static boolean isGenericConference(Call call) {
330f27342bc5d594dfc32dc2bfafe109dcaa6b6d506Sailesh Nepal        return call != null && call.can(CallCapabilities.GENERIC_CONFERENCE);
33142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    }
332d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon
33342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    private void updateContactEntry(ContactCacheEntry entry, boolean isPrimary,
33442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            boolean isConference) {
33542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (isPrimary) {
33642373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mPrimaryContactInfo = entry;
33742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            updatePrimaryDisplayInfo(entry, isConference);
338d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        } else {
33942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            mSecondaryContactInfo = entry;
3405345442d7238c1db00dc8d55a49f7f5dd713d994Christine Chen            updateSecondaryDisplayInfo(isConference);
341d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        }
342d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    }
343d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon
344d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    /**
34582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * Get the highest priority call to display.
34682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * Goes through the calls and chooses which to return based on priority of which type of call
34782f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * to display to the user. Callers can use the "ignore" feature to get the second best call
34882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * by passing a previously found primary call as ignore.
34982f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     *
35082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     * @param ignore A call to ignore if found.
35182f5d003e675dfd56735c745744c3d968883b23cSantos Cordon     */
352d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private Call getCallToDisplay(CallList callList, Call ignore, boolean skipDisconnected) {
35382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
354d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // Active calls come second.  An active call always gets precedent.
355d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        Call retval = callList.getActiveCall();
35682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        if (retval != null && retval != ignore) {
35782f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            return retval;
35882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
35982f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
360d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // Disconnected calls get primary position if there are no active calls
361d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // to let user know quickly what call has disconnected. Disconnected
362d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // calls are very short lived.
363d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (!skipDisconnected) {
3646258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            retval = callList.getDisconnectingCall();
3656258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            if (retval != null && retval != ignore) {
3666258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen                return retval;
3676258ff60a7edc760facc3f387fc9c8ceee3fb518Christine Chen            }
368d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            retval = callList.getDisconnectedCall();
369d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            if (retval != null && retval != ignore) {
370d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon                return retval;
371d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            }
37282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
37382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
37482f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        // Then we go to background call (calls on hold)
37582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        retval = callList.getBackgroundCall();
37682f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        if (retval != null && retval != ignore) {
37782f5d003e675dfd56735c745744c3d968883b23cSantos Cordon            return retval;
37882f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        }
37982f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
38082f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        // Lastly, we go to a second background call.
38182f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        retval = callList.getSecondBackgroundCall();
38282f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
38382f5d003e675dfd56735c745744c3d968883b23cSantos Cordon        return retval;
38482f5d003e675dfd56735c745744c3d968883b23cSantos Cordon    }
38582f5d003e675dfd56735c745744c3d968883b23cSantos Cordon
38642373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    private void updatePrimaryDisplayInfo(ContactCacheEntry entry, boolean isConference) {
38742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        Log.d(TAG, "Update primary display " + entry);
3886d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        final CallCardUi ui = getUi();
389d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        if (ui == null) {
39042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // TODO: May also occur if search result comes back after ui is destroyed. Look into
39142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // removing that case completely.
39242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            Log.d(TAG, "updatePrimaryDisplayInfo called but ui is null!");
393d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon            return;
3946d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        }
395be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee
396812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        final boolean isGenericConf = isGenericConference(mPrimary);
39742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (entry != null) {
39842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            final String name = getNameForCall(entry);
39942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            final String number = getNumberForCall(entry);
40042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            final boolean nameIsNumber = name != null && name.equals(entry.number);
40142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            ui.setPrimary(number, name, nameIsNumber, entry.label,
402812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon                    entry.photo, isConference, isGenericConf, entry.isSipCall);
4036d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        } else {
404812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon            ui.setPrimary(null, null, false, null, null, isConference, isGenericConf, false);
405d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        }
406d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon
407d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    }
408d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon
4095345442d7238c1db00dc8d55a49f7f5dd713d994Christine Chen    private void updateSecondaryDisplayInfo(boolean isConference) {
41042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
41142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        final CallCardUi ui = getUi();
41242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (ui == null) {
41342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            return;
41442373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
41542373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
416812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon        final boolean isGenericConf = isGenericConference(mSecondary);
41742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (mSecondaryContactInfo != null) {
41842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            Log.d(TAG, "updateSecondaryDisplayInfo() " + mSecondaryContactInfo);
419c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee            final String nameForCall = getNameForCall(mSecondaryContactInfo);
420c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee
421c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee            final boolean nameIsNumber = nameForCall != null && nameForCall.equals(
422c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee                    mSecondaryContactInfo.number);
423e5c0d8bdf8269f9435e0381889e4870f36a43f07Andrew Lee            ui.setSecondary(true /* show */, nameForCall, nameIsNumber, mSecondaryContactInfo.label,
424bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                    getSecondaryCallProviderLabel(), getSecondaryCallProviderIcon(),
425e5c0d8bdf8269f9435e0381889e4870f36a43f07Andrew Lee                    isConference, isGenericConf);
42642373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        } else {
42742373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            // reset to nothing so that it starts off blank next time we use it.
428bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen            ui.setSecondary(false, null, false, null, null, null, isConference, isGenericConf);
42942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
43042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng    }
43142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng
4323d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    /**
4333d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     * Returns the gateway number for any existing outgoing call.
4343d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     */
4353d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private String getGatewayNumber() {
4363d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        if (hasOutgoingGatewayCall()) {
437ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal            return mPrimary.getGatewayInfo().getGatewayHandle().getSchemeSpecificPart();
4383d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        }
4393d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        return null;
4403d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
4413d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
4423d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    /**
443bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen     * Return the Drawable object of the icon to display to the left of the connection label.
444bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen     */
445bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    private Drawable getConnectionIcon() {
446df22018185375d2de96673ee8f16d1520283d662Ihab Awad        PhoneAccount account = mPrimary.getAccount();
447df22018185375d2de96673ee8f16d1520283d662Ihab Awad        if (account != null) {
448a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            PhoneAccountMetadata data = getTelecommManager().getPhoneAccountMetadata(account);
449a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            if (data != null) {
450a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal                return data.getIcon(mContext);
451a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            }
452bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        }
453bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        return null;
454bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    }
455bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen
456bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    /**
457bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen     * Returns the label (line of text above the number/name) for any given call.
458f8b0677bed382046cb26e38a8442a9509d1e835cSailesh Nepal     * For example, "calling via [Account/Google Voice]" for outgoing calls.
4593d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon     */
460bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    private String getConnectionLabel() {
4613d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        if (hasOutgoingGatewayCall() && getUi() != null) {
462bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen            // Return the label for the gateway app on outgoing calls.
4633d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            final PackageManager pm = mContext.getPackageManager();
4643d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            try {
465ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                ApplicationInfo info = pm.getApplicationInfo(
466ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                        mPrimary.getGatewayInfo().getGatewayProviderPackageName(), 0);
467bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                return pm.getApplicationLabel(info).toString();
4683d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            } catch (PackageManager.NameNotFoundException e) {
469bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                Log.e(this, "Gateway Application Not Found.", e);
470bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                return null;
4713d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon            }
4723d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        }
473df22018185375d2de96673ee8f16d1520283d662Ihab Awad        PhoneAccount account = mPrimary.getAccount();
474f8b0677bed382046cb26e38a8442a9509d1e835cSailesh Nepal        if (account != null) {
475a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            PhoneAccountMetadata data = getTelecommManager().getPhoneAccountMetadata(account);
476a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            if (data != null) {
477a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal                return data.getLabel();
478a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            }
479bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        }
480bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        return null;
481bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    }
482bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen
483bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    private String getSecondaryCallProviderLabel() {
484df22018185375d2de96673ee8f16d1520283d662Ihab Awad        PhoneAccount account = mSecondary.getAccount();
485df22018185375d2de96673ee8f16d1520283d662Ihab Awad        if (account != null) {
486a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            PhoneAccountMetadata data = getTelecommManager().getPhoneAccountMetadata(account);
487a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            if (data != null) {
488a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal                return data.getLabel();
489a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            }
490bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        }
491bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        return null;
492bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    }
493bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen
494bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen    private Drawable getSecondaryCallProviderIcon() {
495df22018185375d2de96673ee8f16d1520283d662Ihab Awad        PhoneAccount account = mSecondary.getAccount();
496df22018185375d2de96673ee8f16d1520283d662Ihab Awad        if (account != null) {
497a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            PhoneAccountMetadata data = getTelecommManager().getPhoneAccountMetadata(account);
498a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            if (data != null) {
499a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal                return data.getIcon(mContext);
500a39948564946dabae36a7201eb5c28d8941b96c3Sailesh Nepal            }
501bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen        }
5023d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        return null;
5033d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
5043d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
5053d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    private boolean hasOutgoingGatewayCall() {
5063d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        // We only display the gateway information while DIALING so return false for any othe
5073d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon        // call state.
50842373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // TODO: mPrimary can be null because this is called from updatePrimaryDisplayInfo which
50942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // is also called after a contact search completes (call is not present yet).  Split the
51042373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        // UI update so it can receive independent updates.
51142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        if (mPrimary == null) {
51242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng            return false;
51342373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        }
514ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal        return Call.State.isDialing(mPrimary.getState()) && mPrimary.getGatewayInfo() != null &&
515ae73c9aab1c716d9ef85f4f0dbc6f69e97a8f7e6Sailesh Nepal                !mPrimary.getGatewayInfo().isEmpty();
5163d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon    }
5173d3d25f2bee7cf9cdb91ef35d3028a6a62317e08Santos Cordon
518d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    /**
519d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     * Gets the name to display for the call.
520d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     */
521d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private static String getNameForCall(ContactCacheEntry contactInfo) {
522d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (TextUtils.isEmpty(contactInfo.name)) {
523d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon            return contactInfo.number;
5246d231f52e4f00399330d772f2a337283803f3a9dYorke Lee        }
525d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        return contactInfo.name;
526d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    }
5276d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
528d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    /**
529d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     * Gets the number to display for a call.
530d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon     */
531d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon    private static String getNumberForCall(ContactCacheEntry contactInfo) {
532d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // If the name is empty, we use the number for the name...so dont show a second
533d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        // number in the number field
534d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        if (TextUtils.isEmpty(contactInfo.name)) {
5351c6bb983216392b5ceb36cea42a46631f68a3dd6Jay Shrauner            return contactInfo.location;
536d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        }
537d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        return contactInfo.number;
538d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    }
5396d231f52e4f00399330d772f2a337283803f3a9dYorke Lee
540e5c0d8bdf8269f9435e0381889e4870f36a43f07Andrew Lee    public void secondaryInfoClicked() {
54180c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee        if (mSecondary == null) {
542e5c0d8bdf8269f9435e0381889e4870f36a43f07Andrew Lee            Log.wtf(this, "Secondary info clicked but no secondary call.");
54380c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee            return;
54480c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee        }
54580c49a823543c9fb93420d05a6375fb1ff4ca631Yorke Lee
546248a6687e8075e9730217be73c54ee4f95501a0eSailesh Nepal        Log.i(this, "Swapping call to foreground: " + mSecondary);
5478d38cf6761ae048b1a42504f1b59e872cf43df47Ihab Awad        TelecommAdapter.getInstance().unholdCall(mSecondary.getId());
54890995fcb6778a9cb6dc35be12aeb1a5d0dcbb5aeYorke Lee    }
54990995fcb6778a9cb6dc35be12aeb1a5d0dcbb5aeYorke Lee
5507e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee    public void endCallClicked() {
5517e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee        if (mPrimary == null) {
5527e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee            return;
5537e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee        }
5547e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee
555cb2f51bf1acf387f391ca9c8cae8a2344eb2936aEvan Charlton        Log.i(this, "Disconnecting call: " + mPrimary);
5568d38cf6761ae048b1a42504f1b59e872cf43df47Ihab Awad        TelecommAdapter.getInstance().disconnectCall(mPrimary.getId());
5577e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee    }
5587e5763d2b5ee7211c5d19d2b1fd2736e407a7e83Andrew Lee
559d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon    public interface CallCardUi extends Ui {
560d2bd93fe3929403f84367f826f07cbadc0c6366bSantos Cordon        void setVisible(boolean on);
561d28fc12696fa706fed70e04698275af7be7fee82Santos Cordon        void setPrimary(String number, String name, boolean nameIsNumber, String label,
562812c0e88d5d86c29e4942f9a1010a95cce789657Santos Cordon                Drawable photo, boolean isConference, boolean isGeneric, boolean isSipCall);
563c4bacb09c398a615154dc97b066179e77dc57599Yorke Lee        void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
564bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                String providerLabel, Drawable providerIcon, boolean isConference,
565bd93cb5444e886266b47e504138bcc65e6f09cbeNancy Chen                boolean isGeneric);
566a548a7a758928c8c675d93454e6a5c85d8b896cbNancy Chen        void setCallState(int state, int cause, String connectionLabel, Drawable connectionIcon,
567a548a7a758928c8c675d93454e6a5c85d8b896cbNancy Chen                String gatewayNumber);
5688cd746f0342f8c5def42f64b08cf6df741bb61bbSantos Cordon        void setPrimaryCallElapsedTime(boolean show, String duration);
56942373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryName(String name, boolean nameIsNumber);
57049ff6571403695e81dbbd83e4f61790ce9c75f6dSantos Cordon        void setPrimaryImage(Drawable image);
57142373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryPhoneNumber(String phoneNumber);
57242373eb59cbef15ec61ebb5c919031f293291a53Chiao Cheng        void setPrimaryLabel(String label);
573e26b887e90d5e9566a5054a1ccb3ed32ae2eea2dAndrew Lee        void setEndCallButtonEnabled(boolean enabled);
5740e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        void setEmergencyCallbackNumber(String number);
5750e84b83f23af354872b64fc1d1d77d22d825c71cEvan Charlton        void setCallDetails(android.telecomm.Call.Details details);
576be8060acf5ecbb916c161d3249813098c0611ed5Yorke Lee    }
5774feb57b986dc6b1edc5dc026a926b4934778716dIhab Awad
5784feb57b986dc6b1edc5dc026a926b4934778716dIhab Awad    private TelecommManager getTelecommManager() {
5794feb57b986dc6b1edc5dc026a926b4934778716dIhab Awad        if (mTelecommManager == null) {
5804feb57b986dc6b1edc5dc026a926b4934778716dIhab Awad            mTelecommManager = TelecommManager.from(mContext);
5814feb57b986dc6b1edc5dc026a926b4934778716dIhab Awad        }
5824feb57b986dc6b1edc5dc026a926b4934778716dIhab Awad        return mTelecommManager;
5834feb57b986dc6b1edc5dc026a926b4934778716dIhab Awad    }
584c2b430394ac612ba4dd455fb988e29bfcc4d5c5fSantos Cordon}
585