diff options
Diffstat (limited to 'src/com/android/phone/ManageConferenceUtils.java')
-rw-r--r-- | src/com/android/phone/ManageConferenceUtils.java | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/src/com/android/phone/ManageConferenceUtils.java b/src/com/android/phone/ManageConferenceUtils.java new file mode 100644 index 00000000..5821754f --- /dev/null +++ b/src/com/android/phone/ManageConferenceUtils.java @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.phone; + +import android.os.SystemProperties; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewStub; +import android.widget.Button; +import android.widget.Chronometer; +import android.widget.ImageButton; +import android.widget.TextView; + +import com.android.internal.telephony.CallerInfo; +import com.android.internal.telephony.CallerInfoAsyncQuery; +import com.android.internal.telephony.CallManager; +import com.android.internal.telephony.Connection; + +import java.util.List; + + +/** + * Helper class to initialize and run the InCallScreen's "Manage conference" UI. + */ +public class ManageConferenceUtils { + private static final String LOG_TAG = "ManageConferenceUtils"; + private static final boolean DBG = + (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1); + + /** + * CallerInfoAsyncQuery.OnQueryCompleteListener implementation. + * + * This object listens for results from the caller-id info queries we + * fire off in updateManageConferenceRow(), and updates the + * corresponding conference row. + */ + private final class QueryCompleteListener + implements CallerInfoAsyncQuery.OnQueryCompleteListener { + private final int mConferencCallListIndex; + + public QueryCompleteListener(int index) { + mConferencCallListIndex = index; + } + + @Override + public void onQueryComplete(int token, Object cookie, CallerInfo ci) { + if (DBG) log("callerinfo query complete, updating UI." + ci); + + Connection connection = (Connection) cookie; + int presentation = connection.getNumberPresentation(); + + // get the viewgroup (conference call list item) and make it visible + ViewGroup viewGroup = mConferenceCallList[mConferencCallListIndex]; + viewGroup.setVisibility(View.VISIBLE); + + // update the list item with this information. + displayCallerInfoForConferenceRow(ci, presentation, + (TextView) viewGroup.findViewById(R.id.conferenceCallerName), + (TextView) viewGroup.findViewById(R.id.conferenceCallerNumberType), + (TextView) viewGroup.findViewById(R.id.conferenceCallerNumber)); + } + } + + private InCallScreen mInCallScreen; + private CallManager mCM; + + // "Manage conference" UI elements and state + private ViewGroup mManageConferencePanel; + private View mButtonManageConferenceDone; + private ViewGroup[] mConferenceCallList; + private int mNumCallersInConference; + private Chronometer mConferenceTime; + + // See CallTracker.MAX_CONNECTIONS_PER_CALL + private static final int MAX_CALLERS_IN_CONFERENCE = 5; + + public ManageConferenceUtils(InCallScreen inCallScreen, CallManager cm) { + if (DBG) log("ManageConferenceUtils constructor..."); + mInCallScreen = inCallScreen; + mCM = cm; + } + + public void initManageConferencePanel() { + if (DBG) log("initManageConferencePanel()..."); + if (mManageConferencePanel == null) { + if (DBG) log("initManageConferencePanel: first-time initialization!"); + + // Inflate the ViewStub, look up and initialize the UI elements. + ViewStub stub = (ViewStub) mInCallScreen.findViewById(R.id.manageConferencePanelStub); + stub.inflate(); + + mManageConferencePanel = + (ViewGroup) mInCallScreen.findViewById(R.id.manageConferencePanel); + if (mManageConferencePanel == null) { + throw new IllegalStateException("Couldn't find manageConferencePanel!"); + } + + // set up the Conference Call chronometer + mConferenceTime = + (Chronometer) mInCallScreen.findViewById(R.id.manageConferencePanelHeader); + mConferenceTime.setFormat(mInCallScreen.getString(R.string.caller_manage_header)); + + // Create list of conference call widgets + mConferenceCallList = new ViewGroup[MAX_CALLERS_IN_CONFERENCE]; + + final int[] viewGroupIdList = { R.id.caller0, R.id.caller1, R.id.caller2, + R.id.caller3, R.id.caller4 }; + for (int i = 0; i < MAX_CALLERS_IN_CONFERENCE; i++) { + mConferenceCallList[i] = + (ViewGroup) mInCallScreen.findViewById(viewGroupIdList[i]); + } + + mButtonManageConferenceDone = mInCallScreen.findViewById(R.id.manage_done); + mButtonManageConferenceDone.setOnClickListener(mInCallScreen); + } + } + + /** + * Shows or hides the manageConferencePanel. + */ + public void setPanelVisible(boolean visible) { + if (mManageConferencePanel != null) { + mManageConferencePanel.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + + /** + * Starts the "conference time" chronometer. + */ + public void startConferenceTime(long base) { + if (mConferenceTime != null) { + mConferenceTime.setBase(base); + mConferenceTime.start(); + } + } + + /** + * Stops the "conference time" chronometer. + */ + public void stopConferenceTime() { + if (mConferenceTime != null) { + mConferenceTime.stop(); + } + } + + public int getNumCallersInConference() { + return mNumCallersInConference; + } + + /** + * Updates the "Manage conference" UI based on the specified List of + * connections. + * + * @param connections the List of connections belonging to + * the current foreground call; size must be greater than 1 + * (or it wouldn't be a conference call in the first place.) + */ + public void updateManageConferencePanel(List<Connection> connections) { + mNumCallersInConference = connections.size(); + if (DBG) log("updateManageConferencePanel()... num connections in conference = " + + mNumCallersInConference); + + // Can we give the user the option to separate out ("go private with") a single + // caller from this conference? + final boolean hasActiveCall = mCM.hasActiveFgCall(); + final boolean hasHoldingCall = mCM.hasActiveBgCall(); + boolean canSeparate = !(hasActiveCall && hasHoldingCall); + + for (int i = 0; i < MAX_CALLERS_IN_CONFERENCE; i++) { + if (i < mNumCallersInConference) { + // Fill in the row in the UI for this caller. + Connection connection = (Connection) connections.get(i); + updateManageConferenceRow(i, connection, canSeparate); + } else { + // Blank out this row in the UI + updateManageConferenceRow(i, null, false); + } + } + } + + /** + * Updates a single row of the "Manage conference" UI. (One row in this + * UI represents a single caller in the conference.) + * + * @param i the row to update + * @param connection the Connection corresponding to this caller. + * If null, that means this is an "empty slot" in the conference, + * so hide this row in the UI. + * @param canSeparate if true, show a "Separate" (i.e. "Private") button + * on this row in the UI. + */ + public void updateManageConferenceRow(final int i, + final Connection connection, + boolean canSeparate) { + if (DBG) log("updateManageConferenceRow(" + i + ")... connection = " + connection); + + if (connection != null) { + // Activate this row of the Manage conference panel: + mConferenceCallList[i].setVisibility(View.VISIBLE); + + // get the relevant children views + View endButton = mConferenceCallList[i].findViewById(R.id.conferenceCallerDisconnect); + View separateButton = mConferenceCallList[i].findViewById( + R.id.conferenceCallerSeparate); + TextView nameTextView = (TextView) mConferenceCallList[i].findViewById( + R.id.conferenceCallerName); + TextView numberTextView = (TextView) mConferenceCallList[i].findViewById( + R.id.conferenceCallerNumber); + TextView numberTypeTextView = (TextView) mConferenceCallList[i].findViewById( + R.id.conferenceCallerNumberType); + + if (DBG) log("- button: " + endButton + ", nameTextView: " + nameTextView); + + // Hook up this row's buttons. + View.OnClickListener endThisConnection = new View.OnClickListener() { + @Override + public void onClick(View v) { + endConferenceConnection(i, connection); + PhoneGlobals.getInstance().pokeUserActivity(); + } + }; + endButton.setOnClickListener(endThisConnection); + // + if (canSeparate) { + View.OnClickListener separateThisConnection = new View.OnClickListener() { + @Override + public void onClick(View v) { + separateConferenceConnection(i, connection); + PhoneGlobals.getInstance().pokeUserActivity(); + } + }; + separateButton.setOnClickListener(separateThisConnection); + separateButton.setVisibility(View.VISIBLE); + } else { + separateButton.setVisibility(View.INVISIBLE); + } + + // Name/number for this caller. + QueryCompleteListener listener = new QueryCompleteListener(i); + PhoneUtils.CallerInfoToken info = + PhoneUtils.startGetCallerInfo(mInCallScreen, + connection, listener, connection); + if (DBG) log(" - got info from startGetCallerInfo(): " + info); + + // display the CallerInfo. + displayCallerInfoForConferenceRow(info.currentInfo, connection.getNumberPresentation(), + nameTextView, numberTypeTextView, numberTextView); + } else { + // Disable this row of the Manage conference panel: + mConferenceCallList[i].setVisibility(View.GONE); + } + } + + /** + * Helper function to fill out the Conference Call(er) information + * for each item in the "Manage Conference Call" list. + * + * @param presentation presentation specified by {@link Connection}. + */ + public final void displayCallerInfoForConferenceRow(CallerInfo ci, int presentation, + TextView nameTextView, TextView numberTypeTextView, TextView numberTextView) { + // gather the correct name and number information. + String callerName = ""; + String callerNumber = ""; + String callerNumberType = ""; + if (ci != null) { + callerName = ci.name; + if (TextUtils.isEmpty(callerName)) { + // Do similar fallback as CallCard does. + // See also CallCard#updateDisplayForPerson(). + if (TextUtils.isEmpty(ci.phoneNumber)) { + callerName = PhoneUtils.getPresentationString(mInCallScreen, presentation); + } else if (!TextUtils.isEmpty(ci.cnapName)) { + // No name, but we do have a valid CNAP name, so use that. + callerName = ci.cnapName; + } else { + callerName = ci.phoneNumber; + } + } else { + callerNumber = ci.phoneNumber; + callerNumberType = ci.phoneLabel; + } + } + + // set the caller name + nameTextView.setText(callerName); + + // set the caller number in subscript, or make the field disappear. + if (TextUtils.isEmpty(callerNumber)) { + numberTextView.setVisibility(View.GONE); + numberTypeTextView.setVisibility(View.GONE); + } else { + numberTextView.setVisibility(View.VISIBLE); + numberTextView.setText(callerNumber); + numberTypeTextView.setVisibility(View.VISIBLE); + numberTypeTextView.setText(callerNumberType); + } + } + + /** + * Ends the specified connection on a conference call. This method is + * run (via a closure containing a row index and Connection) when the + * user clicks the "End" button on a specific row in the Manage + * conference UI. + */ + public void endConferenceConnection(int i, Connection connection) { + if (DBG) log("===> ENDING conference connection " + i + + ": Connection " + connection); + // The actual work of ending the connection: + PhoneUtils.hangup(connection); + // No need to manually update the "Manage conference" UI here; + // that'll happen automatically very soon (when we get the + // onDisconnect() callback triggered by this hangup() call.) + } + + /** + * Separates out the specified connection on a conference call. This + * method is run (via a closure containing a row index and Connection) + * when the user clicks the "Separate" (i.e. "Private") button on a + * specific row in the Manage conference UI. + */ + public void separateConferenceConnection(int i, Connection connection) { + if (DBG) log("===> SEPARATING conference connection " + i + + ": Connection " + connection); + + PhoneUtils.separateCall(connection); + + // Note that separateCall() automagically makes the + // newly-separated call into the foreground call (which is the + // desired UI), so there's no need to do any further + // call-switching here. + // There's also no need to manually update (or hide) the "Manage + // conference" UI; that'll happen on its own in a moment (when we + // get the phone state change event triggered by the call to + // separateCall().) + } + + + private void log(String msg) { + Log.d(LOG_TAG, msg); + } +} |