summaryrefslogtreecommitdiff
path: root/InCallUI
diff options
context:
space:
mode:
authorChristine Chen <christinech@google.com>2013-09-06 14:50:32 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2013-09-06 14:50:32 -0700
commitd9ef38beea322a20328e39cd1f4c9b5c08a64f31 (patch)
treec9bfe199607511755fbf18d4e9daac8d33ca7665 /InCallUI
parent5a85cb01e8a0bbe5de68a1ff9fc124ba8ff7e41f (diff)
parent5345442d7238c1db00dc8d55a49f7f5dd713d994 (diff)
am 0f09a02b: Adds manage conference call UI
* commit '0f09a02be361d5bb36fac6981649204f5d6987fa': Adds manage conference call UI
Diffstat (limited to 'InCallUI')
-rw-r--r--InCallUI/res/drawable-hdpi/ic_end_call_holo_dark.pngbin0 -> 1974 bytes
-rw-r--r--InCallUI/res/drawable-hdpi/ic_split_holo_dark.pngbin0 -> 1893 bytes
-rw-r--r--InCallUI/res/drawable-mdpi/ic_end_call_holo_dark.pngbin0 -> 1471 bytes
-rw-r--r--InCallUI/res/drawable-mdpi/ic_split_holo_dark.pngbin0 -> 1514 bytes
-rw-r--r--InCallUI/res/drawable-xhdpi/ic_end_call_holo_dark.pngbin0 -> 2704 bytes
-rw-r--r--InCallUI/res/drawable-xhdpi/ic_split_holo_dark.pngbin0 -> 2839 bytes
-rw-r--r--InCallUI/res/layout/call_button_fragment.xml8
-rw-r--r--InCallUI/res/layout/caller_in_conference.xml107
-rw-r--r--InCallUI/res/layout/conference_manager_fragment.xml132
-rw-r--r--InCallUI/res/layout/extra_button_row.xml6
-rw-r--r--InCallUI/res/layout/incall_screen.xml9
-rwxr-xr-xInCallUI/res/values/strings.xml3
-rw-r--r--InCallUI/src/com/android/incallui/CallButtonFragment.java50
-rw-r--r--InCallUI/src/com/android/incallui/CallButtonPresenter.java37
-rw-r--r--InCallUI/src/com/android/incallui/CallCardFragment.java9
-rw-r--r--InCallUI/src/com/android/incallui/CallCardPresenter.java14
-rw-r--r--InCallUI/src/com/android/incallui/CallCommandClient.java15
-rw-r--r--InCallUI/src/com/android/incallui/ConferenceManagerFragment.java197
-rw-r--r--InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java149
-rw-r--r--InCallUI/src/com/android/incallui/InCallActivity.java18
20 files changed, 739 insertions, 15 deletions
diff --git a/InCallUI/res/drawable-hdpi/ic_end_call_holo_dark.png b/InCallUI/res/drawable-hdpi/ic_end_call_holo_dark.png
new file mode 100644
index 000000000..0f373bb26
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/ic_end_call_holo_dark.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/ic_split_holo_dark.png b/InCallUI/res/drawable-hdpi/ic_split_holo_dark.png
new file mode 100644
index 000000000..5b10cf948
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/ic_split_holo_dark.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/ic_end_call_holo_dark.png b/InCallUI/res/drawable-mdpi/ic_end_call_holo_dark.png
new file mode 100644
index 000000000..e090cc806
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/ic_end_call_holo_dark.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/ic_split_holo_dark.png b/InCallUI/res/drawable-mdpi/ic_split_holo_dark.png
new file mode 100644
index 000000000..3980acbb8
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/ic_split_holo_dark.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/ic_end_call_holo_dark.png b/InCallUI/res/drawable-xhdpi/ic_end_call_holo_dark.png
new file mode 100644
index 000000000..f64f5e3d9
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/ic_end_call_holo_dark.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/ic_split_holo_dark.png b/InCallUI/res/drawable-xhdpi/ic_split_holo_dark.png
new file mode 100644
index 000000000..db558e49a
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/ic_split_holo_dark.png
Binary files differ
diff --git a/InCallUI/res/layout/call_button_fragment.xml b/InCallUI/res/layout/call_button_fragment.xml
index cec11f01f..6a76a1ca2 100644
--- a/InCallUI/res/layout/call_button_fragment.xml
+++ b/InCallUI/res/layout/call_button_fragment.xml
@@ -42,10 +42,10 @@
Most of the time this whole row is GONE.
For now, at least, there's only ever one button visible here
at a time, so this can be a simple FrameLayout. -->
- <ViewStub android:id="@+id/extraButtonRow"
- android:layout="@layout/extra_button_row"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ <include android:id="@+id/extraButtonRow"
+ layout="@layout/extra_button_row"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
<!-- Row 2: The "End call" button. -->
<ImageButton android:id="@+id/endButton"
diff --git a/InCallUI/res/layout/caller_in_conference.xml b/InCallUI/res/layout/caller_in_conference.xml
new file mode 100644
index 000000000..c2c68c836
--- /dev/null
+++ b/InCallUI/res/layout/caller_in_conference.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="64dp"
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+
+ <!-- Caller information -->
+ <LinearLayout
+ android:id="@+id/conferenceCallerSeparate"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingStart="16dp"
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+
+ <!-- "Separate" (i.e. "go private") button for this caller -->
+ <ImageView
+ android:src="@drawable/ic_split_holo_dark"
+ android:layout_width="46dp"
+ android:layout_height="46dp"
+ android:scaleType="center"
+ android:contentDescription="@string/goPrivate"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="8dp"
+ android:gravity="center_vertical"
+ android:orientation="vertical">
+
+ <!-- Name or number of this caller -->
+ <TextView
+ android:id="@+id/conferenceCallerName"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textSize="18sp"
+ android:singleLine="true"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="2dp"
+ />
+
+ <!-- Number of this caller if name is supplied above -->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:gravity="bottom">
+
+ <!-- Number -->
+ <TextView
+ android:id="@+id/conferenceCallerNumber"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14sp"
+ android:ellipsize="marquee"
+ android:textColor="@color/manage_conference_secondary_text_color"
+ android:singleLine="true"
+ android:layout_marginEnd="8dp" />
+
+ <!-- Number type -->
+ <TextView
+ android:id="@+id/conferenceCallerNumberType"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="12sp"
+ android:textColor="@color/manage_conference_secondary_text_color"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:textAllCaps="true"
+ android:gravity="start" />
+
+ </LinearLayout> <!-- End of caller number -->
+
+ </LinearLayout> <!-- End of caller information -->
+ </LinearLayout>
+
+ <!-- "End" button for this caller which should look like the
+ "end call" button in the main in-call UI screen -->
+ <ImageButton
+ android:id="@+id/conferenceCallerDisconnect"
+ android:layout_width="80dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_end_call_holo_dark"
+ android:background="@drawable/end_call_background"
+ android:scaleType="center"
+ android:contentDescription="@string/onscreenEndCallText" />
+
+</LinearLayout> <!-- End of single list element -->
diff --git a/InCallUI/res/layout/conference_manager_fragment.xml b/InCallUI/res/layout/conference_manager_fragment.xml
new file mode 100644
index 000000000..f1fbfdfac
--- /dev/null
+++ b/InCallUI/res/layout/conference_manager_fragment.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- The "Manage conference" UI. This panel is displayed (instead of
+ the inCallPanel) when the user clicks the "Manage conference"
+ button while on a conference call. -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/manageConferencePanel"
+ android:background="#FF000000"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ >
+ <!-- This original header (with timer) is currently not being used,
+ but may be of use in the future. -->
+ <!-- Header, including chronometer and List divider -->
+ <Chronometer
+ android:id="@+id/manageConferencePanelHeader"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textSize="24sp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_alignParentTop="true"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:visibility="gone"/>
+
+ <ImageView
+ android:id="@+id/manageConferencePanelDivider"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:src="@android:drawable/divider_horizontal_dark"
+ android:scaleType="fitXY"
+ android:layout_below="@id/manageConferencePanelHeader"
+ android:visibility="gone"/>
+ <!-- End of the original header -->
+
+ <!-- Header which looks like ActionBar. -->
+ <FrameLayout
+ android:id="@+id/manageConferenceHeader"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@*android:drawable/ab_transparent_dark_holo">
+
+ <LinearLayout
+ android:id="@+id/manage_done"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
+ android:clickable="true"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:src="?android:attr/homeAsUpIndicator"
+ android:layout_gravity="center_vertical|left"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ style="@*android:style/TextAppearance.Holo.Widget.ActionBar.Title"
+ android:gravity="center_vertical"
+ android:text="@string/manageConferenceLabel"/>
+ </LinearLayout>
+
+ </FrameLayout> <!-- End of header -->
+
+ <!-- The scrollview wrapper for the list of callers on
+ the conference call (in case the list gets too long). -->
+ <ScrollView
+ android:id="@+id/conferenceList"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/manageConferenceHeader">
+
+ <!-- The actual list of callers; this embedded LinearLayout
+ required since scrollview only supports a single child. -->
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:showDividers="middle|end"
+ android:divider="?android:attr/listDivider">
+
+ <!-- A conference can have at most MAX_CALLERS_IN_CONFERENCE (= 5) callers,
+ so just define all those UI elements here. -->
+
+ <!-- Caller 0 -->
+ <include
+ layout="@layout/caller_in_conference"
+ android:id="@+id/caller0"/>
+
+ <!-- Caller 1 -->
+ <include
+ layout="@layout/caller_in_conference"
+ android:id="@+id/caller1"/>
+
+ <!-- Caller 2 -->
+ <include
+ layout="@layout/caller_in_conference"
+ android:id="@+id/caller2"/>
+
+ <!-- Caller 3 -->
+ <include
+ layout="@layout/caller_in_conference"
+ android:id="@+id/caller3"/>
+
+ <!-- Caller 4 -->
+ <include
+ layout="@layout/caller_in_conference"
+ android:id="@+id/caller4"/>
+
+ </LinearLayout> <!-- End of "list of callers on conference call" -->
+
+ </ScrollView> <!-- End of scrolling list wrapper for the linear layout -->
+
+</RelativeLayout>
diff --git a/InCallUI/res/layout/extra_button_row.xml b/InCallUI/res/layout/extra_button_row.xml
index 79c11366d..a1600e80a 100644
--- a/InCallUI/res/layout/extra_button_row.xml
+++ b/InCallUI/res/layout/extra_button_row.xml
@@ -32,7 +32,8 @@
android:layout_height="wrap_content"
android:paddingStart="@dimen/button_cluster_side_padding"
android:paddingEnd="@dimen/button_cluster_side_padding"
- android:background="?android:attr/selectableItemBackground">
+ android:background="?android:attr/selectableItemBackground"
+ android:visibility="gone">
<!-- The entire LinearLayout here is clickable, so we don't
care about clicks on the ImageButton itself. -->
<ImageButton android:id="@+id/manageConferenceButtonImage"
@@ -55,7 +56,8 @@
android:layout_height="wrap_content"
android:paddingStart="@dimen/button_cluster_side_padding"
android:paddingEnd="@dimen/button_cluster_side_padding"
- android:background="?android:attr/selectableItemBackground">
+ android:background="?android:attr/selectableItemBackground"
+ android:visibility="gone">
<!-- The entire LinearLayout here is clickable, so we don't
care about clicks on the ImageButton itself. -->
<ImageButton android:id="@+id/cdmaMergeButtonImage"
diff --git a/InCallUI/res/layout/incall_screen.xml b/InCallUI/res/layout/incall_screen.xml
index 86f67c989..892f91707 100644
--- a/InCallUI/res/layout/incall_screen.xml
+++ b/InCallUI/res/layout/incall_screen.xml
@@ -67,4 +67,13 @@
android:layout_marginBottom="@dimen/glowpadview_margin_bottom"
android:visibility="gone" />
+ <fragment android:name="com.android.incallui.ConferenceManagerFragment"
+ android:id="@+id/conferenceManagerFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true" />
+
</FrameLayout>
diff --git a/InCallUI/res/values/strings.xml b/InCallUI/res/values/strings.xml
index 785e36467..e7049e5b2 100755
--- a/InCallUI/res/values/strings.xml
+++ b/InCallUI/res/values/strings.xml
@@ -1467,4 +1467,7 @@
related settings.
[CHAR LIMIT=30] -->
<string name="preference_category_ringtone">Ringtone &amp; Vibrate</string>
+
+ <!-- Label for "Manage conference call" panel [CHAR LIMIT=40] -->
+ <string name="manageConferenceLabel">Manage conference call</string>
</resources>
diff --git a/InCallUI/src/com/android/incallui/CallButtonFragment.java b/InCallUI/src/com/android/incallui/CallButtonFragment.java
index 1c3e737e6..4c42a7845 100644
--- a/InCallUI/src/com/android/incallui/CallButtonFragment.java
+++ b/InCallUI/src/com/android/incallui/CallButtonFragment.java
@@ -23,6 +23,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.PopupMenu;
@@ -51,6 +52,9 @@ public class CallButtonFragment
private PopupMenu mAudioModePopup;
private boolean mAudioModePopupVisible;
private View mEndCallButton;
+ private View mExtraRowButton;
+ private View mManageConferenceButton;
+ private View mCDMAMergeButton;
@Override
CallButtonPresenter createPresenter() {
@@ -74,6 +78,17 @@ public class CallButtonFragment
Bundle savedInstanceState) {
final View parent = inflater.inflate(R.layout.call_button_fragment, container, false);
+ mExtraRowButton = parent.findViewById(R.id.extraButtonRow);
+
+ mManageConferenceButton = parent.findViewById(R.id.manageConferenceButton);
+ mManageConferenceButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ getPresenter().manageConferenceButtonClicked();
+ }
+ });
+ mCDMAMergeButton = parent.findViewById(R.id.cdmaMergeButton);
+
mEndCallButton = parent.findViewById(R.id.endButton);
mEndCallButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -449,4 +464,39 @@ public class CallButtonFragment
((InCallActivity) getActivity()).displayDialpad(value);
}
}
+
+ @Override
+ public boolean isDialpadVisible() {
+ if (getActivity() != null && getActivity() instanceof InCallActivity) {
+ return ((InCallActivity) getActivity()).isDialpadVisible();
+ }
+ return false;
+ }
+
+ @Override
+ public void displayManageConferencePanel(boolean value) {
+ if (getActivity() != null && getActivity() instanceof InCallActivity) {
+ ((InCallActivity) getActivity()).displayManageConferencePanel(value);
+ }
+ }
+
+
+ @Override
+ public void showManageConferenceCallButton() {
+ mExtraRowButton.setVisibility(View.VISIBLE);
+ mManageConferenceButton.setVisibility(View.VISIBLE);
+ mCDMAMergeButton.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void showCDMAMergeButton() {
+ mExtraRowButton.setVisibility(View.VISIBLE);
+ mManageConferenceButton.setVisibility(View.GONE);
+ mCDMAMergeButton.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void hideExtraRow() {
+ mExtraRowButton.setVisibility(View.GONE);
+ }
}
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index bc9efe507..17273a874 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -145,6 +145,10 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
CallCommandClient.getInstance().disconnectCall(mCall.getCallId());
}
+ public void manageConferenceButtonClicked() {
+ getUi().displayManageConferencePanel(true);
+ }
+
public void muteClicked(boolean checked) {
Log.d(this, "turning on mute: " + checked);
@@ -217,6 +221,34 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
ui.setMute(mPreviousMuteState);
mAutomaticallyMuted = false;
}
+
+ // Finally, update the "extra button row": It's displayed above the
+ // "End" button, but only if necessary. Also, it's never displayed
+ // while the dialpad is visible (since it would overlap.)
+ //
+ // The row contains two buttons:
+ //
+ // - "Manage conference" (used only on GSM devices)
+ // - "Merge" button (used only on CDMA devices)
+ // TODO(klp) Add cdma merge button
+ final boolean showCdmaMerge = false;
+// (phoneType == PhoneConstants.PHONE_TYPE_CDMA) && inCallControlState.canMerge;
+ final boolean showExtraButtonRow =
+ (showCdmaMerge || call.isConferenceCall()) && !getUi().isDialpadVisible();
+ if (showExtraButtonRow) {
+ // Need to set up mCdmaMergeButton and mManageConferenceButton if this is the first
+ // time they're visible.
+ // TODO(klp) add cdma merge button
+// if (mCdmaMergeButton == null) {
+// setupExtraButtons();
+// }
+// mCdmaMergeButton.setVisibility(showCdmaMerge ? View.VISIBLE : View.GONE);
+ if (call.isConferenceCall()) {
+ getUi().showManageConferenceCallButton();
+ }
+ } else {
+ getUi().hideExtraRow();
+ }
}
}
@@ -241,7 +273,12 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
void showSwap(boolean show);
void showAddCall(boolean show);
void displayDialpad(boolean on);
+ boolean isDialpadVisible();
void setAudio(int mode);
void setSupportedAudio(int mask);
+ void showManageConferenceCallButton();
+ void showCDMAMergeButton();
+ void hideExtraRow();
+ void displayManageConferencePanel(boolean on);
}
}
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index 486b083f9..9c772cb05 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -185,6 +185,7 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
if (isConference) {
name = getView().getResources().getString(R.string.card_title_conf_call);
photo = getView().getResources().getDrawable(R.drawable.picture_conference);
+ nameIsNumber = false;
}
setPrimaryPhoneNumber(number);
@@ -203,9 +204,15 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPr
@Override
public void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
- Drawable photo) {
+ Drawable photo, boolean isConference) {
if (show) {
+ if (isConference) {
+ name = getView().getResources().getString(R.string.card_title_conf_call);
+ photo = getView().getResources().getDrawable(R.drawable.picture_conference);
+ nameIsNumber = false;
+ }
+
showAndInitializeSecondaryCallInfo();
mSecondaryCallName.setText(name);
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index db5b66a9a..d2295d34e 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -156,13 +156,13 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
if (secondary == null) {
// Secondary call may have ended. Update the ui.
mSecondaryContactInfo = null;
- updateSecondaryDisplayInfo();
+ updateSecondaryDisplayInfo(false);
} else {
if (mSecondary == null || mSecondary.getCallId() != secondary.getCallId()) {
// secondary call has changed
mSecondaryContactInfo = ContactInfoCache.buildCacheEntryFromCall(mContext,
secondary.getIdentification(), secondary.getState() == Call.State.INCOMING);
- updateSecondaryDisplayInfo();
+ updateSecondaryDisplayInfo(secondary.isConferenceCall());
startContactInfoSearch(secondary.getIdentification(), false,
secondary.isConferenceCall(), secondary.getState() == Call.State.INCOMING);
}
@@ -289,7 +289,7 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
updatePrimaryDisplayInfo(entry, isConference);
} else {
mSecondaryContactInfo = entry;
- updateSecondaryDisplayInfo();
+ updateSecondaryDisplayInfo(isConference);
}
}
@@ -358,7 +358,7 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
}
- private void updateSecondaryDisplayInfo() {
+ private void updateSecondaryDisplayInfo(boolean isConference) {
final CallCardUi ui = getUi();
if (ui == null) {
@@ -372,10 +372,10 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
final boolean nameIsNumber = nameForCall != null && nameForCall.equals(
mSecondaryContactInfo.number);
ui.setSecondary(true, nameForCall, nameIsNumber, mSecondaryContactInfo.label,
- mSecondaryContactInfo.photo);
+ mSecondaryContactInfo.photo, isConference);
} else {
// reset to nothing so that it starts off blank next time we use it.
- ui.setSecondary(false, null, false, null, null);
+ ui.setSecondary(false, null, false, null, null, false);
}
}
@@ -494,7 +494,7 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
void setPrimary(String number, String name, boolean nameIsNumber, String label,
Drawable photo, boolean isConference, String gatewayLabel, String gatewayNumber);
void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
- Drawable photo);
+ Drawable photo, boolean isConference);
void setSecondaryImage(Bitmap bitmap);
void setCallState(int state, Call.DisconnectCause cause, boolean bluetoothOn);
void setPrimaryCallElapsedTime(boolean show, String duration);
diff --git a/InCallUI/src/com/android/incallui/CallCommandClient.java b/InCallUI/src/com/android/incallui/CallCommandClient.java
index 0cc7a8c2d..b59788b2c 100644
--- a/InCallUI/src/com/android/incallui/CallCommandClient.java
+++ b/InCallUI/src/com/android/incallui/CallCommandClient.java
@@ -79,7 +79,20 @@ public class CallCommandClient {
try {
mCommandService.disconnectCall(callId);
} catch (RemoteException e) {
- Log.e(this, "Error answering call.", e);
+ Log.e(this, "Error disconnecting call.", e);
+ }
+ }
+
+ public void separateCall(int callId) {
+ Log.i(this, "separate Call: " + callId);
+ if (mCommandService == null) {
+ Log.e(this, "Cannot separate call; CallCommandService == null");
+ return;
+ }
+ try {
+ mCommandService.separateCall(callId);
+ } catch (RemoteException e) {
+ Log.e(this, "Error separating call.", e);
}
}
diff --git a/InCallUI/src/com/android/incallui/ConferenceManagerFragment.java b/InCallUI/src/com/android/incallui/ConferenceManagerFragment.java
new file mode 100644
index 000000000..75ff17698
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/ConferenceManagerFragment.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2013 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.incallui;
+
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Chronometer;
+import android.widget.TextView;
+
+/**
+ * Fragment for call control buttons
+ */
+public class ConferenceManagerFragment
+ extends BaseFragment<ConferenceManagerPresenter,
+ ConferenceManagerPresenter.ConferenceManagerUi>
+ implements ConferenceManagerPresenter.ConferenceManagerUi {
+
+ private View mButtonManageConferenceDone;
+ private ViewGroup[] mConferenceCallList;
+ private Chronometer mConferenceTime;
+
+ @Override
+ ConferenceManagerPresenter createPresenter() {
+ // having a singleton instance.
+ return new ConferenceManagerPresenter();
+ }
+
+ @Override
+ ConferenceManagerPresenter.ConferenceManagerUi getUi() {
+ return this;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View parent = inflater.inflate(R.layout.conference_manager_fragment, container,
+ false);
+
+ // set up the Conference Call chronometer
+ mConferenceTime = (Chronometer) parent.findViewById(R.id.manageConferencePanelHeader);
+ mConferenceTime.setFormat(getActivity().getString(R.string.caller_manage_header));
+
+ // Create list of conference call widgets
+ mConferenceCallList = new ViewGroup[getPresenter().getMaxCallersInConference()];
+
+ final int[] viewGroupIdList = { R.id.caller0, R.id.caller1, R.id.caller2,
+ R.id.caller3, R.id.caller4 };
+ for (int i = 0; i < getPresenter().getMaxCallersInConference(); i++) {
+ mConferenceCallList[i] =
+ (ViewGroup) parent.findViewById(viewGroupIdList[i]);
+ }
+
+ mButtonManageConferenceDone = parent.findViewById(R.id.manage_done);
+ mButtonManageConferenceDone.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ getPresenter().manageConferenceDoneClicked();
+ }
+ });
+
+ return parent;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ }
+
+ @Override
+ public void setVisible(boolean on) {
+ if (on) {
+ final CallList calls = CallList.getInstance();
+ getPresenter().init(getActivity(), calls);
+ getView().setVisibility(View.VISIBLE);
+
+ } else {
+ getView().setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public boolean isFragmentVisible() {
+ return isVisible();
+ }
+
+ @Override
+ public void setRowVisible(int rowId, boolean on) {
+ if (on) {
+ mConferenceCallList[rowId].setVisibility(View.VISIBLE);
+ } else {
+ mConferenceCallList[rowId].setVisibility(View.GONE);
+ }
+ }
+
+ /**
+ * Helper function to fill out the Conference Call(er) information
+ * for each item in the "Manage Conference Call" list.
+ */
+ @Override
+ public final void displayCallerInfoForConferenceRow(int rowId, String callerName,
+ String callerNumber, String callerNumberType) {
+
+ final TextView nameTextView = (TextView) mConferenceCallList[rowId].findViewById(
+ R.id.conferenceCallerName);
+ final TextView numberTextView = (TextView) mConferenceCallList[rowId].findViewById(
+ R.id.conferenceCallerNumber);
+ final TextView numberTypeTextView = (TextView) mConferenceCallList[rowId].findViewById(
+ R.id.conferenceCallerNumberType);
+
+ // 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);
+ }
+ }
+
+ @Override
+ public final void setupEndButtonForRow(final int rowId) {
+ View endButton = mConferenceCallList[rowId].findViewById(R.id.conferenceCallerDisconnect);
+ endButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ getPresenter().endConferenceConnection(rowId);
+ }
+ });
+ }
+
+ @Override
+ public final void setCanSeparateButtonForRow(final int rowId, boolean canSeparate) {
+ final View separateButton = mConferenceCallList[rowId].findViewById(
+ R.id.conferenceCallerSeparate);
+
+ if (canSeparate) {
+ final View.OnClickListener separateThisConnection = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ getPresenter().separateConferenceConnection(rowId);
+ }
+ };
+ separateButton.setOnClickListener(separateThisConnection);
+ separateButton.setVisibility(View.VISIBLE);
+ } else {
+ separateButton.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ /**
+ * Starts the "conference time" chronometer.
+ */
+ @Override
+ public void startConferenceTime(long base) {
+ if (mConferenceTime != null) {
+ mConferenceTime.setBase(base);
+ mConferenceTime.start();
+ }
+ }
+
+ /**
+ * Stops the "conference time" chronometer.
+ */
+ @Override
+ public void stopConferenceTime() {
+ if (mConferenceTime != null) {
+ mConferenceTime.stop();
+ }
+ }
+} \ No newline at end of file
diff --git a/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java b/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java
new file mode 100644
index 000000000..6b6f7d815
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/ConferenceManagerPresenter.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2013 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.incallui;
+
+import android.content.Context;
+
+import com.android.incallui.ContactInfoCache.ContactCacheEntry;
+import com.android.incallui.InCallPresenter.InCallState;
+import com.android.incallui.InCallPresenter.InCallStateListener;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSortedSet;
+
+/**
+ * Logic for call buttons.
+ */
+public class ConferenceManagerPresenter
+ extends Presenter<ConferenceManagerPresenter.ConferenceManagerUi>
+ implements InCallStateListener {
+
+ private static final int MAX_CALLERS_IN_CONFERENCE = 5;
+
+ private int mNumCallersInConference;
+ private Integer[] mCallerIds;
+ private Context mContext;
+
+ @Override
+ public void onStateChange(InCallState state, CallList callList) {
+ if (getUi().isFragmentVisible()) {
+ if (state == InCallState.INCALL && callList.getActiveOrBackgroundCall() != null &&
+ callList.getActiveOrBackgroundCall().isConferenceCall()) {
+ Log.v(this, "Number of existing calls is " +
+ String.valueOf(callList.getActiveCall().getChildCallIds().size()));
+ update(callList);
+ } else {
+ getUi().setVisible(false);
+ }
+ }
+ }
+
+ public void init(Context context, CallList callList) {
+ mContext = Preconditions.checkNotNull(context);
+ mContext = context;
+ update(callList);
+ }
+
+ private void update(CallList callList) {
+ mCallerIds = null;
+ mCallerIds = callList.getActiveCall().getChildCallIds().toArray(new Integer[0]);
+ mNumCallersInConference = mCallerIds.length;
+ Log.v(this, "Number of calls is " + String.valueOf(mNumCallersInConference));
+
+ // Users can split out a call from the conference call if there either the active call
+ // or the holding call is empty. If both are filled at the moment, users can not split out
+ // another call.
+ final boolean hasActiveCall = (callList.getActiveCall() != null);
+ final boolean hasHoldingCall = (callList.getBackgroundCall() != null);
+ 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.
+
+ final ContactCacheEntry contactCache = ContactInfoCache.getInstance(mContext).
+ getInfo(mCallerIds[i]);
+ updateManageConferenceRow(i, contactCache, 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 contactCacheEntry the contact details 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 ContactCacheEntry contactCacheEntry,
+ boolean canSeparate) {
+
+ if (contactCacheEntry != null) {
+ // Activate this row of the Manage conference panel:
+ getUi().setRowVisible(i, true);
+
+ final String name = contactCacheEntry.name;
+ final String number = contactCacheEntry.number;
+
+ if (canSeparate) {
+ getUi().setCanSeparateButtonForRow(i, canSeparate);
+ }
+ // display the CallerInfo.
+ getUi().setupEndButtonForRow(i);
+ getUi().displayCallerInfoForConferenceRow(i, name, number, contactCacheEntry.label);
+ } else {
+ // Disable this row of the Manage conference panel:
+ getUi().setRowVisible(i, false);
+ }
+ }
+
+ public void manageConferenceDoneClicked() {
+ getUi().setVisible(false);
+ }
+
+ public int getMaxCallersInConference() {
+ return MAX_CALLERS_IN_CONFERENCE;
+ }
+
+ public void separateConferenceConnection(int rowId) {
+ CallCommandClient.getInstance().separateCall(mCallerIds[rowId]);
+ }
+
+ public void endConferenceConnection(int rowId) {
+ CallCommandClient.getInstance().disconnectCall(mCallerIds[rowId]);
+ }
+
+ public interface ConferenceManagerUi extends Ui {
+ void setVisible(boolean on);
+ boolean isFragmentVisible();
+ void setRowVisible(int rowId, boolean on);
+ void displayCallerInfoForConferenceRow(int rowId, String callerName, String callerNumber,
+ String callerNumberType);
+ void setCanSeparateButtonForRow(int rowId, boolean canSeparate);
+ void setupEndButtonForRow(int rowId);
+ void startConferenceTime(long base);
+ void stopConferenceTime();
+ }
+}
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index fee4d9510..6cae6b05e 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -34,6 +34,7 @@ public class InCallActivity extends Activity {
private CallCardFragment mCallCardFragment;
private AnswerFragment mAnswerFragment;
private DialpadFragment mDialpadFragment;
+ private ConferenceManagerFragment mConferenceManagerFragment;
private boolean mIsForegroundActivity;
@Override
@@ -287,6 +288,11 @@ public class InCallActivity extends Activity {
mDialpadFragment.getView().setVisibility(View.INVISIBLE);
}
+ if (mConferenceManagerFragment == null) {
+ mConferenceManagerFragment = (ConferenceManagerFragment) getFragmentManager()
+ .findFragmentById(R.id.conferenceManagerFragment);
+ mConferenceManagerFragment.getView().setVisibility(View.INVISIBLE);
+ }
setUpPresenterCallbacks();
}
@@ -302,6 +308,7 @@ public class InCallActivity extends Activity {
mainPresenter.addListener(mCallButtonFragment.getPresenter());
mainPresenter.addListener(mCallCardFragment.getPresenter());
+ mainPresenter.addListener(mConferenceManagerFragment.getPresenter());
// setting activity should be last thing in setup process
mainPresenter.setActivity(this);
@@ -313,6 +320,7 @@ public class InCallActivity extends Activity {
mainPresenter.removeListener(mCallButtonFragment.getPresenter());
mainPresenter.removeListener(mCallCardFragment.getPresenter());
+ mainPresenter.removeListener(mConferenceManagerFragment.getPresenter());
mainPresenter.setActivity(null);
}
@@ -332,4 +340,14 @@ public class InCallActivity extends Activity {
mCallCardFragment.setVisible(true);
}
}
+
+ public boolean isDialpadVisible() {
+ return mDialpadFragment.isVisible();
+ }
+
+ public void displayManageConferencePanel(boolean showPanel) {
+ if (showPanel) {
+ mConferenceManagerFragment.setVisible(true);
+ }
+ }
}