blob: 5821754f27559f8a9e967b962de7cd7aa0571bb5 [file] [log] [blame]
/*
* 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);
}
}