summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--InCallUI/res/layout/call_card.xml45
-rw-r--r--InCallUI/res/layout/call_card_fragment.xml136
-rw-r--r--InCallUI/res/layout/primary_call_info.xml284
-rw-r--r--InCallUI/res/layout/secondary_call_info.xml66
-rwxr-xr-xInCallUI/res/values/strings.xml5
-rw-r--r--InCallUI/src/com/android/incallui/AnswerFragment.java59
-rw-r--r--InCallUI/src/com/android/incallui/AnswerPresenter.java45
-rw-r--r--InCallUI/src/com/android/incallui/CallButtonPresenter.java29
-rw-r--r--InCallUI/src/com/android/incallui/CallCardFragment.java29
-rw-r--r--InCallUI/src/com/android/incallui/CallCardPresenter.java22
-rw-r--r--InCallUI/src/com/android/incallui/CallHandlerService.java2
-rw-r--r--InCallUI/src/com/android/incallui/CallList.java38
-rw-r--r--InCallUI/src/com/android/incallui/InCallActivity.java65
13 files changed, 421 insertions, 404 deletions
diff --git a/InCallUI/res/layout/call_card.xml b/InCallUI/res/layout/call_card.xml
new file mode 100644
index 000000000..af47ef751
--- /dev/null
+++ b/InCallUI/res/layout/call_card.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ 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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/call_card"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <!-- The main content of the CallCard is either one or two "call info"
+ blocks, depending on whether one or two lines are in use.
+
+ The call_info blocks are stacked vertically inside a CallCard (LinearLayout),
+ each with layout_weight="1". If only one line is in use (i.e. the
+ common case) then the 2nd call info will be GONE and thus the 1st one
+ will expand to fill the full height of the CallCard. -->
+
+
+ <!-- Primary "call card" block, for the foreground call. -->
+ <include android:id="@+id/primary_call_info"
+ layout="@layout/primary_call_info" />
+
+ <!-- Secondary "Call info" block, for the background ("on hold") call. -->
+ <ViewStub android:id="@+id/secondary_call_info"
+ android:layout="@layout/secondary_call_info"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+</LinearLayout>
diff --git a/InCallUI/res/layout/call_card_fragment.xml b/InCallUI/res/layout/call_card_fragment.xml
deleted file mode 100644
index 44a9f6f64..000000000
--- a/InCallUI/res/layout/call_card_fragment.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ 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
- -->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1">
-
- <!-- Contact photo for primary call info -->
- <ImageView android:id="@+id/photo"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="top|center_horizontal"
- android:scaleType="centerCrop"
- android:contentDescription="@string/contactPhoto"
- android:src="@drawable/picture_unknown"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <!-- "Call Banner" for primary call, the foregound or ringing call.
- The "call banner" is a block of info about a single call,
- including the contact name, phone number, call time counter,
- and other status info. This info is shown as a "banner"
- overlaid across the top of contact photo. -->
- <GridLayout android:id="@+id/primary_call_banner"
- style="@style/PrimaryCallInfoPrimaryCallBanner"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/call_banner_height"
- android:background="@color/incall_call_banner_background"
- android:paddingStart="@dimen/call_banner_side_padding"
- android:paddingEnd="@dimen/call_banner_side_padding"
- android:paddingTop="@dimen/call_banner_top_bottom_padding"
- android:paddingBottom="@dimen/call_banner_top_bottom_padding"
- >
-
- <!-- Name (or the phone number, if we don't have a name to display). -->
- <TextView android:id="@+id/name"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/incall_call_banner_text_color"
- android:singleLine="true"
- android:textAlignment="viewStart"
- android:layout_column="0"
- android:layout_row="0"
- android:layout_columnSpan="2"
- android:layout_gravity="fill"/>
-
- <!-- Label (like "Mobile" or "Work", if present) and phone number, side by side -->
- <TextView android:id="@+id/phoneNumber"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:singleLine="true"
- android:textDirection="ltr"
- android:layout_column="0"
- android:layout_row="1"
- android:layout_gravity="fill"/>
-
- <TextView android:id="@+id/label"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:textAllCaps="true"
- android:singleLine="true"
- android:paddingStart="6dp"
- android:layout_column="1"
- android:layout_row="1"
- android:layout_gravity="fill"/>
-
- <!-- Call type indication: a special label and/or branding
- for certain kinds of calls (like "Internet call" for a SIP call.) -->
- <TextView android:id="@+id/callTypeLabel"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:maxLines="1"
- android:layout_column="0"
- android:layout_row="2"
- android:layout_columnSpan="2"
- android:ellipsize="end"
- android:layout_gravity="fill"/>
-
- <!-- Elapsed time indication for a call in progress. -->
- <TextView android:id="@+id/elapsedTime"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/incall_call_banner_text_color"
- android:singleLine="true"
- android:visibility="invisible"
- android:layout_column="2"
- android:layout_row="0"
- android:layout_rowSpan="3"
- android:layout_gravity="fill"
- android:gravity="end|center_vertical"/>
- </GridLayout>
- <!-- End of call_banner -->
-
-
- <!-- The "call state label": In some states, this shows a special
- indication like "Dialing" or "Incoming call" or "Call ended".
- It's unused for the normal case of an active ongoing call. -->
- <TextView android:id="@+id/callStateLabel"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/provider_info_top_bottom_padding"
- android:paddingBottom="@dimen/provider_info_top_bottom_padding"
- android:paddingStart="@dimen/call_banner_side_padding"
- android:paddingEnd="@dimen/call_banner_side_padding"
- android:gravity="end"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:textAllCaps="true"
- android:background="@color/incall_secondary_info_background"
- android:singleLine="true"
- android:ellipsize="end"/>
-
- </LinearLayout>
-
-
-</FrameLayout> \ No newline at end of file
diff --git a/InCallUI/res/layout/primary_call_info.xml b/InCallUI/res/layout/primary_call_info.xml
index 39c3873d0..251ded30b 100644
--- a/InCallUI/res/layout/primary_call_info.xml
+++ b/InCallUI/res/layout/primary_call_info.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+
<!--
~ Copyright (C) 2013 The Android Open Source Project
~
@@ -15,199 +16,120 @@
~ limitations under the License
-->
-<!-- XML resource file for primary call info, which will be used by CallCard.
- See also call_card.xml. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1">
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
<!-- Contact photo for primary call info -->
<ImageView android:id="@+id/photo"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="top|center_horizontal"
- android:scaleType="centerCrop"
- android:contentDescription="@string/contactPhoto" />
-
- <!-- Used when the phone call is on hold, dimming the primary photo
-
- Note: Theoretically it is possible to achieve this effect using
- Drawable#setColorFilter().
-
- But watch out: we also use cross fade between primary and
- secondary photo, which may interfere with the dim effect with
- setColorFilter(). To try it out, use GSM phones and do multiple
- calls.
-
- Detail: during the cross-fade effect we are currently using
- TransitionDrawable. TransitionDrawable#setColorFilter() will call
- the equivalent method for *both* drawables which are shared by
- the two ImageViews. If we set setColorFilter() for "on hold" effect
- during the cross-fade, *both* primary and secondary photos become
- dim.
-
- Theoretically it can be avoided (by copying drawable, or carefully
- calling setColorFilter() conditionally. But it doesn't bang for the
- buck for now.
-
- TODO: try that. It may be smoother with slower devices.
- -->
- <View android:id="@+id/dim_effect_for_primary_photo"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/on_hold_dim_effect"
- android:visibility="gone" />
-
- <!-- "Call Banner" for primary call, the foregound or ringing call.
- The "call banner" is a block of info about a single call,
- including the contact name, phone number, call time counter,
- and other status info. This info is shown as a "banner"
- overlaid across the top of contact photo. -->
- <RelativeLayout android:id="@+id/primary_call_banner"
- style="@style/PrimaryCallInfoPrimaryCallBanner"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/call_banner_height"
- android:paddingStart="@dimen/call_banner_side_padding"
- android:paddingEnd="@dimen/call_banner_side_padding"
- android:paddingTop="@dimen/call_banner_top_bottom_padding"
- android:paddingBottom="@dimen/call_banner_top_bottom_padding"
- android:background="@color/incall_call_banner_background">
-
- <!-- Name (or the phone number, if we don't have a name to display). -->
- <TextView android:id="@+id/name"
- android:layout_alignParentTop="true"
- android:layout_alignParentStart="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="top|center_horizontal"
+ android:scaleType="centerCrop"
+ android:contentDescription="@string/contactPhoto"
+ android:src="@drawable/picture_unknown"/>
+
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingEnd="@dimen/call_banner_name_number_right_padding"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/incall_call_banner_text_color"
- android:singleLine="true"
- android:textAlignment="viewStart"/>
-
- <!-- Label (like "Mobile" or "Work", if present) and phone number, side by side -->
- <LinearLayout android:id="@+id/labelAndNumber"
- android:layout_below="@id/name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingEnd="@dimen/call_banner_name_number_right_padding"
- android:orientation="horizontal">
+ android:orientation="vertical">
+
+ <!-- "Call Banner" for primary call, the foregound or ringing call.
+ The "call banner" is a block of info about a single call,
+ including the contact name, phone number, call time counter,
+ and other status info. This info is shown as a "banner"
+ overlaid across the top of contact photo. -->
+ <GridLayout android:id="@+id/primary_call_banner"
+ style="@style/PrimaryCallInfoPrimaryCallBanner"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/call_banner_height"
+ android:background="@color/incall_call_banner_background"
+ android:paddingStart="@dimen/call_banner_side_padding"
+ android:paddingEnd="@dimen/call_banner_side_padding"
+ android:paddingTop="@dimen/call_banner_top_bottom_padding"
+ android:paddingBottom="@dimen/call_banner_top_bottom_padding">
+
+ <!-- Name (or the phone number, if we don't have a name to display). -->
+ <TextView android:id="@+id/name"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/incall_call_banner_text_color"
+ android:singleLine="true"
+ android:textAlignment="viewStart"
+ android:layout_column="0"
+ android:layout_row="0"
+ android:layout_columnSpan="2"
+ android:layout_gravity="fill"/>
+
+ <!-- Label (like "Mobile" or "Work", if present) and phone number, side by side -->
<TextView android:id="@+id/phoneNumber"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:singleLine="true"
- android:textDirection="ltr" />
- <TextView android:id="@+id/label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:textAllCaps="true"
- android:singleLine="true"
- android:layout_marginStart="6dp" />
- </LinearLayout>
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="@color/incall_call_banner_text_color"
+ android:singleLine="true"
+ android:textDirection="ltr"
+ android:layout_column="0"
+ android:layout_row="1"
+ android:layout_gravity="fill"/>
- <!-- Elapsed time indication for a call in progress. -->
- <TextView android:id="@+id/elapsedTime"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/incall_call_banner_text_color"
- android:singleLine="true"
- android:visibility="invisible" />
-
- <!-- Call type indication: a special label and/or branding
- for certain kinds of calls (like "Internet call" for a SIP call.) -->
- <TextView android:id="@+id/callTypeLabel"
- android:layout_below="@id/labelAndNumber"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:maxLines="1"
- android:ellipsize="end" />
-
- </RelativeLayout> <!-- End of call_banner -->
-
- <LinearLayout android:id="@+id/secondary_info_container"
- style="@style/PrimaryCallInfoSecondaryInfoContainer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|right"
- android:orientation="vertical"
- android:background="@color/incall_secondary_info_background"
- android:animateLayoutChanges="true">
+ <TextView android:id="@+id/label"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="@color/incall_call_banner_text_color"
+ android:textAllCaps="true"
+ android:singleLine="true"
+ android:paddingStart="6dp"
+ android:layout_column="1"
+ android:layout_row="1"
+ android:layout_gravity="fill"/>
+
+ <!-- Call type indication: a special label and/or branding
+ for certain kinds of calls (like "Internet call" for a SIP call.) -->
+ <TextView android:id="@+id/callTypeLabel"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="@color/incall_call_banner_text_color"
+ android:maxLines="1"
+ android:layout_column="0"
+ android:layout_row="2"
+ android:layout_columnSpan="2"
+ android:ellipsize="end"
+ android:layout_gravity="fill"/>
+
+ <!-- Elapsed time indication for a call in progress. -->
+ <TextView android:id="@+id/elapsedTime"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/incall_call_banner_text_color"
+ android:singleLine="true"
+ android:visibility="invisible"
+ android:layout_column="2"
+ android:layout_row="0"
+ android:layout_rowSpan="3"
+ android:layout_gravity="fill"
+ android:gravity="end|center_vertical"/>
+ </GridLayout>
+ <!-- End of call_banner -->
- <!-- Shown when a gateway provider is used during any outgoing call. -->
- <LinearLayout android:id="@+id/providerInfo"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/provider_info_top_bottom_padding"
- android:paddingBottom="@dimen/provider_info_top_bottom_padding"
- android:paddingStart="@dimen/call_banner_side_padding"
- android:paddingEnd="@dimen/call_banner_side_padding"
- android:gravity="end"
- android:orientation="horizontal"
- android:background="@android:color/transparent">
- <TextView android:id="@+id/providerLabel"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="6"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textAllCaps="true"
- android:textColor="@color/incall_call_banner_text_color"
- android:singleLine="true"
- android:ellipsize="marquee" />
- <TextView android:id="@+id/providerAddress"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="4"
- android:gravity="end"
- android:paddingStart="8dp"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textAllCaps="true"
- android:textColor="@color/incall_call_banner_text_color"
- android:singleLine="true"
- android:ellipsize="middle" />
- </LinearLayout>
<!-- The "call state label": In some states, this shows a special
indication like "Dialing" or "Incoming call" or "Call ended".
It's unused for the normal case of an active ongoing call. -->
<TextView android:id="@+id/callStateLabel"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/provider_info_top_bottom_padding"
- android:paddingBottom="@dimen/provider_info_top_bottom_padding"
- android:paddingStart="@dimen/call_banner_side_padding"
- android:paddingEnd="@dimen/call_banner_side_padding"
- android:gravity="end"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:textAllCaps="true"
- android:background="@android:color/transparent"
- android:singleLine="true"
- android:ellipsize="end" />
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/provider_info_top_bottom_padding"
+ android:paddingBottom="@dimen/provider_info_top_bottom_padding"
+ android:paddingStart="@dimen/call_banner_side_padding"
+ android:paddingEnd="@dimen/call_banner_side_padding"
+ android:gravity="end"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="@color/incall_call_banner_text_color"
+ android:textAllCaps="true"
+ android:background="@color/incall_secondary_info_background"
+ android:singleLine="true"
+ android:ellipsize="end"/>
+
</LinearLayout>
- <!-- Social status (currently unused) -->
- <!-- <TextView android:id="@+id/socialStatus"
- android:layout_below="@id/callTypeLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/incall_call_banner_text_color"
- android:maxLines="2"
- android:ellipsize="end"
- /> -->
-</LinearLayout>
+
+</FrameLayout>
diff --git a/InCallUI/res/layout/secondary_call_info.xml b/InCallUI/res/layout/secondary_call_info.xml
new file mode 100644
index 000000000..546278f95
--- /dev/null
+++ b/InCallUI/res/layout/secondary_call_info.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- XML resource file for secondary call info, which will be used by CallCard.
+ See also call_card.xml.
+
+ This should look similar to primary call info (primary_call_info.xml), but
+ to optimize the view usage, the structure is different. -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- Contact photo for call_info #2 -->
+ <ImageView android:id="@+id/secondaryCallPhoto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="top|center_horizontal"
+ android:scaleType="centerCrop"
+ android:contentDescription="@string/onHold" />
+
+ <!-- TODO(klp): Add clickable dim effect -->
+
+ <!-- Name (or the phone number, if we don't have a name to display). -->
+ <TextView android:id="@+id/secondaryCallName"
+ style="@style/SecondaryCallInfoSecondaryCallName"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/call_banner_height"
+ android:gravity="top|start"
+ android:paddingStart="@dimen/call_banner_side_padding"
+ android:paddingEnd="@dimen/call_banner_side_padding"
+ android:paddingTop="@dimen/call_banner_top_bottom_padding"
+ android:paddingBottom="@dimen/call_banner_top_bottom_padding"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/incall_call_banner_text_color"
+ android:singleLine="true"
+ android:background="@color/incall_call_banner_background" />
+
+ <!-- Call status of the background call, usually the string "On hold". -->
+ <TextView android:id="@+id/secondaryCallStatus"
+ style="@style/SecondaryCallInfoSecondaryCallStatus"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/call_banner_height"
+ android:gravity="top|end"
+ android:paddingStart="@dimen/call_banner_side_padding"
+ android:paddingEnd="@dimen/call_banner_side_padding"
+ android:paddingTop="@dimen/call_banner_top_bottom_padding"
+ android:paddingBottom="@dimen/call_banner_top_bottom_padding"
+ android:text="@string/onHold"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="@color/incall_call_banner_text_color"
+ android:textAllCaps="true"
+ android:singleLine="true" />
+</FrameLayout>
diff --git a/InCallUI/res/values/strings.xml b/InCallUI/res/values/strings.xml
index d92dc16e5..df88e7e56 100755
--- a/InCallUI/res/values/strings.xml
+++ b/InCallUI/res/values/strings.xml
@@ -20,6 +20,11 @@
<!-- Official label for the in-call UI -->
<string name="inCallLabel">InCallUI</string>
+ <!-- Call status -->
+
+ <!-- In-call screen: status label for a call that's on hold -->
+ <string name="onHold">On hold</string>
+
<!-- "Audio mode" popup menu: Item label to select the speakerphone [CHAR LIMIT=25] -->
<string name="audio_mode_speaker">Speaker</string>
<!-- "Audio mode" popup menu: Item label to select the handset earpiece [CHAR LIMIT=25] -->
diff --git a/InCallUI/src/com/android/incallui/AnswerFragment.java b/InCallUI/src/com/android/incallui/AnswerFragment.java
index 90bc43608..76c925163 100644
--- a/InCallUI/src/com/android/incallui/AnswerFragment.java
+++ b/InCallUI/src/com/android/incallui/AnswerFragment.java
@@ -16,6 +16,9 @@
package com.android.incallui;
+import com.google.common.base.Preconditions;
+
+import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -26,16 +29,22 @@ import android.view.ViewGroup;
*
*/
public class AnswerFragment extends BaseFragment<AnswerPresenter> implements
- GlowPadWrapper.AnswerListener {
+ GlowPadWrapper.AnswerListener, AnswerPresenter.AnswerUi {
+ final private IFragmentHost mFragmentHost;
+
+ public AnswerFragment(IFragmentHost fragmentHost) {
+ mFragmentHost = fragmentHost;
+
+ // Normally called with onCreateView, however, AnswerPresenter's interaction
+ // begins before any UI is displayed.
+ // Order matters with this call because mFragmentHost mustn't be null when the presenter
+ // asks AnswerFragment to display itself (see showAnswerWidget).
+ getPresenter().onUiReady(this);
+ }
@Override
public AnswerPresenter createPresenter() {
- return new AnswerPresenter(new AnswerPresenter.Listener() {
- @Override
- public void onClose() {
- close();
- }
- });
+ return new AnswerPresenter();
}
@Override
@@ -47,12 +56,6 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter> implements
return glowPad;
}
- private void close() {
- final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
- fragmentTransaction.remove(this);
- fragmentTransaction.commit();
- }
-
@Override
public void onAnswer() {
getPresenter().onAnswer();
@@ -67,4 +70,34 @@ public class AnswerFragment extends BaseFragment<AnswerPresenter> implements
public void onText() {
getPresenter().onText();
}
+
+ @Override
+ public void showAnswerWidget(boolean show) {
+ Preconditions.checkNotNull(mFragmentHost);
+
+ if (show) {
+ mFragmentHost.addFragment(this);
+ } else {
+ close();
+ }
+ }
+
+ private void close() {
+ // TODO(klp): With a proper main presenter, we will not need to check for isAdded.
+ if (isAdded()) {
+ final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction.remove(this);
+ fragmentTransaction.commit();
+ }
+ }
+
+ // Stop gap until we can consolidate presenters and make InCallActivity a UI Class that relies
+ // on it's the consolidated presenter.
+ //
+ // TODO(klp): Remove individual presenters for button/answer/callcard and have a single
+ // presenter that interacts directly with this activity. This will allow us to remove
+ // this unnecessary interface.
+ static interface IFragmentHost {
+ public void addFragment(Fragment fragment);
+ }
}
diff --git a/InCallUI/src/com/android/incallui/AnswerPresenter.java b/InCallUI/src/com/android/incallui/AnswerPresenter.java
index d6f87c74c..a406b0a2b 100644
--- a/InCallUI/src/com/android/incallui/AnswerPresenter.java
+++ b/InCallUI/src/com/android/incallui/AnswerPresenter.java
@@ -16,46 +16,45 @@
package com.android.incallui;
-import com.google.android.collect.Lists;
-
-import java.util.ArrayList;
-
/**
- *
+ * Presenter for the Incoming call widget.
*/
-public class AnswerPresenter extends Presenter<Ui> {
+public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
+ implements CallList.Listener {
- private ArrayList<Listener> mListeners = Lists.newArrayList();
-
- public AnswerPresenter(Listener listener) {
- this.mListeners.add(listener);
+ @Override
+ public void onUiReady(AnswerUi ui) {
+ super.onUiReady(ui);
+ CallList.getInstance().addListener(this);
}
- public void addCloseListener(Listener listener) {
- mListeners.add(listener);
+ @Override
+ public void onCallListChange(CallList callList) {
+ // TODO(klp): The answer widget and call cards are independently managing their behavior
+ // from CallList events. We need to create a class to manage the behavior of all the
+ // Presenters from a single place.
+ final boolean showWidget = (callList.getIncomingCall() != null);
+
+ final AnswerUi ui = getUi();
+ if (ui != null) {
+ ui.showAnswerWidget(showWidget);
+ }
}
public void onAnswer() {
// TODO(klp): hook in call id.
CallCommandClient.getInstance().answerCall(1);
- notifyListeners();
}
public void onDecline() {
- notifyListeners();
+ // TODO(klp): hook in call id.
+ CallCommandClient.getInstance().disconnectCall(1);
}
public void onText() {
- notifyListeners();
- }
-
- private void notifyListeners() {
- for (Listener listener : mListeners) {
- listener.onClose();
- }
}
- public interface Listener {
- void onClose();
+ interface AnswerUi extends Ui {
+ public void showAnswerWidget(boolean show);
}
}
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index be76f2d21..10d4f7237 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -21,10 +21,10 @@ import android.media.AudioManager;
/**
* Logic for call buttons.
*/
-public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButtonUi> {
+public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButtonUi>
+ implements CallList.Listener {
private AudioManager mAudioManager;
- private EndCallListener mEndCallListener;
public void init(AudioManager audioManager) {
mAudioManager = audioManager;
@@ -35,19 +35,26 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
super.onUiReady(ui);
getUi().setMute(mAudioManager.isMicrophoneMute());
getUi().setSpeaker(mAudioManager.isSpeakerphoneOn());
+
+ CallList.getInstance().addListener(this);
}
- public void show() {
- getUi().setVisible(true);
+ @Override
+ public void onCallListChange(CallList callList) {
+ // show the buttons if there is a live call AND there is no
+ // incoming call.
+ final boolean showButtons = callList.existsLiveCall() &&
+ callList.getIncomingCall() == null;
+ getUi().setVisible(showButtons);
}
public void endCallClicked() {
// TODO(klp): hook up call id.
CallCommandClient.getInstance().disconnectCall(1);
- mEndCallListener.onCallEnd();
-
- // TODO(klp): These states should come from Call objects from the CallList.
+ // TODO(klp): Remove once all state is gathered from CallList.
+ // This will be wrong when you disconnect from a call if
+ // the user has another call on hold.
reset();
}
@@ -74,18 +81,10 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
getUi().setHold(checked);
}
- public void setEndCallListener(EndCallListener endCallListener) {
- mEndCallListener = endCallListener;
- }
-
public interface CallButtonUi extends Ui {
void setVisible(boolean on);
void setMute(boolean on);
void setSpeaker(boolean on);
void setHold(boolean on);
}
-
- public interface EndCallListener {
- void onCallEnd();
- }
}
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index 2fb317221..3f46bb568 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -20,6 +20,7 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import android.widget.TextView;
/**
@@ -30,6 +31,9 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter>
private TextView mPhoneNumber;
+ private ViewStub mSecondaryCallInfo;
+ private TextView mSecondaryCallName;
+
@Override
CallCardPresenter createPresenter() {
return new CallCardPresenter();
@@ -38,12 +42,13 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter>
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- return inflater.inflate(R.layout.call_card_fragment, container, false);
+ return inflater.inflate(R.layout.call_card, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mPhoneNumber = (TextView) view.findViewById(R.id.phoneNumber);
+ mSecondaryCallInfo = (ViewStub) view.findViewById(R.id.secondary_call_info);
// This method call will begin the callbacks on CallCardUi. We need to ensure
// everything needed for the callbacks is set up before this is called.
@@ -51,6 +56,18 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter>
}
@Override
+ public void setSecondaryCallInfo(boolean show, String number) {
+ if (show) {
+ showAndInitializeSecondaryCallInfo();
+
+ // Until we have the name source, use the number as the main text for secondary calls.
+ mSecondaryCallName.setText(number);
+ } else {
+ mSecondaryCallInfo.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
public void setNumber(String number) {
mPhoneNumber.setText(number);
}
@@ -59,4 +76,14 @@ public class CallCardFragment extends BaseFragment<CallCardPresenter>
public void setName(String name) {
}
+ private void showAndInitializeSecondaryCallInfo() {
+ mSecondaryCallInfo.setVisibility(View.VISIBLE);
+
+ // mSecondaryCallName is initialized here (vs. onViewCreated) because it is inaccesible
+ // until mSecondaryCallInfo is inflated in the call above.
+ if (mSecondaryCallName == null) {
+ mSecondaryCallName = (TextView) getView().findViewById(R.id.secondaryCallName);
+ }
+ }
+
}
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index 85f05341e..0ba4176c3 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -30,26 +30,36 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
super.onUiReady(ui);
CallList.getInstance().addListener(this);
-
- // When UI is ready, manually trigger a change
- onCallListChange(CallList.getInstance());
}
@Override
public void onCallListChange(CallList callList) {
- Call call = callList.getIncomingOrActive();
+ final CallCardUi ui = getUi();
+ // Populate the primary call card based on the incoming call or the active call.
+ final Call call = callList.getIncomingOrActive();
if (call != null) {
- getUi().setNumber(call.getNumber());
+ ui.setNumber(call.getNumber());
} else {
// When there is no longer an incoming/active call, we need to reset everything
// so that no data survives for the next call.
- getUi().setNumber("");
+ ui.setNumber("");
+ }
+
+ // secondary call card info only comes from the background call (if any exist)
+ final Call backgroundCall = callList.getBackgroundCall();
+ if (backgroundCall != null) {
+ ui.setSecondaryCallInfo(true, backgroundCall.getNumber());
+ } else {
+ ui.setSecondaryCallInfo(false, null);
}
}
public interface CallCardUi extends Ui {
+ // TODO(klp): Consider passing in the Call object directly in these methods.
+
public void setNumber(String number);
public void setName(String name);
+ public void setSecondaryCallInfo(boolean show, String number);
}
}
diff --git a/InCallUI/src/com/android/incallui/CallHandlerService.java b/InCallUI/src/com/android/incallui/CallHandlerService.java
index 4a14dab8e..a9516e8ad 100644
--- a/InCallUI/src/com/android/incallui/CallHandlerService.java
+++ b/InCallUI/src/com/android/incallui/CallHandlerService.java
@@ -70,6 +70,8 @@ public class CallHandlerService extends Service {
@Override
public void onIncomingCall(Call call) {
+ // TODO(klp): New presenter manager should launch this task...not this service.
+ // TODO(klp): Update the flags to match the only activity
final Intent intent = new Intent(getApplication(), InCallActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java
index ac3e3bfd5..f41af930b 100644
--- a/InCallUI/src/com/android/incallui/CallList.java
+++ b/InCallUI/src/com/android/incallui/CallList.java
@@ -82,7 +82,11 @@ public class CallList {
public void addListener(Listener listener) {
Preconditions.checkNotNull(listener);
+
mListeners.add(listener);
+
+ // Let the listener know about the active calls immediately.
+ listener.onCallListChange(this);
}
public void removeListener(Listener listener) {
@@ -96,15 +100,39 @@ public class CallList {
* update the Call object when the active call changes.
*/
public Call getIncomingOrActive() {
- Call retval = null;
+ Call retval = getIncomingCall();
+ if (retval == null) {
+ retval = getFirstCallWithState(Call.State.ACTIVE);
+ }
+ return retval;
+ }
+
+ public Call getBackgroundCall() {
+ return getFirstCallWithState(Call.State.ONHOLD);
+ }
+
+ public Call getIncomingCall() {
+ return getFirstCallWithState(Call.State.INCOMING);
+ }
+ public boolean existsLiveCall() {
for (Call call : mCallMap.values()) {
- if (call.getState() == Call.State.INCOMING) {
+ if (!isCallDead(call)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns first call found in the call map with the specified state.
+ */
+ public Call getFirstCallWithState(int state) {
+ Call retval = null;
+ for (Call call : mCallMap.values()) {
+ if (call.getState() == state) {
retval = call;
- // incoming call takes precedence, cut out early.
break;
- } else if (retval == null && call.getState() == Call.State.ACTIVE) {
- retval = call;
}
}
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index 04f1f09b1..9732203bd 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -17,6 +17,7 @@
package com.android.incallui;
import android.app.Activity;
+import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
@@ -30,15 +31,17 @@ import android.widget.Toast;
/**
* Phone app "in call" screen.
*/
-public class InCallActivity extends Activity implements CallButtonPresenter.EndCallListener {
+public class InCallActivity extends Activity implements AnswerFragment.IFragmentHost,
+ CallList.Listener {
private static final String TAG = InCallActivity.class.getSimpleName();
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
- private CallButtonPresenter mCallButtonPresenter;
- private CallCardPresenter mCallCardPresenter;
+ private CallButtonFragment mCallButtonFragment;
+ private CallCardFragment mCallCardFragment;
+ private AnswerFragment mAnswerFragment;
@Override
protected void onCreate(Bundle icicle) {
@@ -68,19 +71,6 @@ public class InCallActivity extends Activity implements CallButtonPresenter.EndC
protected void onResume() {
logD("onResume()...");
- // TODO(klp): create once and reset when needed.
- final AnswerFragment answerFragment = new AnswerFragment();
- final AnswerPresenter presenter = answerFragment.getPresenter();
- presenter.addCloseListener(new AnswerPresenter.Listener() {
- @Override
- public void onClose() {
- mCallButtonPresenter.show();
- }
- });
-
- final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
- fragmentTransaction.add(R.id.main, answerFragment);
- fragmentTransaction.commit();
super.onResume();
}
@@ -207,13 +197,23 @@ public class InCallActivity extends Activity implements CallButtonPresenter.EndC
private void initializeInCall() {
- final CallButtonFragment callButtonFragment = (CallButtonFragment) getFragmentManager()
- .findFragmentById(R.id.callButtonFragment);
- mCallButtonPresenter = callButtonFragment.getPresenter();
- mCallButtonPresenter.setEndCallListener(this);
+ // TODO(klp): Make sure that this doesn't need to move back to onResume() since they are
+ // statically added fragments.
+ if (mCallButtonFragment == null) {
+ mCallButtonFragment = (CallButtonFragment) getFragmentManager()
+ .findFragmentById(R.id.callButtonFragment);
+ }
+
+ if (mCallCardFragment == null) {
+ mCallCardFragment = (CallCardFragment) getFragmentManager()
+ .findFragmentById(R.id.callCardFragment);
+ }
+
+ if (mAnswerFragment == null) {
+ mAnswerFragment = new AnswerFragment(this);
+ }
- final CallCardFragment callCardFragment = (CallCardFragment) getFragmentManager()
- .findFragmentById(R.id.callCardFragment);
+ CallList.getInstance().addListener(this);
}
private void toast(String text) {
@@ -229,7 +229,24 @@ public class InCallActivity extends Activity implements CallButtonPresenter.EndC
}
@Override
- public void onCallEnd() {
- finish();
+ public void addFragment(Fragment fragment) {
+ Log.d(TAG, "AddFragment");
+
+ // TODO(klp): Do a check to make sure the fragment isn't already added before trying to
+ // add it again.
+ // TODO(klp): IsResumed check only required because CallList notifications are coming in
+ // an indeterminate order. This should no longer be required with a main Presenter class.
+ if (this.isResumed()) {
+ final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction.add(R.id.main, fragment);
+ fragmentTransaction.commit();
+ }
+ }
+
+ @Override
+ public void onCallListChange(CallList callList) {
+ if (!callList.existsLiveCall()) {
+ finish();
+ }
}
}