CallCard.java revision a232063e9bb9f7b8875a24af212287ba0d2cd0c3
1b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/*
2b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
3b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project *
4b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * you may not use this file except in compliance with the License.
6b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * You may obtain a copy of the License at
7b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project *
8b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project *
10b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * See the License for the specific language governing permissions and
14b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * limitations under the License.
15b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */
16b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
17b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpackage com.android.phone;
18b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
19b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.ContentUris;
20b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Context;
21b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.graphics.drawable.Drawable;
22b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.net.Uri;
23b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.pim.ContactsAsyncHelper;
243d6d70562622660e581b53308e675386d299dd19Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
25f3602b0659d01fef19159e7111be76102549f7a1David Brownimport android.telephony.PhoneNumberUtils;
26b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.text.TextUtils;
27b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.text.format.DateUtils;
28b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.AttributeSet;
29b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log;
30b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.LayoutInflater;
31b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.View;
32b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.ViewGroup;
33dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brownimport android.view.accessibility.AccessibilityEvent;
346d5544932495d81ff7ce53f4678c4beb25acc1b0David Brownimport android.widget.Button;
35b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.widget.FrameLayout;
36b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.widget.ImageView;
37b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.widget.TextView;
38b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
396b7d0da33af02960736da204eb7a25ccf91d5396David Brownimport com.android.internal.telephony.Call;
406b7d0da33af02960736da204eb7a25ccf91d5396David Brownimport com.android.internal.telephony.CallerInfo;
416b7d0da33af02960736da204eb7a25ccf91d5396David Brownimport com.android.internal.telephony.CallerInfoAsyncQuery;
426b7d0da33af02960736da204eb7a25ccf91d5396David Brownimport com.android.internal.telephony.Connection;
436b7d0da33af02960736da204eb7a25ccf91d5396David Brownimport com.android.internal.telephony.Phone;
448343169cc89621d46dce86449f5ee1ff5d3a4919John Wangimport com.android.internal.telephony.CallManager;
456b7d0da33af02960736da204eb7a25ccf91d5396David Brown
460fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Savilleimport java.util.List;
470fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
486b7d0da33af02960736da204eb7a25ccf91d5396David Brown
49b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/**
50b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * "Call card" UI element: the in-call screen contains a tiled layout of call
51b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * cards, each representing the state of a current "call" (ie. an active call,
52b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * a call on hold, or an incoming call.)
53b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */
54b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpublic class CallCard extends FrameLayout
55b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        implements CallTime.OnTickListener, CallerInfoAsyncQuery.OnQueryCompleteListener,
566d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                   ContactsAsyncHelper.OnImageLoadCompleteListener, View.OnClickListener {
57796c70c99bc39295bf685061056f06ab8949c742David Brown    private static final String LOG_TAG = "CallCard";
58796c70c99bc39295bf685061056f06ab8949c742David Brown    private static final boolean DBG = (PhoneApp.DBG_LEVEL >= 2);
59b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
608bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project    /**
618bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project     * Reference to the InCallScreen activity that owns us.  This may be
628bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project     * null if we haven't been initialized yet *or* after the InCallScreen
638bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project     * activity has been destroyed.
648bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project     */
658bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project    private InCallScreen mInCallScreen;
668bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project
670fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    // Phone app instance
680fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private PhoneApp mApplication;
690fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
70b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // Top-level subviews of the CallCard
710d315275d08cd33f801ae3a74e8fc265520f6246David Brown    private ViewGroup mPrimaryCallInfo;
720d315275d08cd33f801ae3a74e8fc265520f6246David Brown    private ViewGroup mSecondaryCallInfo;
73b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
7434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown    // Title and elapsed-time widgets
75b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private TextView mUpperTitle;
76b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private TextView mElapsedTime;
77b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
7834a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown    // Text colors, used for various labels / titles
799688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown    private int mTextColorDefaultPrimary;
809688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown    private int mTextColorDefaultSecondary;
81b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private int mTextColorConnected;
828bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project    private int mTextColorConnectedBluetooth;
83b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private int mTextColorEnded;
84b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private int mTextColorOnHold;
859d14e16e8214b4a396dad293b6f0941608ee4798David Brown    private int mTextColorCallTypeSip;
86b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
870d315275d08cd33f801ae3a74e8fc265520f6246David Brown    // The main block of info about the "primary" or "active" call,
880d315275d08cd33f801ae3a74e8fc265520f6246David Brown    // including photo / name / phone number / etc.
89b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private ImageView mPhoto;
906d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown    private Button mManageConferencePhotoButton;  // Possibly shown in place of mPhoto
91b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private TextView mName;
92b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private TextView mPhoneNumber;
93b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private TextView mLabel;
949d14e16e8214b4a396dad293b6f0941608ee4798David Brown    private TextView mCallTypeLabel;
9529d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown    private TextView mSocialStatus;
96b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
970d315275d08cd33f801ae3a74e8fc265520f6246David Brown    // Info about the "secondary" call, which is the "call on hold" when
980d315275d08cd33f801ae3a74e8fc265520f6246David Brown    // two lines are in use.
990d315275d08cd33f801ae3a74e8fc265520f6246David Brown    private TextView mSecondaryCallName;
1000d315275d08cd33f801ae3a74e8fc265520f6246David Brown    private TextView mSecondaryCallStatus;
1010d315275d08cd33f801ae3a74e8fc265520f6246David Brown    private ImageView mSecondaryCallPhoto;
102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // Menu button hint
104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private TextView mMenuButtonHint;
105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1069688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown    // Onscreen hint for the incoming call RotarySelector widget.
107ea505da2d0ebae37b07fece15297b5432fe96c5dJim Miller    private int mIncomingCallWidgetHintTextResId;
108ea505da2d0ebae37b07fece15297b5432fe96c5dJim Miller    private int mIncomingCallWidgetHintColorResId;
1099688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown
110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private CallTime mCallTime;
111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // Track the state for the photo.
113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private ContactsAsyncHelper.ImageTracker mPhotoTracker;
114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
11529d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown    // Cached DisplayMetrics density.
11629d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown    private float mDensity;
11729d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown
118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    public CallCard(Context context, AttributeSet attrs) {
119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        super(context, attrs);
120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("CallCard constructor...");
122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("- this = " + this);
123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("- context " + context + ", attrs " + attrs);
124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Inflate the contents of this CallCard, and add it (to ourself) as a child.
126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        LayoutInflater inflater = LayoutInflater.from(context);
127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        inflater.inflate(
128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                R.layout.call_card,  // resource
129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                this,                // root
130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                true);
131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1320fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        mApplication = PhoneApp.getInstance();
1330fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mCallTime = new CallTime(this);
135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // create a new object to track the state for the photo.
137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mPhotoTracker = new ContactsAsyncHelper.ImageTracker();
13829d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown
13929d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        mDensity = getResources().getDisplayMetrics().density;
14029d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        if (DBG) log("- Density: " + mDensity);
141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1438bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project    void setInCallScreenInstance(InCallScreen inCallScreen) {
1448bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project        mInCallScreen = inCallScreen;
1458bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project    }
1468bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project
147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    public void onTickForCallTimeElapsed(long timeElapsed) {
148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // While a call is in progress, update the elapsed time shown
149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // onscreen.
150b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        updateElapsedTimeWidget(timeElapsed);
151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /* package */
154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    void stopTimer() {
155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mCallTime.cancelTimer();
156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    @Override
159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    protected void onFinishInflate() {
160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        super.onFinishInflate();
161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("CallCard onFinishInflate(this = " + this + ")...");
163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1640d315275d08cd33f801ae3a74e8fc265520f6246David Brown        mPrimaryCallInfo = (ViewGroup) findViewById(R.id.primaryCallInfo);
1650d315275d08cd33f801ae3a74e8fc265520f6246David Brown        mSecondaryCallInfo = (ViewGroup) findViewById(R.id.secondaryCallInfo);
166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // "Upper" and "lower" title widgets
168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mUpperTitle = (TextView) findViewById(R.id.upperTitle);
169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mElapsedTime = (TextView) findViewById(R.id.elapsedTime);
170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Text colors
1729688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        mTextColorDefaultPrimary =  // corresponds to textAppearanceLarge
1739688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown                getResources().getColor(android.R.color.primary_text_dark);
1749688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        mTextColorDefaultSecondary =  // corresponds to textAppearanceSmall
1759688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown                getResources().getColor(android.R.color.secondary_text_dark);
176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mTextColorConnected = getResources().getColor(R.color.incall_textConnected);
1778bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project        mTextColorConnectedBluetooth =
1788bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project                getResources().getColor(R.color.incall_textConnectedBluetooth);
179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mTextColorEnded = getResources().getColor(R.color.incall_textEnded);
180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mTextColorOnHold = getResources().getColor(R.color.incall_textOnHold);
1819d14e16e8214b4a396dad293b6f0941608ee4798David Brown        mTextColorCallTypeSip = getResources().getColor(R.color.incall_callTypeSip);
182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // "Caller info" area, including photo / name / phone numbers / etc
184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mPhoto = (ImageView) findViewById(R.id.photo);
1856d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        mManageConferencePhotoButton = (Button) findViewById(R.id.manageConferencePhotoButton);
1866d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        mManageConferencePhotoButton.setOnClickListener(this);
187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mName = (TextView) findViewById(R.id.name);
188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mPhoneNumber = (TextView) findViewById(R.id.phoneNumber);
189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mLabel = (TextView) findViewById(R.id.label);
1909d14e16e8214b4a396dad293b6f0941608ee4798David Brown        mCallTypeLabel = (TextView) findViewById(R.id.callTypeLabel);
19129d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        mSocialStatus = (TextView) findViewById(R.id.socialStatus);
192b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // "Other call" info area
1940d315275d08cd33f801ae3a74e8fc265520f6246David Brown        mSecondaryCallName = (TextView) findViewById(R.id.secondaryCallName);
1950d315275d08cd33f801ae3a74e8fc265520f6246David Brown        mSecondaryCallStatus = (TextView) findViewById(R.id.secondaryCallStatus);
1960d315275d08cd33f801ae3a74e8fc265520f6246David Brown        mSecondaryCallPhoto = (ImageView) findViewById(R.id.secondaryCallPhoto);
197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
198b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Menu Button hint
199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mMenuButtonHint = (TextView) findViewById(R.id.menuButtonHint);
200b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
202b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown    /**
203b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown     * Updates the state of all UI elements on the CallCard, based on the
204b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown     * current state of the phone.
205b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown     */
2068343169cc89621d46dce86449f5ee1ff5d3a4919John Wang    void updateState(CallManager cm) {
2078343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        if (DBG) log("updateState(" + cm + ")...");
208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Update some internal state based on the current state of the phone.
2106b7d0da33af02960736da204eb7a25ccf91d5396David Brown
2116b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // TODO: clean up this method to just fully update EVERYTHING in
2126b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // the callcard based on the current phone state: set the overall
2136b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // type of the CallCard, load up the main caller info area, and
2146b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // load up and show or hide the "other call" area if necessary.
215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
2168343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        Phone.State state = cm.getState();  // IDLE, RINGING, or OFFHOOK
217091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan        Call ringingCall = cm.getFirstActiveRingingCall();
218091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan        Call fgCall = cm.getActiveFgCall();
219091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan        Call bgCall = cm.getFirstActiveBgCall();
220091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan
2217f09c1629141416c489ede69e70e2aa59453ddedHung-ying Tyan        // If the FG call is dialing/alerting, we should display for that call
2227f09c1629141416c489ede69e70e2aa59453ddedHung-ying Tyan        // and ignore the ringing call. This case happens when the telephony
2237f09c1629141416c489ede69e70e2aa59453ddedHung-ying Tyan        // layer rejects the ringing call while the FG call is dialing/alerting,
2247f09c1629141416c489ede69e70e2aa59453ddedHung-ying Tyan        // but the incoming call *does* briefly exist in the DISCONNECTING or
2257f09c1629141416c489ede69e70e2aa59453ddedHung-ying Tyan        // DISCONNECTED state.
2267f09c1629141416c489ede69e70e2aa59453ddedHung-ying Tyan        if ((ringingCall.getState() != Call.State.IDLE)
2277f09c1629141416c489ede69e70e2aa59453ddedHung-ying Tyan                && !fgCall.getState().isDialing()) {
228091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // A phone call is ringing, call waiting *or* being rejected
229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // (ie. another call may also be active as well.)
2308343169cc89621d46dce86449f5ee1ff5d3a4919John Wang            updateRingingCall(cm);
231091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan        } else if ((fgCall.getState() != Call.State.IDLE)
232091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan                || (bgCall.getState() != Call.State.IDLE)) {
233091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // We are here because either:
234091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // (1) the phone is off hook. At least one call exists that is
235091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // dialing, active, or holding, and no calls are ringing or waiting,
236091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // or:
237091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // (2) the phone is IDLE but a call just ended and it's still in
238091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // the DISCONNECTING or DISCONNECTED state. In this case, we want
239091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // the main CallCard to display "Hanging up" or "Call ended".
240091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // The normal "foreground call" code path handles both cases.
2418343169cc89621d46dce86449f5ee1ff5d3a4919John Wang            updateForegroundCall(cm);
242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else {
243091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // We don't have any DISCONNECTED calls, which means
244091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // that the phone is *truly* idle.
245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            //
246091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // It's very rare to be on the InCallScreen at all in this
247091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // state, but it can happen in some cases:
248091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // - A stray onPhoneStateChanged() event came in to the
249091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            //   InCallScreen *after* it was dismissed.
250091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // - We're allowed to be on the InCallScreen because
251091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            //   an MMI or USSD is running, but there's no actual "call"
252091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            //   to display.
253091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // - We're displaying an error dialog to the user
254091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            //   (explaining why the call failed), so we need to stay on
255091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            //   the InCallScreen so that the dialog will be visible.
256091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            //
257091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            // In these cases, put the callcard into a sane but "blank" state:
258091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan            updateNoCall(cm);
259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates the UI for the state where the phone is in use, but not ringing.
264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
2658343169cc89621d46dce86449f5ee1ff5d3a4919John Wang    private void updateForegroundCall(CallManager cm) {
266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("updateForegroundCall()...");
26702d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown        // if (DBG) PhoneUtils.dumpCallManager();
2688343169cc89621d46dce86449f5ee1ff5d3a4919John Wang
2698343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        Call fgCall = cm.getActiveFgCall();
2708343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        Call bgCall = cm.getFirstActiveBgCall();
2718343169cc89621d46dce86449f5ee1ff5d3a4919John Wang
272091ccad8630a43e62d84fba9c7613441e9d0a597Hung-ying Tyan        if (fgCall.getState() == Call.State.IDLE) {
273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (DBG) log("updateForegroundCall: no active call, show holding call");
274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // TODO: make sure this case agrees with the latest UI spec.
275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Display the background call in the main info area of the
277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // CallCard, since there is no foreground call.  Note that
278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // displayMainCallStatus() will notice if the call we passed in is on
279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // hold, and display the "on hold" indication.
280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            fgCall = bgCall;
281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // And be sure to not display anything in the "on hold" box.
283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            bgCall = null;
284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
2868343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        displayMainCallStatus(cm, fgCall);
2878343169cc89621d46dce86449f5ee1ff5d3a4919John Wang
2888343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        Phone phone = fgCall.getPhone();
2890fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
29079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink        int phoneType = phone.getPhoneType();
29179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink        if (phoneType == Phone.PHONE_TYPE_CDMA) {
29239a84144262f12df44861d746788b9de92259e4fAbhishek Pillai            if ((mApplication.cdmaPhoneCallState.getCurrentCallState()
29339a84144262f12df44861d746788b9de92259e4fAbhishek Pillai                    == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE)
29439a84144262f12df44861d746788b9de92259e4fAbhishek Pillai                    && mApplication.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) {
2958343169cc89621d46dce86449f5ee1ff5d3a4919John Wang                displayOnHoldCallStatus(cm, fgCall);
2960fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            } else {
2970fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                //This is required so that even if a background call is not present
2980fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                // we need to clean up the background call area.
2998343169cc89621d46dce86449f5ee1ff5d3a4919John Wang                displayOnHoldCallStatus(cm, bgCall);
3000fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            }
301872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
302872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                || (phoneType == Phone.PHONE_TYPE_SIP)) {
3038343169cc89621d46dce86449f5ee1ff5d3a4919John Wang            displayOnHoldCallStatus(cm, bgCall);
3040fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates the UI for the state where an incoming call is ringing (or
309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * call waiting), regardless of whether the phone's already offhook.
310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
3118343169cc89621d46dce86449f5ee1ff5d3a4919John Wang    private void updateRingingCall(CallManager cm) {
312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("updateRingingCall()...");
313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
3148343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        Call ringingCall = cm.getFirstActiveRingingCall();
315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
3166b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // Display caller-id info and photo from the incoming call:
3178343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        displayMainCallStatus(cm, ringingCall);
3186b7d0da33af02960736da204eb7a25ccf91d5396David Brown
3196b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // And even in the Call Waiting case, *don't* show any info about
3206b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // the current ongoing call and/or the current call on hold.
3216b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // (Since the caller-id info for the incoming call totally trumps
3226b7d0da33af02960736da204eb7a25ccf91d5396David Brown        // any info about the current call(s) in progress.)
3238343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        displayOnHoldCallStatus(cm, null);
324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates the UI for the state where the phone is not in use.
328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * This is analogous to updateForegroundCall() and updateRingingCall(),
329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * but for the (uncommon) case where the phone is
330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * totally idle.  (See comments in updateState() above.)
331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * This puts the callcard into a sane but "blank" state.
333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
3348343169cc89621d46dce86449f5ee1ff5d3a4919John Wang    private void updateNoCall(CallManager cm) {
335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("updateNoCall()...");
336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
3378343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        displayMainCallStatus(cm, null);
3388343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        displayOnHoldCallStatus(cm, null);
339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates the main block of caller info on the CallCard
3430d315275d08cd33f801ae3a74e8fc265520f6246David Brown     * (ie. the stuff in the primaryCallInfo block) based on the specified Call.
344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
3458343169cc89621d46dce86449f5ee1ff5d3a4919John Wang    private void displayMainCallStatus(CallManager cm, Call call) {
34602d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown        if (DBG) log("displayMainCallStatus(call " + call + ")...");
347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (call == null) {
349b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // There's no call to display, presumably because the phone is idle.
3500d315275d08cd33f801ae3a74e8fc265520f6246David Brown            mPrimaryCallInfo.setVisibility(View.GONE);
351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            return;
352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
3530d315275d08cd33f801ae3a74e8fc265520f6246David Brown        mPrimaryCallInfo.setVisibility(View.VISIBLE);
354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Call.State state = call.getState();
356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("  - call.state: " + call.getState());
357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        switch (state) {
359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case ACTIVE:
3605eff1e7d582679b3a85f580eb1d550b2e6ca111cDavid Brown            case DISCONNECTING:
361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // update timer field
362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (DBG) log("displayMainCallStatus: start periodicUpdateTimer");
363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallTime.setActiveCallMode(call);
364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallTime.reset();
365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallTime.periodicUpdateTimer();
366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case HOLDING:
370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // update timer field
371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallTime.cancelTimer();
372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case DISCONNECTED:
376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Stop getting timer ticks from this call
377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallTime.cancelTimer();
378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case DIALING:
382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case ALERTING:
383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Stop getting timer ticks from a previous call
384b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallTime.cancelTimer();
385b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
386b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
387b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case INCOMING:
389b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case WAITING:
390b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Stop getting timer ticks from a previous call
391b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallTime.cancelTimer();
392b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
393b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
394b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
395b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case IDLE:
396b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // The "main CallCard" should never be trying to display
397b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // an idle call!  In updateState(), if the phone is idle,
398b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // we call updateNoCall(), which means that we shouldn't
399b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // have passed a call into this method at all.
400b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                Log.w(LOG_TAG, "displayMainCallStatus: IDLE call in the main call card!");
401b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
402b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // (It is possible, though, that we had a valid call which
403b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // became idle *after* the check in updateState() but
404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // before we get here...  So continue the best we can,
405b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // with whatever (stale) info we can get from the
406b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // passed-in Call object.)
407b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
408b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
409b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
410b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            default:
411b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                Log.w(LOG_TAG, "displayMainCallStatus: unexpected call state: " + state);
412b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
413b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
414b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
4158343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        updateCardTitleWidgets(call.getPhone(), call);
416b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
417b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (PhoneUtils.isConferenceCall(call)) {
418b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Update onscreen info for a conference call.
419872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            updateDisplayForConference(call);
420b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else {
421b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Update onscreen info for a regular call (which presumably
422b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // has only one connection.)
4230fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            Connection conn = null;
4248343169cc89621d46dce86449f5ee1ff5d3a4919John Wang            int phoneType = call.getPhone().getPhoneType();
42579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink            if (phoneType == Phone.PHONE_TYPE_CDMA) {
4260fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                conn = call.getLatestConnection();
427872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
428872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                  || (phoneType == Phone.PHONE_TYPE_SIP)) {
4290fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                conn = call.getEarliestConnection();
43079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink            } else {
43179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                throw new IllegalStateException("Unexpected phone type: " + phoneType);
4320fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            }
433b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
434b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (conn == null) {
435b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (DBG) log("displayMainCallStatus: connection is null, using default values.");
436b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // if the connection is null, we run through the behaviour
437b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // we had in the past, which breaks down into trivial steps
438b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // with the current implementation of getCallerInfo and
439b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // updateDisplayForPerson.
4404359358c4f430cbb986a5e7640ec506f08f1e332David Brown                CallerInfo info = PhoneUtils.getCallerInfo(getContext(), null /* conn */);
4414359358c4f430cbb986a5e7640ec506f08f1e332David Brown                updateDisplayForPerson(info, Connection.PRESENTATION_ALLOWED, false, call);
442b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            } else {
443b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (DBG) log("  - CONN: " + conn + ", state = " + conn.getState());
4444359358c4f430cbb986a5e7640ec506f08f1e332David Brown                int presentation = conn.getNumberPresentation();
445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // make sure that we only make a new query when the current
447b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // callerinfo differs from what we've been requested to display.
448b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                boolean runQuery = true;
449b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                Object o = conn.getUserData();
450b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (o instanceof PhoneUtils.CallerInfoToken) {
451b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    runQuery = mPhotoTracker.isDifferentImageRequest(
452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                            ((PhoneUtils.CallerInfoToken) o).currentInfo);
453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                } else {
454b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    runQuery = mPhotoTracker.isDifferentImageRequest(conn);
455b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
456b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
45746532b66a467f247380054270c6151aa3dc7a761Wink Saville                // Adding a check to see if the update was caused due to a Phone number update
45846532b66a467f247380054270c6151aa3dc7a761Wink Saville                // or CNAP update. If so then we need to start a new query
45979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                if (phoneType == Phone.PHONE_TYPE_CDMA) {
46046532b66a467f247380054270c6151aa3dc7a761Wink Saville                    Object obj = conn.getUserData();
46146532b66a467f247380054270c6151aa3dc7a761Wink Saville                    String updatedNumber = conn.getAddress();
46246532b66a467f247380054270c6151aa3dc7a761Wink Saville                    String updatedCnapName = conn.getCnapName();
46346532b66a467f247380054270c6151aa3dc7a761Wink Saville                    CallerInfo info = null;
46446532b66a467f247380054270c6151aa3dc7a761Wink Saville                    if (obj instanceof PhoneUtils.CallerInfoToken) {
46546532b66a467f247380054270c6151aa3dc7a761Wink Saville                        info = ((PhoneUtils.CallerInfoToken) o).currentInfo;
46646532b66a467f247380054270c6151aa3dc7a761Wink Saville                    } else if (o instanceof CallerInfo) {
46746532b66a467f247380054270c6151aa3dc7a761Wink Saville                        info = (CallerInfo) o;
46846532b66a467f247380054270c6151aa3dc7a761Wink Saville                    }
46946532b66a467f247380054270c6151aa3dc7a761Wink Saville
47046532b66a467f247380054270c6151aa3dc7a761Wink Saville                    if (info != null) {
47146532b66a467f247380054270c6151aa3dc7a761Wink Saville                        if (updatedNumber != null && !updatedNumber.equals(info.phoneNumber)) {
47246532b66a467f247380054270c6151aa3dc7a761Wink Saville                            if (DBG) log("- displayMainCallStatus: updatedNumber = "
47346532b66a467f247380054270c6151aa3dc7a761Wink Saville                                    + updatedNumber);
47446532b66a467f247380054270c6151aa3dc7a761Wink Saville                            runQuery = true;
47546532b66a467f247380054270c6151aa3dc7a761Wink Saville                        }
47646532b66a467f247380054270c6151aa3dc7a761Wink Saville                        if (updatedCnapName != null && !updatedCnapName.equals(info.cnapName)) {
47746532b66a467f247380054270c6151aa3dc7a761Wink Saville                            if (DBG) log("- displayMainCallStatus: updatedCnapName = "
47846532b66a467f247380054270c6151aa3dc7a761Wink Saville                                    + updatedCnapName);
47946532b66a467f247380054270c6151aa3dc7a761Wink Saville                            runQuery = true;
48046532b66a467f247380054270c6151aa3dc7a761Wink Saville                        }
48146532b66a467f247380054270c6151aa3dc7a761Wink Saville                    }
48246532b66a467f247380054270c6151aa3dc7a761Wink Saville                }
48346532b66a467f247380054270c6151aa3dc7a761Wink Saville
484b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (runQuery) {
485b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (DBG) log("- displayMainCallStatus: starting CallerInfo query...");
486b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    PhoneUtils.CallerInfoToken info =
487b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                            PhoneUtils.startGetCallerInfo(getContext(), conn, this, call);
4884b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project                    updateDisplayForPerson(info.currentInfo, presentation, !info.isFinal, call);
489b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                } else {
490b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // No need to fire off a new query.  We do still need
491b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // to update the display, though (since we might have
492b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // previously been in the "conference call" state.)
493b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (DBG) log("- displayMainCallStatus: using data we already have...");
494b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (o instanceof CallerInfo) {
495b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        CallerInfo ci = (CallerInfo) o;
496e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                        // Update CNAP information if Phone state change occurred
497e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                        ci.cnapName = conn.getCnapName();
498e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                        ci.numberPresentation = conn.getNumberPresentation();
499e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                        ci.namePresentation = conn.getCnapNamePresentation();
500e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                        if (DBG) log("- displayMainCallStatus: CNAP data from Connection: "
501e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                                + "CNAP name=" + ci.cnapName
502e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                                + ", Number/Name Presentation=" + ci.numberPresentation);
503b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        if (DBG) log("   ==> Got CallerInfo; updating display: ci = " + ci);
5044b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project                        updateDisplayForPerson(ci, presentation, false, call);
505b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    } else if (o instanceof PhoneUtils.CallerInfoToken){
506b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        CallerInfo ci = ((PhoneUtils.CallerInfoToken) o).currentInfo;
507e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                        if (DBG) log("- displayMainCallStatus: CNAP data from Connection: "
508e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                                + "CNAP name=" + ci.cnapName
509e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                                + ", Number/Name Presentation=" + ci.numberPresentation);
510b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        if (DBG) log("   ==> Got CallerInfoToken; updating display: ci = " + ci);
5114b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project                        updateDisplayForPerson(ci, presentation, true, call);
512b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    } else {
513b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        Log.w(LOG_TAG, "displayMainCallStatus: runQuery was false, "
514b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                              + "but we didn't have a cached CallerInfo object!  o = " + o);
515b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        // TODO: any easy way to recover here (given that
516b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        // the CallCard is probably displaying stale info
517b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        // right now?)  Maybe force the CallCard into the
518b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        // "Unknown" state?
519b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    }
520b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
521b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
522b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
523b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
524b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // In some states we override the "photo" ImageView to be an
525b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // indication of the current state, rather than displaying the
526b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // regular photo as set above.
527b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        updatePhotoForCallState(call);
5289688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown
5299688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        // One special feature of the "number" text field: For incoming
5309688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        // calls, while the user is dragging the RotarySelector widget, we
5319688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        // use mPhoneNumber to display a hint like "Rotate to answer".
532ea505da2d0ebae37b07fece15297b5432fe96c5dJim Miller        if (mIncomingCallWidgetHintTextResId != 0) {
5339688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown            // Display the hint!
534ea505da2d0ebae37b07fece15297b5432fe96c5dJim Miller            mPhoneNumber.setText(mIncomingCallWidgetHintTextResId);
535ea505da2d0ebae37b07fece15297b5432fe96c5dJim Miller            mPhoneNumber.setTextColor(getResources().getColor(mIncomingCallWidgetHintColorResId));
5369688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown            mPhoneNumber.setVisibility(View.VISIBLE);
5379688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown            mLabel.setVisibility(View.GONE);
5389688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        }
5399688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        // If we don't have a hint to display, just don't touch
5409688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        // mPhoneNumber and mLabel. (Their text / color / visibility have
5419688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        // already been set correctly, by either updateDisplayForPerson()
5429688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown        // or updateDisplayForConference().)
543b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown    }
544b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown
545b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown    /**
546b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Implemented for CallerInfoAsyncQuery.OnQueryCompleteListener interface.
547b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * refreshes the CallCard data when it called.
548b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
549b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    public void onQueryComplete(int token, Object cookie, CallerInfo ci) {
550b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("onQueryComplete: token " + token + ", cookie " + cookie + ", ci " + ci);
551b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
552b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (cookie instanceof Call) {
553b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // grab the call object and update the display for an individual call,
554b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // as well as the successive call to update image via call state.
555b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // If the object is a textview instead, we update it as we need to.
556b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (DBG) log("callerinfo query complete, updating ui from displayMainCallStatus()");
557b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            Call call = (Call) cookie;
558a0ea7a803c8953a14bc35d1fef0973fd1d9c64b9Abhishek Pillai            Connection conn = null;
559872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            int phoneType = call.getPhone().getPhoneType();
560a0ea7a803c8953a14bc35d1fef0973fd1d9c64b9Abhishek Pillai            if (phoneType == Phone.PHONE_TYPE_CDMA) {
561a0ea7a803c8953a14bc35d1fef0973fd1d9c64b9Abhishek Pillai                conn = call.getLatestConnection();
562872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            } else if ((phoneType == Phone.PHONE_TYPE_GSM)
563872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                  || (phoneType == Phone.PHONE_TYPE_SIP)) {
564a0ea7a803c8953a14bc35d1fef0973fd1d9c64b9Abhishek Pillai                conn = call.getEarliestConnection();
565a0ea7a803c8953a14bc35d1fef0973fd1d9c64b9Abhishek Pillai            } else {
566a0ea7a803c8953a14bc35d1fef0973fd1d9c64b9Abhishek Pillai                throw new IllegalStateException("Unexpected phone type: " + phoneType);
567a0ea7a803c8953a14bc35d1fef0973fd1d9c64b9Abhishek Pillai            }
568e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai            PhoneUtils.CallerInfoToken cit =
569e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                   PhoneUtils.startGetCallerInfo(getContext(), conn, this, null);
570e066d6979acb39dbc0ba79ecc10bc12e84a15195David Brown
571e066d6979acb39dbc0ba79ecc10bc12e84a15195David Brown            int presentation = Connection.PRESENTATION_ALLOWED;
572e066d6979acb39dbc0ba79ecc10bc12e84a15195David Brown            if (conn != null) presentation = conn.getNumberPresentation();
573e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai            if (DBG) log("- onQueryComplete: presentation=" + presentation
574e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    + ", contactExists=" + ci.contactExists);
575e066d6979acb39dbc0ba79ecc10bc12e84a15195David Brown
576e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai            // Depending on whether there was a contact match or not, we want to pass in different
577e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai            // CallerInfo (for CNAP). Therefore if ci.contactExists then use the ci passed in.
578e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai            // Otherwise, regenerate the CIT from the Connection and use the CallerInfo from there.
579e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai            if (ci.contactExists) {
580e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                updateDisplayForPerson(ci, Connection.PRESENTATION_ALLOWED, false, call);
581e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai            } else {
582e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                updateDisplayForPerson(cit.currentInfo, presentation, false, call);
583e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai            }
584b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            updatePhotoForCallState(call);
585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else if (cookie instanceof TextView){
587b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (DBG) log("callerinfo query complete, updating ui from ongoing or onhold");
588b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            ((TextView) cookie).setText(PhoneUtils.getCompactNameFromCallerInfo(ci, mContext));
589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
591b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
593b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Implemented for ContactsAsyncHelper.OnImageLoadCompleteListener interface.
594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * make sure that the call state is reflected after the image is loaded.
595b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
596b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    public void onImageLoadComplete(int token, Object cookie, ImageView iView,
597b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            boolean imagePresent){
598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (cookie != null) {
599b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            updatePhotoForCallState((Call) cookie);
600b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
601b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
602b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
603b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
60434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown     * Updates the "card title" (and also elapsed time widget) based on
60534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown     * the current state of the call.
606b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
607e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown    // TODO: it's confusing for updateCardTitleWidgets() and
608e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown    // getTitleForCallCard() to be separate methods, since they both
609e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown    // just list out the exact same "phone state" cases.
610e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown    // Let's merge the getTitleForCallCard() logic into here.
611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void updateCardTitleWidgets(Phone phone, Call call) {
612b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("updateCardTitleWidgets(call " + call + ")...");
613b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Call.State state = call.getState();
614f3602b0659d01fef19159e7111be76102549f7a1David Brown        Context context = getContext();
615b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
616b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // TODO: Still need clearer spec on exactly how title *and* status get
617b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // set in all states.  (Then, given that info, refactor the code
618b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // here to be more clear about exactly which widgets on the card
619b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // need to be set.)
620b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
6213800ac871d6548790ac6119bb68b9be0640af261David Krause        String cardTitle;
622872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        int phoneType = phone.getPhoneType();
62379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink        if (phoneType == Phone.PHONE_TYPE_CDMA) {
6243800ac871d6548790ac6119bb68b9be0640af261David Krause            if (!PhoneApp.getInstance().notifier.getIsCdmaRedialCall()) {
6256b7d0da33af02960736da204eb7a25ccf91d5396David Brown                cardTitle = getTitleForCallCard(call);  // Normal "foreground" call card
6263800ac871d6548790ac6119bb68b9be0640af261David Krause            } else {
627f3602b0659d01fef19159e7111be76102549f7a1David Brown                cardTitle = context.getString(R.string.card_title_redialing);
6283800ac871d6548790ac6119bb68b9be0640af261David Krause            }
629872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
630872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                || (phoneType == Phone.PHONE_TYPE_SIP)) {
6313800ac871d6548790ac6119bb68b9be0640af261David Krause            cardTitle = getTitleForCallCard(call);
63279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink        } else {
63379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink            throw new IllegalStateException("Unexpected phone type: " + phoneType);
6343800ac871d6548790ac6119bb68b9be0640af261David Krause        }
635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("updateCardTitleWidgets: " + cardTitle);
636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
63734a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown        // Update the title and elapsed time widgets based on the current call state.
63834a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown        switch (state) {
63934a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown            case ACTIVE:
64034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown            case DISCONNECTING:
64134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                final boolean bluetoothActive = mApplication.showBluetoothIndication();
64234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                int ongoingCallIcon = bluetoothActive ? R.drawable.ic_incall_ongoing_bluetooth
64334a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                        : R.drawable.ic_incall_ongoing;
64434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                int connectedTextColor = bluetoothActive
64534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                        ? mTextColorConnectedBluetooth : mTextColorConnected;
646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
64779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                if (phoneType == Phone.PHONE_TYPE_CDMA) {
648f3602b0659d01fef19159e7111be76102549f7a1David Brown                    // In normal operation we don't use an "upper title" at all,
649f3602b0659d01fef19159e7111be76102549f7a1David Brown                    // except for a couple of special cases:
65034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                    if (mApplication.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) {
651f3602b0659d01fef19159e7111be76102549f7a1David Brown                        // Display "Dialing" while dialing a 3Way call, even
652f3602b0659d01fef19159e7111be76102549f7a1David Brown                        // though the foreground call state is still ACTIVE.
653f3602b0659d01fef19159e7111be76102549f7a1David Brown                        setUpperTitle(cardTitle, mTextColorDefaultPrimary, state);
654f3602b0659d01fef19159e7111be76102549f7a1David Brown                    } else if (PhoneUtils.isPhoneInEcm(phone)) {
655f3602b0659d01fef19159e7111be76102549f7a1David Brown                        // In emergency callback mode (ECM), use a special title
656f3602b0659d01fef19159e7111be76102549f7a1David Brown                        // that shows your own phone number.
657f3602b0659d01fef19159e7111be76102549f7a1David Brown                        cardTitle = getECMCardTitle(context, phone);
6589688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown                        setUpperTitle(cardTitle, mTextColorDefaultPrimary, state);
65934a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                    } else {
66034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                        // Normal "ongoing call" state; don't use any "title" at all.
66134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                        clearUpperTitle();
66234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                    }
663872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                } else if ((phoneType == Phone.PHONE_TYPE_GSM)
664872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                        || (phoneType == Phone.PHONE_TYPE_SIP)) {
665e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    // While in the DISCONNECTING state we display a
666e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    // "Hanging up" message in order to make the UI feel more
667e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    // responsive.  (In GSM it's normal to see a delay of a
668e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    // couple of seconds while negotiating the disconnect with
669e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    // the network, so the "Hanging up" state at least lets
670e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    // the user know that we're doing something.)
671e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    // TODO: consider displaying the "Hanging up" state for
672e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    // CDMA also if the latency there ever gets high enough.
673e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    if (state == Call.State.DISCONNECTING) {
674e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                        // Display the brief "Hanging up" indication.
675e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                        setUpperTitle(cardTitle, mTextColorDefaultPrimary, state);
676e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    } else {  // state == Call.State.ACTIVE
677e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                        // Normal "ongoing call" state; don't use any "title" at all.
678e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                        clearUpperTitle();
679e806935bab812a8ebf71846cdf342bb1a46a45f4David Brown                    }
68034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                }
68134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
68234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // Use the elapsed time widget to show the current call duration.
68334a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                mElapsedTime.setVisibility(View.VISIBLE);
68434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                mElapsedTime.setTextColor(connectedTextColor);
68534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                long duration = CallTime.getCallDuration(call);  // msec
68634a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                updateElapsedTimeWidget(duration / 1000);
68734a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // Also see onTickForCallTimeElapsed(), which updates this
68834a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // widget once per second while the call is active.
68934a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                break;
69034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
69134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown            case DISCONNECTED:
69234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // Display "Call ended" (or possibly some error indication;
69334a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // see getCallFailedString()) in the upper title, in red.
69434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
69534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // TODO: display a "call ended" icon somewhere, like the old
69634a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // R.drawable.ic_incall_end?
69734a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
69834a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                setUpperTitle(cardTitle, mTextColorEnded, state);
69934a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
70034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // In the "Call ended" state, leave the mElapsedTime widget
70134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // visible, but don't touch it (so  we continue to see the elapsed time of
70234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // the call that just ended.)
70334a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                mElapsedTime.setVisibility(View.VISIBLE);
70434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                mElapsedTime.setTextColor(mTextColorEnded);
70534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                break;
70634a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
70734a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown            case HOLDING:
70834a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // For a single call on hold, display the title "On hold" in
70934a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // orange.
71034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // (But since the upper title overlaps the label of the
71134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // Hold/Unhold button, we actually use the elapsedTime widget
71234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // to display the title in this case.)
71334a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
71434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // TODO: display an "On hold" icon somewhere, like the old
71534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // R.drawable.ic_incall_onhold?
71634a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
71734a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                clearUpperTitle();
71834a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                mElapsedTime.setText(cardTitle);
71934a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
72034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // While on hold, the elapsed time widget displays an
72134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // "on hold" indication rather than an amount of time.
72234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                mElapsedTime.setVisibility(View.VISIBLE);
72334a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                mElapsedTime.setTextColor(mTextColorOnHold);
72434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                break;
72534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
72634a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown            default:
72734a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // All other states (DIALING, INCOMING, etc.) use the "upper title":
7289688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown                setUpperTitle(cardTitle, mTextColorDefaultPrimary, state);
72934a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
73034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                // ...and we don't show the elapsed time.
73134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                mElapsedTime.setVisibility(View.INVISIBLE);
73234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                break;
733b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
734b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
735b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
736b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
737b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates mElapsedTime based on the specified number of seconds.
738b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * A timeElapsed value of zero means to not show an elapsed time at all.
739b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
740b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void updateElapsedTimeWidget(long timeElapsed) {
741b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // if (DBG) log("updateElapsedTimeWidget: " + timeElapsed);
742b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (timeElapsed == 0) {
743b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mElapsedTime.setText("");
744b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else {
745b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mElapsedTime.setText(DateUtils.formatElapsedTime(timeElapsed));
746b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
747b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
748b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Returns the "card title" displayed at the top of a foreground
751b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * ("active") CallCard to indicate the current state of this call, like
752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * "Dialing" or "In call" or "On hold".  A null return value means that
753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * there's no title string for this state.
754b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
755b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private String getTitleForCallCard(Call call) {
756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        String retVal = null;
757b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Call.State state = call.getState();
758b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Context context = getContext();
759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
760b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("- getTitleForCallCard(Call " + call + ")...");
761b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
762b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        switch (state) {
763b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case IDLE:
764b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
765b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
766b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case ACTIVE:
767b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Title is "Call in progress".  (Note this appears in the
768b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // "lower title" area of the CallCard.)
769872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                int phoneType = call.getPhone().getPhoneType();
77079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                if (phoneType == Phone.PHONE_TYPE_CDMA) {
7710fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    if (mApplication.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) {
7720fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        retVal = context.getString(R.string.card_title_dialing);
7730fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    } else {
7740fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        retVal = context.getString(R.string.card_title_in_progress);
7750fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    }
776872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                } else if ((phoneType == Phone.PHONE_TYPE_GSM)
777872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                        || (phoneType == Phone.PHONE_TYPE_SIP)) {
7780fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    retVal = context.getString(R.string.card_title_in_progress);
77979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                } else {
78079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                    throw new IllegalStateException("Unexpected phone type: " + phoneType);
7810fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                }
782b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
783b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
784b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case HOLDING:
785b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                retVal = context.getString(R.string.card_title_on_hold);
786b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // TODO: if this is a conference call on hold,
787b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // maybe have a special title here too?
788b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
789b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
790b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case DIALING:
791b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case ALERTING:
792b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                retVal = context.getString(R.string.card_title_dialing);
793b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
794b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
795b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case INCOMING:
796b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case WAITING:
797b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                retVal = context.getString(R.string.card_title_incoming_call);
798b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
799b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
8005eff1e7d582679b3a85f580eb1d550b2e6ca111cDavid Brown            case DISCONNECTING:
8015eff1e7d582679b3a85f580eb1d550b2e6ca111cDavid Brown                retVal = context.getString(R.string.card_title_hanging_up);
8025eff1e7d582679b3a85f580eb1d550b2e6ca111cDavid Brown                break;
8035eff1e7d582679b3a85f580eb1d550b2e6ca111cDavid Brown
804b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case DISCONNECTED:
805b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                retVal = getCallFailedString(call);
806b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
807b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
808b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
809b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("  ==> result: " + retVal);
810b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        return retVal;
811b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
812b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
813b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
814b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates the "on hold" box in the "other call" info area
8150d315275d08cd33f801ae3a74e8fc265520f6246David Brown     * (ie. the stuff in the secondaryCallInfo block)
816b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * based on the specified Call.
817b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Or, clear out the "on hold" box if the specified call
818b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * is null or idle.
819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
8208343169cc89621d46dce86449f5ee1ff5d3a4919John Wang    private void displayOnHoldCallStatus(CallManager cm, Call call) {
821b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("displayOnHoldCallStatus(call =" + call + ")...");
822af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville
823af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville        if ((call == null) || (PhoneApp.getInstance().isOtaCallInActiveState())) {
8240d315275d08cd33f801ae3a74e8fc265520f6246David Brown            mSecondaryCallInfo.setVisibility(View.GONE);
825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            return;
826b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
827b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
8288da4d90151c882972e15429d4d48bdaa45095d72David Brown        boolean showSecondaryCallInfo = false;
829b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Call.State state = call.getState();
830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        switch (state) {
831b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case HOLDING:
832b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Ok, there actually is a background call on hold.
833b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Display the "on hold" box.
834b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
8350d315275d08cd33f801ae3a74e8fc265520f6246David Brown                // Note this case occurs only on GSM devices.  (On CDMA,
8360d315275d08cd33f801ae3a74e8fc265520f6246David Brown                // the "call on hold" is actually the 2nd connection of
8370d315275d08cd33f801ae3a74e8fc265520f6246David Brown                // that ACTIVE call; see the ACTIVE case below.)
8380d315275d08cd33f801ae3a74e8fc265520f6246David Brown
839b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (PhoneUtils.isConferenceCall(call)) {
840b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (DBG) log("==> conference call.");
8410d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    mSecondaryCallName.setText(getContext().getString(R.string.confCall));
8420d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    showImage(mSecondaryCallPhoto, R.drawable.picture_conference);
843b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                } else {
844b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // perform query and update the name temporarily
845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // make sure we hand the textview we want updated to the
846b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // callback function.
847b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (DBG) log("==> NOT a conf call; call startGetCallerInfo...");
8480d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    PhoneUtils.CallerInfoToken infoToken = PhoneUtils.startGetCallerInfo(
8490d315275d08cd33f801ae3a74e8fc265520f6246David Brown                            getContext(), call, this, mSecondaryCallName);
8500d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    mSecondaryCallName.setText(
8510d315275d08cd33f801ae3a74e8fc265520f6246David Brown                            PhoneUtils.getCompactNameFromCallerInfo(infoToken.currentInfo,
8520d315275d08cd33f801ae3a74e8fc265520f6246David Brown                                                                    getContext()));
8530d315275d08cd33f801ae3a74e8fc265520f6246David Brown
8540d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    // Also pull the photo out of the current CallerInfo.
8550d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    // (Note we assume we already have a valid photo at
8560d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    // this point, since *presumably* the caller-id query
8570d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    // was already run at some point *before* this call
8580d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    // got put on hold.  If there's no cached photo, just
8590d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    // fall back to the default "unknown" image.)
8600d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    if (infoToken.isFinal) {
8610d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        showCachedImage(mSecondaryCallPhoto, infoToken.currentInfo);
8620d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    } else {
8630d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        showImage(mSecondaryCallPhoto, R.drawable.picture_unknown);
8640d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    }
865b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
866b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
8678da4d90151c882972e15429d4d48bdaa45095d72David Brown                showSecondaryCallInfo = true;
868b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
869b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
870b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
8710fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            case ACTIVE:
8720fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                // CDMA: This is because in CDMA when the user originates the second call,
8730fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                // although the Foreground call state is still ACTIVE in reality the network
8740fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                // put the first call on hold.
87579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                if (mApplication.phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
8760fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    List<Connection> connections = call.getConnections();
8770fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    if (connections.size() > 2) {
8780fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        // This means that current Mobile Originated call is the not the first 3-Way
8790fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        // call the user is making, which in turn tells the PhoneApp that we no
8800fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        // longer know which previous caller/party had dropped out before the user
8810fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        // made this call.
8820d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        mSecondaryCallName.setText(
8830d315275d08cd33f801ae3a74e8fc265520f6246David Brown                                getContext().getString(R.string.card_title_in_call));
8840d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        showImage(mSecondaryCallPhoto, R.drawable.picture_unknown);
8850fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    } else {
8860fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        // This means that the current Mobile Originated call IS the first 3-Way
8870fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        // and hence we display the first callers/party's info here.
8880fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        Connection conn = call.getEarliestConnection();
889de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                        PhoneUtils.CallerInfoToken infoToken = PhoneUtils.startGetCallerInfo(
8900d315275d08cd33f801ae3a74e8fc265520f6246David Brown                                getContext(), conn, this, mSecondaryCallName);
8910fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
892de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                        // Get the compactName to be displayed, but then check that against
893de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                        // the number presentation value for the call. If it's not an allowed
894de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                        // presentation, then display the appropriate presentation string instead.
895de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                        CallerInfo info = infoToken.currentInfo;
8960d315275d08cd33f801ae3a74e8fc265520f6246David Brown
8970d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        String name = PhoneUtils.getCompactNameFromCallerInfo(info, getContext());
8980d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        boolean forceGenericPhoto = false;
899de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                        if (info != null && info.numberPresentation !=
900de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                                Connection.PRESENTATION_ALLOWED) {
901de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                            name = getPresentationString(info.numberPresentation);
9020d315275d08cd33f801ae3a74e8fc265520f6246David Brown                            forceGenericPhoto = true;
9030d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        }
9040d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        mSecondaryCallName.setText(name);
9050d315275d08cd33f801ae3a74e8fc265520f6246David Brown
9060d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        // Also pull the photo out of the current CallerInfo.
9070d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        // (Note we assume we already have a valid photo at
9080d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        // this point, since *presumably* the caller-id query
9090d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        // was already run at some point *before* this call
9100d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        // got put on hold.  If there's no cached photo, just
9110d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        // fall back to the default "unknown" image.)
9120d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        if (!forceGenericPhoto && infoToken.isFinal) {
9130d315275d08cd33f801ae3a74e8fc265520f6246David Brown                            showCachedImage(mSecondaryCallPhoto, info);
9140d315275d08cd33f801ae3a74e8fc265520f6246David Brown                        } else {
9150d315275d08cd33f801ae3a74e8fc265520f6246David Brown                            showImage(mSecondaryCallPhoto, R.drawable.picture_unknown);
916de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                        }
9170fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    }
9188da4d90151c882972e15429d4d48bdaa45095d72David Brown                    showSecondaryCallInfo = true;
9190fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
9200d315275d08cd33f801ae3a74e8fc265520f6246David Brown                } else {
9210d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    // We shouldn't ever get here at all for non-CDMA devices.
9220d315275d08cd33f801ae3a74e8fc265520f6246David Brown                    Log.w(LOG_TAG, "displayOnHoldCallStatus: ACTIVE state on non-CDMA device");
9238da4d90151c882972e15429d4d48bdaa45095d72David Brown                    showSecondaryCallInfo = false;
9240fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                }
9250fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                break;
9260fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
927b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            default:
928b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // There's actually no call on hold.  (Presumably this call's
929b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // state is IDLE, since any other state is meaningless for the
930b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // background call.)
9318da4d90151c882972e15429d4d48bdaa45095d72David Brown                showSecondaryCallInfo = false;
932b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
933b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
9348da4d90151c882972e15429d4d48bdaa45095d72David Brown
9358da4d90151c882972e15429d4d48bdaa45095d72David Brown        if (showSecondaryCallInfo) {
9368da4d90151c882972e15429d4d48bdaa45095d72David Brown            // Ok, we have something useful to display in the "secondary
9378da4d90151c882972e15429d4d48bdaa45095d72David Brown            // call" info area.
9388da4d90151c882972e15429d4d48bdaa45095d72David Brown            mSecondaryCallInfo.setVisibility(View.VISIBLE);
9398da4d90151c882972e15429d4d48bdaa45095d72David Brown
9408da4d90151c882972e15429d4d48bdaa45095d72David Brown            // Watch out: there are some cases where we need to display the
9418da4d90151c882972e15429d4d48bdaa45095d72David Brown            // secondary call photo but *not* the two lines of text above it.
9428da4d90151c882972e15429d4d48bdaa45095d72David Brown            // Specifically, that's any state where the CallCard "upper title" is
9438da4d90151c882972e15429d4d48bdaa45095d72David Brown            // in use, since the title (e.g. "Dialing" or "Call ended") might
9448da4d90151c882972e15429d4d48bdaa45095d72David Brown            // collide with the secondaryCallStatus and secondaryCallName widgets.
9458da4d90151c882972e15429d4d48bdaa45095d72David Brown            //
9468da4d90151c882972e15429d4d48bdaa45095d72David Brown            // We detect this case by simply seeing whether or not there's any text
9478da4d90151c882972e15429d4d48bdaa45095d72David Brown            // in mUpperTitle.  (This is much simpler than detecting all possible
9488da4d90151c882972e15429d4d48bdaa45095d72David Brown            // telephony states where the "upper title" is used!  But note it does
9498da4d90151c882972e15429d4d48bdaa45095d72David Brown            // rely on the fact that updateCardTitleWidgets() gets called *earlier*
9508da4d90151c882972e15429d4d48bdaa45095d72David Brown            // than this method, in the CallCard.updateState() sequence...)
9518da4d90151c882972e15429d4d48bdaa45095d72David Brown            boolean okToShowLabels = TextUtils.isEmpty(mUpperTitle.getText());
9528da4d90151c882972e15429d4d48bdaa45095d72David Brown            mSecondaryCallName.setVisibility(okToShowLabels ? View.VISIBLE : View.INVISIBLE);
9538da4d90151c882972e15429d4d48bdaa45095d72David Brown            mSecondaryCallStatus.setVisibility(okToShowLabels ? View.VISIBLE : View.INVISIBLE);
9548da4d90151c882972e15429d4d48bdaa45095d72David Brown        } else {
9558da4d90151c882972e15429d4d48bdaa45095d72David Brown            // Hide the entire "secondary call" info area.
9568da4d90151c882972e15429d4d48bdaa45095d72David Brown            mSecondaryCallInfo.setVisibility(View.GONE);
9578da4d90151c882972e15429d4d48bdaa45095d72David Brown        }
958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private String getCallFailedString(Call call) {
961b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Connection c = call.getEarliestConnection();
962b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        int resID;
963b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
964b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (c == null) {
965b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (DBG) log("getCallFailedString: connection is null, using default values.");
966b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // if this connection is null, just assume that the
967b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // default case occurs.
968b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            resID = R.string.card_title_call_ended;
969b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else {
970b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
971b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            Connection.DisconnectCause cause = c.getDisconnectCause();
972b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
973b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // TODO: The card *title* should probably be "Call ended" in all
974b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // cases, but if the DisconnectCause was an error condition we should
975b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // probably also display the specific failure reason somewhere...
976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            switch (cause) {
978b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case BUSY:
979b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    resID = R.string.callFailed_userBusy;
980b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
981b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
982b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case CONGESTION:
983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    resID = R.string.callFailed_congestion;
984b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
985b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
9861d0075e4a480a32e26a673c58b94bd706f997620Hung-ying Tyan                case TIMED_OUT:
9871d0075e4a480a32e26a673c58b94bd706f997620Hung-ying Tyan                    resID = R.string.callFailed_timedOut;
9881d0075e4a480a32e26a673c58b94bd706f997620Hung-ying Tyan                    break;
9891d0075e4a480a32e26a673c58b94bd706f997620Hung-ying Tyan
99068d060b8f52c6c1176d5c55358250b18d14f2b51Hung-ying Tyan                case SERVER_UNREACHABLE:
99168d060b8f52c6c1176d5c55358250b18d14f2b51Hung-ying Tyan                    resID = R.string.callFailed_server_unreachable;
99268d060b8f52c6c1176d5c55358250b18d14f2b51Hung-ying Tyan                    break;
99368d060b8f52c6c1176d5c55358250b18d14f2b51Hung-ying Tyan
9946c17cfbbf0b1b6fed8c9f32da48a854c20c24af8Hung-ying Tyan                case NUMBER_UNREACHABLE:
99568d060b8f52c6c1176d5c55358250b18d14f2b51Hung-ying Tyan                    resID = R.string.callFailed_number_unreachable;
9966c17cfbbf0b1b6fed8c9f32da48a854c20c24af8Hung-ying Tyan                    break;
9976c17cfbbf0b1b6fed8c9f32da48a854c20c24af8Hung-ying Tyan
9983a635c7dd2f3283f6a1bde0e9370977c4685882fHung-ying Tyan                case INVALID_CREDENTIALS:
9993a635c7dd2f3283f6a1bde0e9370977c4685882fHung-ying Tyan                    resID = R.string.callFailed_invalid_credentials;
10003a635c7dd2f3283f6a1bde0e9370977c4685882fHung-ying Tyan                    break;
10013a635c7dd2f3283f6a1bde0e9370977c4685882fHung-ying Tyan
1002a32036470be1cff3ce604c0dd83f0609243c6100Hung-ying Tyan                case SERVER_ERROR:
1003a32036470be1cff3ce604c0dd83f0609243c6100Hung-ying Tyan                    resID = R.string.callFailed_server_error;
1004a32036470be1cff3ce604c0dd83f0609243c6100Hung-ying Tyan                    break;
1005a32036470be1cff3ce604c0dd83f0609243c6100Hung-ying Tyan
10063a635c7dd2f3283f6a1bde0e9370977c4685882fHung-ying Tyan                case OUT_OF_NETWORK:
10073a635c7dd2f3283f6a1bde0e9370977c4685882fHung-ying Tyan                    resID = R.string.callFailed_out_of_network;
10083a635c7dd2f3283f6a1bde0e9370977c4685882fHung-ying Tyan                    break;
10093a635c7dd2f3283f6a1bde0e9370977c4685882fHung-ying Tyan
1010b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case LOST_SIGNAL:
10113800ac871d6548790ac6119bb68b9be0640af261David Krause                case CDMA_DROP:
1012b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    resID = R.string.callFailed_noSignal;
1013b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1014b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1015b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case LIMIT_EXCEEDED:
1016b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    resID = R.string.callFailed_limitExceeded;
1017b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1018b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case POWER_OFF:
1020b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    resID = R.string.callFailed_powerOff;
1021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1023a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville                case ICC_ERROR:
1024b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    resID = R.string.callFailed_simError;
1025b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1026b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1027b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case OUT_OF_SERVICE:
1028b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    resID = R.string.callFailed_outOfService;
1029b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1030b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
103122e353c3d76a3dd649c6e87244c5d94cadf64c8eHung-ying Tyan                case INVALID_NUMBER:
10329eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                case UNOBTAINABLE_NUMBER:
10339eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                    resID = R.string.callFailed_unobtainable_number;
10349eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                    break;
10359eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla
1036b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                default:
1037b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    resID = R.string.card_title_call_ended;
1038b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1039b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1040b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1041b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        return getContext().getString(resID);
1042b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1043b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1044b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1045b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates the name / photo / number / label fields on the CallCard
1046b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * based on the specified CallerInfo.
1047b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
1048b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * If the current call is a conference call, use
1049b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * updateDisplayForConference() instead.
1050b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1051b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void updateDisplayForPerson(CallerInfo info,
10524b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project                                        int presentation,
1053b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                                        boolean isTemporary,
1054b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                                        Call call) {
1055a1c2398ade0e01d0bcfe23212bdaa18e4c19a1e5Nicolas Catania        if (DBG) log("updateDisplayForPerson(" + info + ")\npresentation:" +
1056a1c2398ade0e01d0bcfe23212bdaa18e4c19a1e5Nicolas Catania                     presentation + " isTemporary:" + isTemporary);
1057b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1058b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // inform the state machine that we are displaying a photo.
1059b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mPhotoTracker.setPhotoRequest(info);
1060b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mPhotoTracker.setPhotoState(ContactsAsyncHelper.ImageTracker.DISPLAY_IMAGE);
1061b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1062592fb0a9a5b079f168096907bd50822f94c69448David Brown        // The actual strings we're going to display onscreen:
1063592fb0a9a5b079f168096907bd50822f94c69448David Brown        String displayName;
1064b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        String displayNumber = null;
1065b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        String label = null;
1066b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Uri personUri = null;
106729d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        String socialStatusText = null;
106829d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        Drawable socialStatusBadge = null;
1069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (info != null) {
1071b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // It appears that there is a small change in behaviour with the
1072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // PhoneUtils' startGetCallerInfo whereby if we query with an
1073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // empty number, we will get a valid CallerInfo object, but with
1074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // fields that are all null, and the isTemporary boolean input
1075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // parameter as true.
1076b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1077b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // In the past, we would see a NULL callerinfo object, but this
1078b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // ends up causing null pointer exceptions elsewhere down the
1079b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // line in other cases, so we need to make this fix instead. It
1080b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // appears that this was the ONLY call to PhoneUtils
1081b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // .getCallerInfo() that relied on a NULL CallerInfo to indicate
1082b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // an unknown contact.
1083b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1084592fb0a9a5b079f168096907bd50822f94c69448David Brown            // Currently, info.phoneNumber may actually be a SIP address, and
1085592fb0a9a5b079f168096907bd50822f94c69448David Brown            // if so, it might sometimes include the "sip:" prefix.  That
1086592fb0a9a5b079f168096907bd50822f94c69448David Brown            // prefix isn't really useful to the user, though, so strip it off
1087592fb0a9a5b079f168096907bd50822f94c69448David Brown            // if present.  (For any other URI scheme, though, leave the
1088592fb0a9a5b079f168096907bd50822f94c69448David Brown            // prefix alone.)
1089592fb0a9a5b079f168096907bd50822f94c69448David Brown            // TODO: It would be cleaner for CallerInfo to explicitly support
1090592fb0a9a5b079f168096907bd50822f94c69448David Brown            // SIP addresses instead of overloading the "phoneNumber" field.
1091592fb0a9a5b079f168096907bd50822f94c69448David Brown            // Then we could remove this hack, and instead ask the CallerInfo
1092592fb0a9a5b079f168096907bd50822f94c69448David Brown            // for a "user visible" form of the SIP address.
1093592fb0a9a5b079f168096907bd50822f94c69448David Brown            String number = info.phoneNumber;
10949ec000a412524ed98d486ca4b160dd1e885db574David Brown            if ((number != null) && number.startsWith("sip:")) {
1095592fb0a9a5b079f168096907bd50822f94c69448David Brown                number = number.substring(4);
1096592fb0a9a5b079f168096907bd50822f94c69448David Brown            }
1097592fb0a9a5b079f168096907bd50822f94c69448David Brown
1098b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (TextUtils.isEmpty(info.name)) {
1099592fb0a9a5b079f168096907bd50822f94c69448David Brown                // No valid "name" in the CallerInfo, so fall back to
1100592fb0a9a5b079f168096907bd50822f94c69448David Brown                // something else.
1101a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                // (Typically, we promote the phone number up to the "name" slot
1102a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                // onscreen, and possibly display a descriptive string in the
1103a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                // "number" slot.)
1104592fb0a9a5b079f168096907bd50822f94c69448David Brown                if (TextUtils.isEmpty(number)) {
1105a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    // No name *or* number!  Display a generic "unknown" string
1106a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    // (or potentially some other default based on the presentation.)
1107592fb0a9a5b079f168096907bd50822f94c69448David Brown                    displayName =  getPresentationString(presentation);
1108a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    if (DBG) log("  ==> no name *or* number! displayName = " + displayName);
1109e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                } else if (presentation != Connection.PRESENTATION_ALLOWED) {
1110e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    // This case should never happen since the network should never send a phone #
1111e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    // AND a restricted presentation. However we leave it here in case of weird
1112e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    // network behavior
1113592fb0a9a5b079f168096907bd50822f94c69448David Brown                    displayName = getPresentationString(presentation);
1114a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    if (DBG) log("  ==> presentation not allowed! displayName = " + displayName);
1115e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                } else if (!TextUtils.isEmpty(info.cnapName)) {
1116a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    // No name, but we do have a valid CNAP name, so use that.
1117592fb0a9a5b079f168096907bd50822f94c69448David Brown                    displayName = info.cnapName;
1118e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    info.name = info.cnapName;
1119592fb0a9a5b079f168096907bd50822f94c69448David Brown                    displayNumber = number;
1120a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    if (DBG) log("  ==> cnapName available: displayName '"
1121a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                                 + displayName + "', displayNumber '" + displayNumber + "'");
1122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                } else {
1123a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    // No name; all we have is a number.  This is the typical
1124a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    // case when an incoming call doesn't match any contact.
1125a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown
1126a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    // Promote the phone number up to the "name" slot, and use
1127a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    // the "number" slot for a geographical description string
1128a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    // if available.
1129592fb0a9a5b079f168096907bd50822f94c69448David Brown                    displayName = number;
1130a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    displayNumber = info.geoDescription;  // may be null
1131a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    if (DBG) log("  ==>  no name; falling back to number: displayName '"
1132a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                                 + displayName + "', displayNumber '" + displayNumber + "'");
1133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
1134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            } else {
1135592fb0a9a5b079f168096907bd50822f94c69448David Brown                // We do have a valid "name" in the CallerInfo.  Display that
1136592fb0a9a5b079f168096907bd50822f94c69448David Brown                // in the "name" slot, and the phone number in the "number" slot.
1137e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                if (presentation != Connection.PRESENTATION_ALLOWED) {
1138e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    // This case should never happen since the network should never send a name
1139e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    // AND a restricted presentation. However we leave it here in case of weird
1140e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    // network behavior
1141592fb0a9a5b079f168096907bd50822f94c69448David Brown                    displayName = getPresentationString(presentation);
1142a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    if (DBG) log("  ==> valid name, but presentation not allowed!"
1143a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                                 + " displayName = " + displayName);
1144e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                } else {
1145592fb0a9a5b079f168096907bd50822f94c69448David Brown                    displayName = info.name;
1146592fb0a9a5b079f168096907bd50822f94c69448David Brown                    displayNumber = number;
1147e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                    label = info.phoneLabel;
1148a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                    if (DBG) log("  ==>  name is present in CallerInfo: displayName '"
1149a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown                                 + displayName + "', displayNumber '" + displayNumber + "'");
1150e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai                }
1151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
11523d6d70562622660e581b53308e675386d299dd19Dmitri Plotnikov            personUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, info.person_id);
115302d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown            if (DBG) log("- got personUri: '" + personUri
115402d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown                         + "', based on info.person_id: " + info.person_id);
1155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else {
1156592fb0a9a5b079f168096907bd50822f94c69448David Brown            displayName =  getPresentationString(presentation);
1157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
11580fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
11590fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        if (call.isGeneric()) {
11600fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            mName.setText(R.string.card_title_in_call);
11610fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        } else {
1162592fb0a9a5b079f168096907bd50822f94c69448David Brown            mName.setText(displayName);
11630fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
1164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mName.setVisibility(View.VISIBLE);
1165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Update mPhoto
1167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // if the temporary flag is set, we know we'll be getting another call after
1168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // the CallerInfo has been correctly updated.  So, we can skip the image
1169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // loading until then.
1170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // If the photoResource is filled in for the CallerInfo, (like with the
1172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Emergency Number case), then we can just set the photo image without
1173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // requesting for an image load. Please refer to CallerInfoAsyncQuery.java
1174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // for cases where CallerInfo.photoResource may be set.  We can also avoid
1175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // the image load step if the image data is cached.
1176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (isTemporary && (info == null || !info.isCachedPhotoCurrent)) {
1177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mPhoto.setVisibility(View.INVISIBLE);
1178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else if (info != null && info.photoResource != 0){
1179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            showImage(mPhoto, info.photoResource);
1180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else if (!showCachedImage(mPhoto, info)) {
1181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Load the image with a callback to update the image state.
1182a1c2398ade0e01d0bcfe23212bdaa18e4c19a1e5Nicolas Catania            // Use the default unknown picture while the query is running.
1183a1c2398ade0e01d0bcfe23212bdaa18e4c19a1e5Nicolas Catania            ContactsAsyncHelper.updateImageViewWithContactPhotoAsync(
1184a1c2398ade0e01d0bcfe23212bdaa18e4c19a1e5Nicolas Catania                info, 0, this, call, getContext(), mPhoto, personUri, R.drawable.picture_unknown);
1185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
11866d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        // And no matter what, on all devices, we never see the "manage
11876d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        // conference" button in this state.
11886d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        mManageConferencePhotoButton.setVisibility(View.INVISIBLE);
11896d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown
11900fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        if (displayNumber != null && !call.isGeneric()) {
1191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mPhoneNumber.setText(displayNumber);
11929688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown            mPhoneNumber.setTextColor(mTextColorDefaultSecondary);
1193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mPhoneNumber.setVisibility(View.VISIBLE);
1194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else {
1195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mPhoneNumber.setVisibility(View.GONE);
1196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1198153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman        if (label != null && !call.isGeneric()) {
1199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mLabel.setText(label);
1200b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mLabel.setVisibility(View.VISIBLE);
1201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else {
1202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mLabel.setVisibility(View.GONE);
1203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
12059d14e16e8214b4a396dad293b6f0941608ee4798David Brown        // Other text fields:
12069d14e16e8214b4a396dad293b6f0941608ee4798David Brown        updateCallTypeLabel(call);
12079d14e16e8214b4a396dad293b6f0941608ee4798David Brown        updateSocialStatus(socialStatusText, socialStatusBadge, call);  // Currently unused
120829d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown    }
1209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
12104b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project    private String getPresentationString(int presentation) {
12114b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        String name = getContext().getString(R.string.unknown);
12124b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        if (presentation == Connection.PRESENTATION_RESTRICTED) {
12134b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project            name = getContext().getString(R.string.private_num);
12144b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        } else if (presentation == Connection.PRESENTATION_PAYPHONE) {
12154b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project            name = getContext().getString(R.string.payphone);
12164b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        }
12174b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        return name;
12184b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project    }
12194b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project
1220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates the name / photo / number / label fields
1222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * for the special "conference call" state.
1223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
1224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * If the current call has only a single connection, use
1225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * updateDisplayForPerson() instead.
1226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1227872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan    private void updateDisplayForConference(Call call) {
1228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("updateDisplayForConference()...");
1229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1230872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        int phoneType = call.getPhone().getPhoneType();
123179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink        if (phoneType == Phone.PHONE_TYPE_CDMA) {
12320fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            // This state corresponds to both 3-Way merged call and
12330fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            // Call Waiting accepted call.
123429d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown            // In this case we display the UI in a "generic" state, with
123529d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown            // the generic "dialing" icon and no caller information,
123629d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown            // because in this state in CDMA the user does not really know
123729d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown            // which caller party he is talking to.
12380fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            showImage(mPhoto, R.drawable.picture_dialing);
12390fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            mName.setText(R.string.card_title_in_call);
1240872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        } else if ((phoneType == Phone.PHONE_TYPE_GSM)
1241872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                || (phoneType == Phone.PHONE_TYPE_SIP)) {
12426d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown            if (mInCallScreen.isTouchUiEnabled()) {
12436d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                // Display the "manage conference" button in place of the photo.
12446d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                mManageConferencePhotoButton.setVisibility(View.VISIBLE);
12456d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                mPhoto.setVisibility(View.INVISIBLE);  // Not GONE, since that would break
12466d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                                                       // other views in our RelativeLayout.
12476d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown            } else {
12486d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                // Display the "conference call" image in the photo slot,
12496d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                // with no other information.
12506d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                showImage(mPhoto, R.drawable.picture_conference);
12516d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown            }
12520fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            mName.setText(R.string.card_title_conf_call);
125379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink        } else {
125479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink            throw new IllegalStateException("Unexpected phone type: " + phoneType);
12550fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
1256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mName.setVisibility(View.VISIBLE);
1258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // TODO: For a conference call, the "phone number" slot is specced
1260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // to contain a summary of who's on the call, like "Bill Foldes
1261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // and Hazel Nutt" or "Bill Foldes and 2 others".
1262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // But for now, just hide it:
1263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mPhoneNumber.setVisibility(View.GONE);
1264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mLabel.setVisibility(View.GONE);
1265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
12669d14e16e8214b4a396dad293b6f0941608ee4798David Brown        // Other text fields:
12679d14e16e8214b4a396dad293b6f0941608ee4798David Brown        updateCallTypeLabel(call);
12689d14e16e8214b4a396dad293b6f0941608ee4798David Brown        updateSocialStatus(null, null, null);  // socialStatus is never visible in this state
126929d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown
127029d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        // TODO: for a GSM conference call, since we do actually know who
127129d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        // you're talking to, consider also showing names / numbers /
127229d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        // photos of some of the people on the conference here, so you can
127329d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        // see that info without having to click "Manage conference".  We
127429d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        // probably have enough space to show info for 2 people, at least.
1275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        //
1276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // To do this, our caller would pass us the activeConnections
1277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // list, and we'd call PhoneUtils.getCallerInfo() separately for
1278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // each connection.
1279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Updates the CallCard "photo" IFF the specified Call is in a state
1283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * that needs a special photo (like "busy" or "dialing".)
1284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
1285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * If the current call does not require a special image in the "photo"
1286b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * slot onscreen, don't do anything, since presumably the photo image
1287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * has already been set (to the photo of the person we're talking, or
1288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * the generic "picture_unknown" image, or the "conference call"
1289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * image.)
1290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void updatePhotoForCallState(Call call) {
1292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("updatePhotoForCallState(" + call + ")...");
1293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        int photoImageResource = 0;
1294b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Check for the (relatively few) telephony states that need a
1296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // special image in the "photo" slot.
1297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Call.State state = call.getState();
1298b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        switch (state) {
1299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case DISCONNECTED:
1300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Display the special "busy" photo for BUSY or CONGESTION.
1301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Otherwise (presumably the normal "call ended" state)
1302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // leave the photo alone.
1303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                Connection c = call.getEarliestConnection();
1304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // if the connection is null, we assume the default case,
1305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // otherwise update the image resource normally.
1306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (c != null) {
1307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    Connection.DisconnectCause cause = c.getDisconnectCause();
1308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if ((cause == Connection.DisconnectCause.BUSY)
1309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        || (cause == Connection.DisconnectCause.CONGESTION)) {
1310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        photoImageResource = R.drawable.picture_busy;
1311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    }
1312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                } else if (DBG) {
1313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    log("updatePhotoForCallState: connection is null, ignoring.");
1314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
1315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // TODO: add special images for any other DisconnectCauses?
1317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
1318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case ALERTING:
132044e42e4eccd8ecdcdcca166c9f6f35a4d6c65591Nicolas Catania            case DIALING:
1321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            default:
1322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Leave the photo alone in all other states.
1323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // If this call is an individual call, and the image is currently
1324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // displaying a state, (rather than a photo), we'll need to update
1325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // the image.
1326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // This is for the case where we've been displaying the state and
1327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // now we need to restore the photo.  This can happen because we
1328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // only query the CallerInfo once, and limit the number of times
1329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // the image is loaded. (So a state image may overwrite the photo
1330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // and we would otherwise have no way of displaying the photo when
1331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // the state goes away.)
1332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // if the photoResource field is filled-in in the Connection's
1334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // caller info, then we can just use that instead of requesting
1335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // for a photo load.
1336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // look for the photoResource if it is available.
1338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                CallerInfo ci = null;
1339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                {
13400fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    Connection conn = null;
1341872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                    int phoneType = call.getPhone().getPhoneType();
134279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                    if (phoneType == Phone.PHONE_TYPE_CDMA) {
13430fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        conn = call.getLatestConnection();
1344872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                    } else if ((phoneType == Phone.PHONE_TYPE_GSM)
1345872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                            || (phoneType == Phone.PHONE_TYPE_SIP)) {
13460fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                        conn = call.getEarliestConnection();
134779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                    } else {
134879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
13490fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    }
13500fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
1351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (conn != null) {
1352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        Object o = conn.getUserData();
1353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        if (o instanceof CallerInfo) {
1354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                            ci = (CallerInfo) o;
1355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        } else if (o instanceof PhoneUtils.CallerInfoToken) {
1356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                            ci = ((PhoneUtils.CallerInfoToken) o).currentInfo;
1357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        }
1358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    }
1359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
1360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (ci != null) {
1362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    photoImageResource = ci.photoResource;
1363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
1364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // If no photoResource found, check to see if this is a conference call. If
1366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // it is not a conference call:
1367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                //   1. Try to show the cached image
1368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                //   2. If the image is not cached, check to see if a load request has been
1369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                //      made already.
1370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                //   3. If the load request has not been made [DISPLAY_DEFAULT], start the
1371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                //      request and note that it has started by updating photo state with
1372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                //      [DISPLAY_IMAGE].
1373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Load requests started in (3) use a placeholder image of -1 to hide the
1374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // image by default.  Please refer to CallerInfoAsyncQuery.java for cases
1375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // where CallerInfo.photoResource may be set.
1376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (photoImageResource == 0) {
1377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (!PhoneUtils.isConferenceCall(call)) {
1378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        if (!showCachedImage(mPhoto, ci) && (mPhotoTracker.getPhotoState() ==
1379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                                ContactsAsyncHelper.ImageTracker.DISPLAY_DEFAULT)) {
1380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                            ContactsAsyncHelper.updateImageViewWithContactPhotoAsync(ci,
1381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                                    getContext(), mPhoto, mPhotoTracker.getPhotoUri(), -1);
1382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                            mPhotoTracker.setPhotoState(
1383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                                    ContactsAsyncHelper.ImageTracker.DISPLAY_IMAGE);
1384b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        }
1385b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    }
1386b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                } else {
1387b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    showImage(mPhoto, photoImageResource);
1388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    mPhotoTracker.setPhotoState(ContactsAsyncHelper.ImageTracker.DISPLAY_IMAGE);
1389b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    return;
1390b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
1391b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
1392b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1393b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1394b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (photoImageResource != 0) {
1395b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (DBG) log("- overrriding photo image: " + photoImageResource);
1396b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            showImage(mPhoto, photoImageResource);
1397b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Track the image state.
1398b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mPhotoTracker.setPhotoState(ContactsAsyncHelper.ImageTracker.DISPLAY_DEFAULT);
1399b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1400b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1401b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1402b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1403b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Try to display the cached image from the callerinfo object.
1404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
1405b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *  @return true if we were able to find the image in the cache, false otherwise.
1406b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
14070d315275d08cd33f801ae3a74e8fc265520f6246David Brown    private static final boolean showCachedImage(ImageView view, CallerInfo ci) {
1408b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if ((ci != null) && ci.isCachedPhotoCurrent) {
1409b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (ci.cachedPhoto != null) {
1410b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                showImage(view, ci.cachedPhoto);
1411b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            } else {
1412b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                showImage(view, R.drawable.picture_unknown);
1413b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1414b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            return true;
1415b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1416b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        return false;
1417b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1418b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1419b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /** Helper function to display the resource in the imageview AND ensure its visibility.*/
1420b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final void showImage(ImageView view, int resource) {
1421b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        view.setImageResource(resource);
1422b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        view.setVisibility(View.VISIBLE);
1423b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1424b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1425b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /** Helper function to display the drawable in the imageview AND ensure its visibility.*/
1426b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final void showImage(ImageView view, Drawable drawable) {
1427b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        view.setImageDrawable(drawable);
1428b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        view.setVisibility(View.VISIBLE);
1429b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1430b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1431b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1432b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Returns the "Menu button hint" TextView (which is manipulated
1433b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * directly by the InCallScreen.)
1434b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * @see InCallScreen.updateMenuButtonHint()
1435b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1436b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /* package */ TextView getMenuButtonHint() {
1437b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        return mMenuButtonHint;
1438b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1439b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1440b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1441b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Sets the left and right margins of the specified ViewGroup (whose
1442b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * LayoutParams object which must inherit from
1443b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * ViewGroup.MarginLayoutParams.)
1444b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
1445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * TODO: Is there already a convenience method like this somewhere?
1446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1447b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void setSideMargins(ViewGroup vg, int margin) {
1448b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        ViewGroup.MarginLayoutParams lp =
1449b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                (ViewGroup.MarginLayoutParams) vg.getLayoutParams();
1450b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Equivalent to setting android:layout_marginLeft/Right in XML
1451b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        lp.leftMargin = margin;
1452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        lp.rightMargin = margin;
1453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        vg.setLayoutParams(lp);
1454b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1455b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
14568bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project    /**
14578bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project     * Sets the CallCard "upper title".  Also, depending on the passed-in
14588bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project     * Call state, possibly display an icon along with the title.
14598bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project     */
146034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown    private void setUpperTitle(String title, int color, Call.State state) {
14618bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project        mUpperTitle.setText(title);
146234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown        mUpperTitle.setTextColor(color);
14638bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project
14648bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project        int bluetoothIconId = 0;
146534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown        if (!TextUtils.isEmpty(title)
146634a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown                && ((state == Call.State.INCOMING) || (state == Call.State.WAITING))
14670fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                && mApplication.showBluetoothIndication()) {
14688bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project            // Display the special bluetooth icon also, if this is an incoming
14698bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project            // call and the audio will be routed to bluetooth.
14708bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project            bluetoothIconId = R.drawable.ic_incoming_call_bluetooth;
14718bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project        }
14728bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project
14738bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project        mUpperTitle.setCompoundDrawablesWithIntrinsicBounds(bluetoothIconId, 0, 0, 0);
147429d71cebdbcfe433f851899b91a650ad9352c15fDavid Brown        if (bluetoothIconId != 0) mUpperTitle.setCompoundDrawablePadding((int) (mDensity * 5));
14758bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project    }
14768bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project
1477af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville    /**
147834a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown     * Clears the CallCard "upper title", for states (like a normal
147934a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown     * ongoing call) where we don't use any "title" at all.
148034a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown     */
148134a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown    private void clearUpperTitle() {
148234a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown        setUpperTitle("", 0, Call.State.IDLE);  // Use dummy values for "color" and "state"
148334a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown    }
148434a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown
148534a38b7ed4a63f8e6264030735911fdeadb21e5cDavid Brown    /**
1486f3602b0659d01fef19159e7111be76102549f7a1David Brown     * Returns the special card title used in emergency callback mode (ECM),
1487f3602b0659d01fef19159e7111be76102549f7a1David Brown     * which shows your own phone number.
1488f3602b0659d01fef19159e7111be76102549f7a1David Brown     */
1489f3602b0659d01fef19159e7111be76102549f7a1David Brown    private String getECMCardTitle(Context context, Phone phone) {
1490f3602b0659d01fef19159e7111be76102549f7a1David Brown        String rawNumber = phone.getLine1Number();  // may be null or empty
1491f3602b0659d01fef19159e7111be76102549f7a1David Brown        String formattedNumber;
1492f3602b0659d01fef19159e7111be76102549f7a1David Brown        if (!TextUtils.isEmpty(rawNumber)) {
1493f3602b0659d01fef19159e7111be76102549f7a1David Brown            formattedNumber = PhoneNumberUtils.formatNumber(rawNumber);
1494f3602b0659d01fef19159e7111be76102549f7a1David Brown        } else {
1495f3602b0659d01fef19159e7111be76102549f7a1David Brown            formattedNumber = context.getString(R.string.unknown);
1496f3602b0659d01fef19159e7111be76102549f7a1David Brown        }
1497f3602b0659d01fef19159e7111be76102549f7a1David Brown        String titleFormat = context.getString(R.string.card_title_my_phone_number);
1498f3602b0659d01fef19159e7111be76102549f7a1David Brown        return String.format(titleFormat, formattedNumber);
1499f3602b0659d01fef19159e7111be76102549f7a1David Brown    }
1500f3602b0659d01fef19159e7111be76102549f7a1David Brown
1501f3602b0659d01fef19159e7111be76102549f7a1David Brown    /**
15029d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * Updates the "Call type" label, based on the current foreground call.
15039d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * This is a special label and/or branding we display for certain
15049d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * kinds of calls.
15059d14e16e8214b4a396dad293b6f0941608ee4798David Brown     *
15069d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * (So far, this is used only for SIP calls, which get an
15079d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * "Internet call" label.  TODO: But eventually, the telephony
15089d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * layer might allow each pluggable "provider" to specify a string
15099d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * and/or icon to be displayed here.)
15109d14e16e8214b4a396dad293b6f0941608ee4798David Brown     */
15119d14e16e8214b4a396dad293b6f0941608ee4798David Brown    private void updateCallTypeLabel(Call call) {
15129d14e16e8214b4a396dad293b6f0941608ee4798David Brown        int phoneType = (call != null) ? call.getPhone().getPhoneType() : Phone.PHONE_TYPE_NONE;
15139d14e16e8214b4a396dad293b6f0941608ee4798David Brown        if (phoneType == Phone.PHONE_TYPE_SIP) {
15149d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mCallTypeLabel.setVisibility(View.VISIBLE);
15159d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mCallTypeLabel.setText(R.string.incall_call_type_label_sip);
15169d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mCallTypeLabel.setTextColor(mTextColorCallTypeSip);
15179d14e16e8214b4a396dad293b6f0941608ee4798David Brown            // If desired, we could also display a "badge" next to the label, as follows:
15189d14e16e8214b4a396dad293b6f0941608ee4798David Brown            //   mCallTypeLabel.setCompoundDrawablesWithIntrinsicBounds(
15199d14e16e8214b4a396dad293b6f0941608ee4798David Brown            //           callTypeSpecificBadge, null, null, null);
15209d14e16e8214b4a396dad293b6f0941608ee4798David Brown            //   mCallTypeLabel.setCompoundDrawablePadding((int) (mDensity * 6));
15219d14e16e8214b4a396dad293b6f0941608ee4798David Brown        } else {
15229d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mCallTypeLabel.setVisibility(View.GONE);
15239d14e16e8214b4a396dad293b6f0941608ee4798David Brown        }
15249d14e16e8214b4a396dad293b6f0941608ee4798David Brown    }
15259d14e16e8214b4a396dad293b6f0941608ee4798David Brown
15269d14e16e8214b4a396dad293b6f0941608ee4798David Brown    /**
15279d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * Updates the "social status" label with the specified text and
15289d14e16e8214b4a396dad293b6f0941608ee4798David Brown     * (optional) badge.
15299d14e16e8214b4a396dad293b6f0941608ee4798David Brown     */
15309d14e16e8214b4a396dad293b6f0941608ee4798David Brown    private void updateSocialStatus(String socialStatusText,
15319d14e16e8214b4a396dad293b6f0941608ee4798David Brown                                    Drawable socialStatusBadge,
15329d14e16e8214b4a396dad293b6f0941608ee4798David Brown                                    Call call) {
15339d14e16e8214b4a396dad293b6f0941608ee4798David Brown        // The socialStatus field is *only* visible while an incoming call
15349d14e16e8214b4a396dad293b6f0941608ee4798David Brown        // is ringing, never in any other call state.
15359d14e16e8214b4a396dad293b6f0941608ee4798David Brown        if ((socialStatusText != null)
15369d14e16e8214b4a396dad293b6f0941608ee4798David Brown                && (call != null)
15379d14e16e8214b4a396dad293b6f0941608ee4798David Brown                && call.isRinging()
15389d14e16e8214b4a396dad293b6f0941608ee4798David Brown                && !call.isGeneric()) {
15399d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mSocialStatus.setVisibility(View.VISIBLE);
15409d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mSocialStatus.setText(socialStatusText);
15419d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mSocialStatus.setCompoundDrawablesWithIntrinsicBounds(
15429d14e16e8214b4a396dad293b6f0941608ee4798David Brown                    socialStatusBadge, null, null, null);
15439d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mSocialStatus.setCompoundDrawablePadding((int) (mDensity * 6));
15449d14e16e8214b4a396dad293b6f0941608ee4798David Brown        } else {
15459d14e16e8214b4a396dad293b6f0941608ee4798David Brown            mSocialStatus.setVisibility(View.GONE);
15469d14e16e8214b4a396dad293b6f0941608ee4798David Brown        }
15479d14e16e8214b4a396dad293b6f0941608ee4798David Brown    }
15489d14e16e8214b4a396dad293b6f0941608ee4798David Brown
15499d14e16e8214b4a396dad293b6f0941608ee4798David Brown    /**
1550af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * Hides the top-level UI elements of the call card:  The "main
1551af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * call card" element representing the current active or ringing call,
1552af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * and also the info areas for "ongoing" or "on hold" calls in some
1553af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * states.
1554af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     *
1555af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * This is intended to be used in special states where the normal
1556af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * in-call UI is totally replaced by some other UI, like OTA mode on a
1557af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * CDMA device.
1558af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     *
1559af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * To bring back the regular CallCard UI, just re-run the normal
1560af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     * updateState() call sequence.
1561af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville     */
1562af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville    public void hideCallCardElements() {
15630d315275d08cd33f801ae3a74e8fc265520f6246David Brown        mPrimaryCallInfo.setVisibility(View.GONE);
15640d315275d08cd33f801ae3a74e8fc265520f6246David Brown        mSecondaryCallInfo.setVisibility(View.GONE);
1565af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville    }
1566b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
15679688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown    /*
15689688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown     * Updates the hint (like "Rotate to answer") that we display while
15699688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown     * the user is dragging the incoming call RotarySelector widget.
15709688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown     */
1571ea505da2d0ebae37b07fece15297b5432fe96c5dJim Miller    /* package */ void setIncomingCallWidgetHint(int hintTextResId, int hintColorResId) {
1572ea505da2d0ebae37b07fece15297b5432fe96c5dJim Miller        mIncomingCallWidgetHintTextResId = hintTextResId;
1573ea505da2d0ebae37b07fece15297b5432fe96c5dJim Miller        mIncomingCallWidgetHintColorResId = hintColorResId;
15749688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown    }
15759688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown
15766d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown    // View.OnClickListener implementation
15776d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown    public void onClick(View view) {
15786d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        int id = view.getId();
15796d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        if (DBG) log("onClick(View " + view + ", id " + id + ")...");
15806d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown
15816d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        switch (id) {
15826d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown            case R.id.manageConferencePhotoButton:
15836d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                // A click on anything here gets forwarded
15846d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                // straight to the InCallScreen.
15856d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                mInCallScreen.handleOnscreenButtonClick(id);
15866d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                break;
15876d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown
15886d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown            default:
15896d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                Log.w(LOG_TAG, "onClick: unexpected click: View " + view + ", id " + id);
15906d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown                break;
15916d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown        }
15926d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown    }
15936d5544932495d81ff7ce53f4678c4beb25acc1b0David Brown
1594dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    // Accessibility event support.
1595dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    // Since none of the CallCard elements are focusable, we need to manually
1596dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    // fill in the AccessibilityEvent here (so that the name / number / etc will
1597dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    // get pronounced by a screen reader, for example.)
1598dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    @Override
1599dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
1600dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mUpperTitle);
1601dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mPhoto);
1602dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mManageConferencePhotoButton);
1603dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mName);
1604dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mPhoneNumber);
1605dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mLabel);
1606dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mSocialStatus);
1607dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mSecondaryCallName);
1608dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mSecondaryCallStatus);
1609dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        dispatchPopulateAccessibilityEvent(event, mSecondaryCallPhoto);
1610dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        return true;
1611dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    }
1612dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown
1613dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    private void dispatchPopulateAccessibilityEvent(AccessibilityEvent event, View view) {
1614dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        List<CharSequence> eventText = event.getText();
1615dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        int size = eventText.size();
1616dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        view.dispatchPopulateAccessibilityEvent(event);
1617dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        // if no text added write null to keep relative position
1618dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        if (size == eventText.size()) {
1619dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown            eventText.add(null);
1620dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown        }
1621dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown    }
1622dc66301e77d854b6cef2101bf7029c9bbb816f3eDavid Brown
16239688349b8750a9ac7282d83993e0112c5f51e7acDavid Brown
1624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // Debugging / testing code
1625b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1626b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void log(String msg) {
1627796c70c99bc39295bf685061056f06ab8949c742David Brown        Log.d(LOG_TAG, msg);
1628b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project}
1630