summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/layout/call_detail.xml6
-rw-r--r--res/layout/call_log_list_item_actions.xml19
-rw-r--r--res/layout/voicemail_playback_layout.xml (renamed from res/layout/playback_layout.xml)0
-rw-r--r--src/com/android/dialer/CallDetailActivity.java58
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapter.java25
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java17
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemHelper.java4
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemViewHolder.java48
-rw-r--r--src/com/android/dialer/list/ListsFragment.java14
-rw-r--r--src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java10
-rw-r--r--src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java162
-rw-r--r--src/com/android/dialerbind/ObjectFactory.java3
-rw-r--r--tests/src/com/android/dialer/calllog/CallLogAdapterTest.java2
-rw-r--r--tests/src/com/android/dialer/calllog/CallLogFragmentTest.java31
-rw-r--r--tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java10
15 files changed, 200 insertions, 209 deletions
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index 5d1607edf..c07785159 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -87,12 +87,6 @@
</LinearLayout>
</LinearLayout>
- <com.android.dialer.voicemail.VoicemailPlaybackLayout
- android:id="@+id/voicemail_playback_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone" />
-
<!--
The list view is under everything.
It contains a first header element which is hidden under the controls UI.
diff --git a/res/layout/call_log_list_item_actions.xml b/res/layout/call_log_list_item_actions.xml
index d3e18be28..f1d0e9ec8 100644
--- a/res/layout/call_log_list_item_actions.xml
+++ b/res/layout/call_log_list_item_actions.xml
@@ -23,6 +23,11 @@
android:visibility="visible"
android:importantForAccessibility="1">
+ <com.android.dialer.voicemail.VoicemailPlaybackLayout
+ android:id="@+id/voicemail_playback_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
<LinearLayout
android:id="@+id/video_call_action"
style="@style/CallLogActionStyle">
@@ -38,20 +43,6 @@
</LinearLayout>
<LinearLayout
- android:id="@+id/voicemail_action"
- style="@style/CallLogActionStyle">
-
- <ImageView
- style="@style/CallLogActionIconStyle"
- android:src="@drawable/ic_voicemail_24dp" />
-
- <TextView
- style="@style/CallLogActionTextStyle"
- android:text="@string/call_log_action_voicemail" />
-
- </LinearLayout>
-
- <LinearLayout
android:id="@+id/create_new_contact_action"
style="@style/CallLogActionStyle">
diff --git a/res/layout/playback_layout.xml b/res/layout/voicemail_playback_layout.xml
index 96feba648..96feba648 100644
--- a/res/layout/playback_layout.xml
+++ b/res/layout/voicemail_playback_layout.xml
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index ce29049d3..6da7c798c 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -61,8 +61,6 @@ import com.android.dialer.calllog.PhoneNumberUtilsWrapper;
import com.android.dialer.util.IntentUtil;
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.TelecomUtil;
-import com.android.dialer.voicemail.VoicemailPlaybackLayout;
-import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
import java.util.List;
@@ -218,8 +216,6 @@ public class CallDetailActivity extends Activity {
/** Helper to load contact photos. */
private ContactPhotoManager mContactPhotoManager;
- private VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
-
private Uri mVoicemailUri;
private BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
@@ -255,8 +251,6 @@ public class CallDetailActivity extends Activity {
mContactInfoHelper = new ContactInfoHelper(this, GeoUtil.getCurrentCountryIso(this));
getActionBar().setDisplayHomeAsUpEnabled(true);
- optionallyHandleVoicemail();
-
if (getIntent().getBooleanExtra(EXTRA_FROM_NOTIFICATION, false)) {
closeSystemDialogs();
}
@@ -269,58 +263,6 @@ public class CallDetailActivity extends Activity {
CallLogAsyncTaskUtil.getCallDetails(this, getCallLogEntryUris(), mCallLogAsyncTaskListener);
}
- @Override
- public void onPause() {
- if (mVoicemailPlaybackPresenter != null) {
- mVoicemailPlaybackPresenter.onPause(isFinishing());
- }
- super.onPause();
- }
-
- @Override
- public void onDestroy() {
- if (mVoicemailPlaybackPresenter != null) {
- mVoicemailPlaybackPresenter.onDestroy(isFinishing());
- }
- super.onDestroy();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (mVoicemailPlaybackPresenter != null) {
- mVoicemailPlaybackPresenter.onSaveInstanceState(outState);
- }
- }
-
- @Override
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- if (mVoicemailPlaybackPresenter != null) {
- mVoicemailPlaybackPresenter.onRestoreInstanceState(savedInstanceState);
- }
- super.onRestoreInstanceState(savedInstanceState);
- }
-
- /**
- * Handle voicemail playback or hide voicemail ui.
- * <p>
- * If the Intent used to start this Activity contains the suitable extras, then start voicemail
- * playback. If it doesn't, then don't inflate the voicemail ui.
- */
- private void optionallyHandleVoicemail() {
- if (hasVoicemail()) {
- VoicemailPlaybackLayout voicemailPlaybackLayout =
- (VoicemailPlaybackLayout) findViewById(R.id.voicemail_playback_layout);
-
- mVoicemailPlaybackPresenter = new VoicemailPlaybackPresenter(this);
- mVoicemailPlaybackPresenter.setPlaybackView(
- voicemailPlaybackLayout, mVoicemailUri, false /* startPlayingImmediately */);
-
- voicemailPlaybackLayout.setVisibility(View.VISIBLE);
- CallLogAsyncTaskUtil.markVoicemailAsRead(this, mVoicemailUri);
- }
- }
-
private boolean hasVoicemail() {
return mVoicemailUri != null;
}
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index c472ef2ca..6862f68e2 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -22,6 +22,7 @@ import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
+import android.os.Bundle;
import android.os.Trace;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.telecom.PhoneAccountHandle;
@@ -41,6 +42,7 @@ import com.android.dialer.R;
import com.android.dialer.contactinfo.ContactInfoCache;
import com.android.dialer.contactinfo.ContactInfoCache.OnContactInfoChangedListener;
import com.android.dialer.util.DialerUtils;
+import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
import com.google.common.annotations.VisibleForTesting;
@@ -67,6 +69,7 @@ public class CallLogAdapter extends GroupingListAdapter
protected final Context mContext;
private final ContactInfoHelper mContactInfoHelper;
+ private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
private final CallFetcher mCallFetcher;
private final OnReportButtonClickListener mOnReportButtonClickListener;
private ViewTreeObserver mViewTreeObserver = null;
@@ -75,6 +78,9 @@ public class CallLogAdapter extends GroupingListAdapter
private boolean mIsShowingRecentsTab;
+ private static final String KEY_EXPANDED_POSITION = "expanded_position";
+ private static final String KEY_EXPANDED_ROW_ID = "expanded_row_id";
+
// Tracks the position of the currently expanded list item.
private int mCurrentlyExpandedPosition = RecyclerView.NO_POSITION;
// Tracks the rowId of the currently expanded list item, so the position can be updated if there
@@ -200,6 +206,7 @@ public class CallLogAdapter extends GroupingListAdapter
Context context,
CallFetcher callFetcher,
ContactInfoHelper contactInfoHelper,
+ VoicemailPlaybackPresenter voicemailPlaybackPresenter,
boolean isShowingRecentsTab,
OnReportButtonClickListener onReportButtonClickListener) {
super(context);
@@ -207,6 +214,7 @@ public class CallLogAdapter extends GroupingListAdapter
mContext = context;
mCallFetcher = callFetcher;
mContactInfoHelper = contactInfoHelper;
+ mVoicemailPlaybackPresenter = voicemailPlaybackPresenter;
mIsShowingRecentsTab = isShowingRecentsTab;
mOnReportButtonClickListener = onReportButtonClickListener;
@@ -226,6 +234,20 @@ public class CallLogAdapter extends GroupingListAdapter
mCallLogGroupBuilder = new CallLogGroupBuilder(this);
}
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putInt(KEY_EXPANDED_POSITION, mCurrentlyExpandedPosition);
+ outState.putLong(KEY_EXPANDED_ROW_ID, mCurrentlyExpandedRowId);
+ }
+
+ public void onRestoreInstanceState(Bundle savedInstanceState) {
+ if (savedInstanceState != null) {
+ mCurrentlyExpandedPosition =
+ savedInstanceState.getInt(KEY_EXPANDED_POSITION, RecyclerView.NO_POSITION);
+ mCurrentlyExpandedRowId =
+ savedInstanceState.getLong(KEY_EXPANDED_ROW_ID, NO_EXPANDED_LIST_ITEM);
+ }
+ }
+
/**
* Requery on background thread when {@link Cursor} changes.
*/
@@ -296,7 +318,8 @@ public class CallLogAdapter extends GroupingListAdapter
mContext,
mActionListener,
mPhoneNumberUtilsWrapper,
- mCallLogViewsHelper);
+ mCallLogViewsHelper,
+ mVoicemailPlaybackPresenter);
viewHolder.callLogEntryView.setTag(viewHolder);
viewHolder.callLogEntryView.setAccessibilityDelegate(mAccessibilityDelegate);
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 36d9bb6ea..845f91108 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -51,6 +51,7 @@ import com.android.dialer.R;
import com.android.dialer.list.ListsFragment.HostInterface;
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.EmptyLoader;
+import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
import com.android.dialer.voicemail.VoicemailStatusHelper;
import com.android.dialer.voicemail.VoicemailStatusHelper.StatusMessage;
import com.android.dialer.voicemail.VoicemailStatusHelperImpl;
@@ -87,6 +88,7 @@ public class CallLogFragment extends Fragment
private LinearLayoutManager mLayoutManager;
private CallLogAdapter mAdapter;
private CallLogQueryHandler mCallLogQueryHandler;
+ private VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
private boolean mScrollToTop;
/** Whether there is at least one voicemail source installed. */
@@ -187,6 +189,8 @@ public class CallLogFragment extends Fragment
mContactsObserver);
resolver.registerContentObserver(Status.CONTENT_URI, true, mVoicemailStatusObserver);
setHasOptionsMenu(true);
+
+ mVoicemailPlaybackPresenter = new VoicemailPlaybackPresenter(activity, state);
}
/** Called by the CallLogQueryHandler when the list of calls has been fetched or updated. */
@@ -272,6 +276,7 @@ public class CallLogFragment extends Fragment
getActivity(),
this,
new ContactInfoHelper(getActivity(), currentCountryIso),
+ mVoicemailPlaybackPresenter,
isShowingRecentsTab,
this);
mRecyclerView.setAdapter(mAdapter);
@@ -283,7 +288,9 @@ public class CallLogFragment extends Fragment
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+
updateEmptyMessage(mCallTypeFilter);
+ mAdapter.onRestoreInstanceState(savedInstanceState);
}
/**
@@ -318,8 +325,9 @@ public class CallLogFragment extends Fragment
@Override
public void onPause() {
- super.onPause();
+ mVoicemailPlaybackPresenter.onPause(getActivity().isFinishing());
mAdapter.pauseCache();
+ super.onPause();
}
@Override
@@ -331,12 +339,14 @@ public class CallLogFragment extends Fragment
@Override
public void onDestroy() {
- super.onDestroy();
mAdapter.pauseCache();
mAdapter.changeCursor(null);
+ mVoicemailPlaybackPresenter.onDestroy(getActivity().isFinishing());
+
getActivity().getContentResolver().unregisterContentObserver(mCallLogObserver);
getActivity().getContentResolver().unregisterContentObserver(mContactsObserver);
getActivity().getContentResolver().unregisterContentObserver(mVoicemailStatusObserver);
+ super.onDestroy();
}
@Override
@@ -345,6 +355,9 @@ public class CallLogFragment extends Fragment
outState.putInt(KEY_FILTER_TYPE, mCallTypeFilter);
outState.putInt(KEY_LOG_LIMIT, mLogLimit);
outState.putLong(KEY_DATE_LIMIT, mDateLimit);
+
+ mAdapter.onSaveInstanceState(outState);
+ mVoicemailPlaybackPresenter.onSaveInstanceState(outState);
}
@Override
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index 147a192e3..4eb8797ee 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -91,10 +91,6 @@ import com.android.dialer.R;
mResources.getString(R.string.description_video_call_action),
nameOrNumber));
- views.voicemailButtonView.setContentDescription(
- TextUtils.expandTemplate(
- mResources.getString(R.string.description_voicemail_action), nameOrNumber));
-
views.createNewContactButtonView.setContentDescription(
TextUtils.expandTemplate(
mResources.getString(R.string.description_create_new_contact_action),
diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index ccd480ec6..5125247aa 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -41,6 +41,9 @@ import com.android.contacts.common.util.UriUtils;
import com.android.dialer.PhoneCallDetailsHelper;
import com.android.dialer.PhoneCallDetailsViews;
import com.android.dialer.R;
+import com.android.dialer.calllog.CallLogAsyncTaskUtil;
+import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
+import com.android.dialer.voicemail.VoicemailPlaybackLayout;
/**
* This is an object containing references to views contained by the call log list item. This
@@ -68,8 +71,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
/** The view containing call log item actions. Null until the ViewStub is inflated. */
public View actionsView;
/** The button views below are assigned only when the action section is expanded. */
+ public VoicemailPlaybackLayout voicemailPlaybackView;
public View videoCallButtonView;
- public View voicemailButtonView;
public View createNewContactButtonView;
public View addToExistingContactButtonView;
public View sendMessageView;
@@ -142,6 +145,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
private final View.OnClickListener mActionListener;
private final PhoneNumberUtilsWrapper mPhoneNumberUtilsWrapper;
private final CallLogListItemHelper mCallLogListItemHelper;
+ private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
private final int mPhotoSize;
@@ -150,6 +154,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
View.OnClickListener actionListener,
PhoneNumberUtilsWrapper phoneNumberUtilsWrapper,
CallLogListItemHelper callLogListItemHelper,
+ VoicemailPlaybackPresenter voicemailPlaybackPresenter,
View rootView,
QuickContactBadge quickContactView,
View primaryActionView,
@@ -163,6 +168,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
mActionListener = actionListener;
mPhoneNumberUtilsWrapper = phoneNumberUtilsWrapper;
mCallLogListItemHelper = callLogListItemHelper;
+ mVoicemailPlaybackPresenter = voicemailPlaybackPresenter;
this.rootView = rootView;
this.quickContactView = quickContactView;
@@ -191,13 +197,15 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
Context context,
View.OnClickListener actionListener,
PhoneNumberUtilsWrapper phoneNumberUtilsWrapper,
- CallLogListItemHelper callLogListItemHelper) {
+ CallLogListItemHelper callLogListItemHelper,
+ VoicemailPlaybackPresenter voicemailPlaybackPresenter) {
return new CallLogListItemViewHolder(
context,
actionListener,
phoneNumberUtilsWrapper,
callLogListItemHelper,
+ voicemailPlaybackPresenter,
view,
(QuickContactBadge) view.findViewById(R.id.quick_contact_photo),
view.findViewById(R.id.primary_action_view),
@@ -220,12 +228,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
if (stub != null) {
actionsView = (ViewGroup) stub.inflate();
+ voicemailPlaybackView = (VoicemailPlaybackLayout) actionsView
+ .findViewById(R.id.voicemail_playback_layout);
+
videoCallButtonView = actionsView.findViewById(R.id.video_call_action);
videoCallButtonView.setOnClickListener(mActionListener);
- voicemailButtonView = actionsView.findViewById(R.id.voicemail_action);
- voicemailButtonView.setOnClickListener(mActionListener);
-
createNewContactButtonView = actionsView.findViewById(R.id.create_new_contact_action);
createNewContactButtonView.setOnClickListener(mActionListener);
@@ -302,29 +310,30 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
videoCallButtonView.setVisibility(View.GONE);
}
- // For voicemail calls, show the "VOICEMAIL" action button; hide otherwise.
- if (callType == Calls.VOICEMAIL_TYPE) {
- voicemailButtonView.setTag(
- IntentProvider.getPlayVoicemailIntentProvider(rowId, voicemailUri));
- voicemailButtonView.setVisibility(View.VISIBLE);
+ // For voicemail calls, show the voicemail playback layout; hide otherwise.
+ if (callType == Calls.VOICEMAIL_TYPE && mVoicemailPlaybackPresenter != null) {
+ voicemailPlaybackView.setVisibility(View.VISIBLE);
- detailsButtonView.setVisibility(View.GONE);
- } else {
- voicemailButtonView.setTag(null);
- voicemailButtonView.setVisibility(View.GONE);
+ Uri uri = Uri.parse(voicemailUri);
+ mVoicemailPlaybackPresenter.setPlaybackView(
+ voicemailPlaybackView, uri, false /* startPlayingImmediately */);
- detailsButtonView.setVisibility(View.VISIBLE);
- detailsButtonView.setTag(
- IntentProvider.getCallDetailIntentProvider(rowId, callIds, null));
+ CallLogAsyncTaskUtil.markVoicemailAsRead(mContext, uri);
+ } else {
+ voicemailPlaybackView.setVisibility(View.GONE);
}
+ detailsButtonView.setVisibility(View.VISIBLE);
+ detailsButtonView.setTag(
+ IntentProvider.getCallDetailIntentProvider(rowId, callIds, null));
+
if (canBeReportedAsInvalid && !info.isBadData) {
reportButtonView.setVisibility(View.VISIBLE);
} else {
reportButtonView.setVisibility(View.GONE);
}
- if (UriUtils.isEncodedContactUri(info.lookupUri)) {
+ if (info != null && UriUtils.isEncodedContactUri(info.lookupUri)) {
createNewContactButtonView.setTag(IntentProvider.getAddContactIntentProvider(
info.lookupUri, info.name, info.number, info.type, true /* isNewContact */));
createNewContactButtonView.setVisibility(View.VISIBLE);
@@ -420,6 +429,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
null /* actionListener */,
phoneNumberUtilsWrapper,
new CallLogListItemHelper(phoneCallDetailsHelper, resources),
+ null /* voicemailPlaybackPresenter */,
new View(context),
new QuickContactBadge(context),
new View(context),
@@ -427,10 +437,10 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder {
new CardView(context),
new TextView(context),
new View(context));
- viewHolder.voicemailButtonView = new TextView(context);
viewHolder.detailsButtonView = new TextView(context);
viewHolder.reportButtonView = new TextView(context);
viewHolder.actionsView = new View(context);
+ viewHolder.voicemailPlaybackView = new VoicemailPlaybackLayout(context);
return viewHolder;
}
diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java
index a0e443c22..49226d61e 100644
--- a/src/com/android/dialer/list/ListsFragment.java
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -62,6 +62,9 @@ public class ListsFragment extends Fragment
// Oldest recents entry to display is 2 weeks old.
private static final long OLDEST_RECENTS_DATE = 1000L * 60 * 60 * 24 * 14;
+ private static final String KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER =
+ "has_active_voicemail_provider";
+
public interface HostInterface {
public ActionBarController getActionBarController();
}
@@ -161,6 +164,11 @@ public class ListsFragment extends Fragment
Trace.endSection();
mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
+
+ if (savedInstanceState != null) {
+ mHasActiveVoicemailProvider = savedInstanceState.getBoolean(
+ KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, false);
+ }
Trace.endSection();
}
@@ -227,6 +235,12 @@ public class ListsFragment extends Fragment
}
@Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_HAS_ACTIVE_VOICEMAIL_PROVIDER, mHasActiveVoicemailProvider);
+ }
+
+ @Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
mTabIndex = getRtlPosition(position);
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java b/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
index 0e9ff3bdc..703004d07 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
@@ -76,10 +76,9 @@ public class VoicemailPlaybackLayout extends LinearLayout
public PositionUpdater(
MediaPlayer mediaPlayer,
- int duration,
ScheduledExecutorService executorService) {
mMediaPlayer = mediaPlayer;
- mDuration = duration;
+ mDuration = mediaPlayer.getDuration();
mExecutorService = executorService;
}
@@ -167,6 +166,7 @@ public class VoicemailPlaybackLayout extends LinearLayout
if (mPresenter == null) {
return;
}
+
if (mIsPlaying) {
mPresenter.pausePlayback();
} else {
@@ -197,7 +197,7 @@ public class VoicemailPlaybackLayout extends LinearLayout
mContext = context;
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.playback_layout, this);
+ inflater.inflate(R.layout.voicemail_playback_layout, this);
}
@Override
@@ -222,7 +222,6 @@ public class VoicemailPlaybackLayout extends LinearLayout
@Override
public void onPlaybackStarted(
MediaPlayer mediaPlayer,
- int duration,
ScheduledExecutorService executorService) {
mIsPlaying = true;
@@ -232,7 +231,7 @@ public class VoicemailPlaybackLayout extends LinearLayout
onSpeakerphoneOn(mPresenter.isSpeakerphoneOn());
}
- mPositionUpdater = new PositionUpdater(mediaPlayer, duration, executorService);
+ mPositionUpdater = new PositionUpdater(mediaPlayer, executorService);
mPositionUpdater.startUpdating();
}
@@ -286,6 +285,7 @@ public class VoicemailPlaybackLayout extends LinearLayout
if (mPlaybackSeek.getMax() != seekBarMax) {
mPlaybackSeek.setMax(seekBarMax);
}
+
mPlaybackSeek.setProgress(seekBarPosition);
mPlaybackPosition.setText(formatAsMinutesAndSeconds(seekBarMax - seekBarPosition));
}
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
index e8b04602d..99d2734eb 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
@@ -78,9 +78,9 @@ public class VoicemailPlaybackPresenter
void disableUiElements();
void enableUiElements();
void onPlaybackError(Exception e);
- void onPlaybackStarted(MediaPlayer mediaPlayer, int duration,
- ScheduledExecutorService executorService);
+ void onPlaybackStarted(MediaPlayer mediaPlayer, ScheduledExecutorService executorService);
void onPlaybackStopped();
+ void onSpeakerphoneOn(boolean on);
void setClipPosition(int clipPositionInMillis, int clipLengthInMillis);
void setFetchContentTimeout();
void setIsBuffering();
@@ -103,6 +103,10 @@ public class VoicemailPlaybackPresenter
// Time to wait for content to be fetched before timing out.
private static final long FETCH_CONTENT_TIMEOUT_MS = 20000;
+ private static final String VOICEMAIL_URI_KEY =
+ VoicemailPlaybackPresenter.class.getName() + ".VOICEMAIL_URI";
+ private static final String IS_PREPARED_KEY =
+ VoicemailPlaybackPresenter.class.getName() + ".IS_PREPARED";
// If present in the saved instance bundle, we should not resume playback on create.
private static final String IS_PLAYING_STATE_KEY =
VoicemailPlaybackPresenter.class.getName() + ".IS_PLAYING_STATE_KEY";
@@ -111,22 +115,21 @@ public class VoicemailPlaybackPresenter
VoicemailPlaybackPresenter.class.getName() + ".CLIP_POSITION_KEY";
/**
- * The most recently calculated duration.
- * <p>
- * We cache this in a field since we don't want to keep requesting it from the player, as
- * this can easily lead to throwing {@link IllegalStateException} (any time the player is
- * released, it's illegal to ask for the duration).
+ * The most recently cached duration. We cache this since we don't want to keep requesting it
+ * from the player, as this can easily lead to throwing {@link IllegalStateException} (any time
+ * the player is released, it's illegal to ask for the duration).
*/
private final AtomicInteger mDuration = new AtomicInteger(0);
private Context mContext;
- private MediaPlayer mMediaPlayer;
private PlaybackView mView;
+ private static MediaPlayer mMediaPlayer;
private Uri mVoicemailUri;
private int mPosition;
private boolean mIsPrepared;
private boolean mIsPlaying;
+
private boolean mShouldResumePlaybackAfterSeeking;
// Used to run async tasks that need to interact with the UI.
@@ -141,11 +144,19 @@ public class VoicemailPlaybackPresenter
private PowerManager.WakeLock mProximityWakeLock;
private AudioManager mAudioManager;
- public VoicemailPlaybackPresenter(Activity activity) {
+ public VoicemailPlaybackPresenter(Activity activity, Bundle savedInstanceState) {
mContext = activity;
mAsyncTaskExecutor = AsyncTaskExecutors.createAsyncTaskExecutor();
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ if (savedInstanceState != null) {
+ // Restores playback state when activity is recreated, such as after rotation.
+ mVoicemailUri = (Uri) savedInstanceState.getParcelable(VOICEMAIL_URI_KEY);
+ mIsPrepared = savedInstanceState.getBoolean(IS_PREPARED_KEY);
+ mPosition = savedInstanceState.getInt(CLIP_POSITION_KEY, 0);
+ mIsPlaying = savedInstanceState.getBoolean(IS_PLAYING_STATE_KEY, false);
+ }
+
PowerManager powerManager =
(PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
if (powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
@@ -153,12 +164,15 @@ public class VoicemailPlaybackPresenter
PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
}
+ // mMediaPlayer is static to enable seamless playback during rotation. If we do not create
+ // a new MediaPlayer, we still need to update listeners to the current Presenter instance.
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
- mMediaPlayer.setOnPreparedListener(this);
- mMediaPlayer.setOnErrorListener(this);
- mMediaPlayer.setOnCompletionListener(this);
+ mIsPrepared = false;
}
+ mMediaPlayer.setOnPreparedListener(this);
+ mMediaPlayer.setOnErrorListener(this);
+ mMediaPlayer.setOnCompletionListener(this);
activity.setVolumeControlStream(PLAYBACK_STREAM);
}
@@ -169,21 +183,29 @@ public class VoicemailPlaybackPresenter
public void setPlaybackView(
PlaybackView view, Uri voicemailUri, boolean startPlayingImmediately) {
mView = view;
- mVoicemailUri = voicemailUri;
-
mView.setPresenter(this);
- if (!mMediaPlayer.isPlaying()) {
- setPosition(0, startPlayingImmediately);
- mIsPrepared = false;
+ mView.onSpeakerphoneOn(isSpeakerphoneOn());
+
+ if (mVoicemailUri != null && mVoicemailUri.equals(voicemailUri)) {
+ // Handles rotation case where playback view is set for the same voicemail.
+ if (mIsPrepared) {
+ onPrepared(mMediaPlayer);
+ } else {
+ checkForContent();
+ }
+ } else {
+ mVoicemailUri = voicemailUri;
+ mPosition = 0;
+ mIsPlaying = startPlayingImmediately;
+ checkForContent();
}
- checkForContent();
}
public void onPause(boolean isFinishing) {
// Do not pause for orientation changes.
if (mMediaPlayer.isPlaying() && isFinishing) {
- pausePlayback(mMediaPlayer.getCurrentPosition(), mIsPlaying);
+ pausePlayback();
}
disableProximitySensor(false /* waitForFarState */);
@@ -210,16 +232,11 @@ public class VoicemailPlaybackPresenter
}
public void onSaveInstanceState(Bundle outState) {
- outState.putInt(CLIP_POSITION_KEY, mView.getDesiredClipPosition());
- outState.putBoolean(IS_PLAYING_STATE_KEY, mIsPlaying);
- }
-
- public void onRestoreInstanceState(Bundle inState) {
- if (inState != null) {
- int position = inState.getInt(CLIP_POSITION_KEY, 0);
- boolean isPlaying = inState.getBoolean(IS_PLAYING_STATE_KEY, false);
- // Playback will be automatically resumed, if appropriate, in onPrepared().
- setPosition(position, isPlaying);
+ if (mView != null) {
+ outState.putParcelable(VOICEMAIL_URI_KEY, mVoicemailUri);
+ outState.putBoolean(IS_PREPARED_KEY, mIsPrepared);
+ outState.putInt(CLIP_POSITION_KEY, mView.getDesiredClipPosition());
+ outState.putBoolean(IS_PLAYING_STATE_KEY, mIsPlaying);
}
}
@@ -355,6 +372,7 @@ public class VoicemailPlaybackPresenter
* and it will call {@link #onError()} otherwise.
*/
private void prepareToPlayContent() {
+ mIsPrepared = false;
mView.setIsBuffering();
try {
@@ -373,8 +391,10 @@ public class VoicemailPlaybackPresenter
@Override
public void onPrepared(MediaPlayer mp) {
mIsPrepared = true;
+ mDuration.set(mMediaPlayer.getDuration());
mView.enableUiElements();
+ mView.setClipPosition(mPosition, mDuration.get());
if (mIsPlaying) {
resumePlayback();
@@ -400,7 +420,9 @@ public class VoicemailPlaybackPresenter
}
mView.onPlaybackError(e);
- setPosition(0, false);
+
+ mPosition = 0;
+ mIsPlaying = false;
}
/**
@@ -408,7 +430,11 @@ public class VoicemailPlaybackPresenter
*/
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
- pausePlayback(0, false);
+ pausePlayback();
+
+ // Reset the seekbar position to the beginning.
+ mPosition = 0;
+ mView.setClipPosition(0, mDuration.get());
}
@Override
@@ -423,56 +449,45 @@ public class VoicemailPlaybackPresenter
}
/**
- * Sets the position and playing state for when playback is resumed.
- */
- private void setPosition(int position, boolean isPlaying) {
- mPosition = position;
- mIsPlaying = isPlaying;
- }
-
- /**
- * Resumes voicemail playback at the clip position stored by the presenter.
+ * Resumes voicemail playback at the clip position stored by the presenter. Null-op if already
+ * playing.
*/
public void resumePlayback() {
- final int duration = mMediaPlayer.getDuration();
- mDuration.set(duration);
+ mIsPlaying = true;
- // Clamp the start position between 0 and the duration.
- int startPosition = Math.max(0, Math.min(mPosition, duration));
- mMediaPlayer.seekTo(startPosition);
- setPosition(startPosition, true);
+ if (!mMediaPlayer.isPlaying()) {
+ // Clamp the start position between 0 and the duration.
+ mPosition = Math.max(0, Math.min(mPosition, mDuration.get()));
+ mMediaPlayer.seekTo(mPosition);
+
+ try {
+ // Grab audio focus here
+ int result = mAudioManager.requestAudioFocus(
+ VoicemailPlaybackPresenter.this,
+ PLAYBACK_STREAM,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+
+ if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+ throw new RejectedExecutionException("Could not capture audio focus.");
+ }
- try {
- // Grab audio focus here
- int result = mAudioManager.requestAudioFocus(
- VoicemailPlaybackPresenter.this,
- PLAYBACK_STREAM,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
-
- if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- throw new RejectedExecutionException("Could not capture audio focus.");
+ // Can throw RejectedExecutionException
+ mMediaPlayer.start();
+ } catch (RejectedExecutionException e) {
+ handleError(e);
}
-
- // Can throw RejectedExecutionException
- mMediaPlayer.start();
-
- mView.onPlaybackStarted(mMediaPlayer, duration, getScheduledExecutorServiceInstance());
- enableProximitySensor();
- } catch (RejectedExecutionException e) {
- handleError(e);
}
- }
- public void pausePlayback() {
- pausePlayback(mMediaPlayer.getCurrentPosition(), false);
+ enableProximitySensor();
+ mView.onPlaybackStarted(mMediaPlayer, getScheduledExecutorServiceInstance());
}
/**
- * {@link isPlaying} may be set to {@code true} so voicemail playback can be resumed after a
- * rotation.
+ * Pauses voicemail playback at the current position. Null-op if already paused.
*/
- private void pausePlayback(int position, boolean isPlaying) {
- setPosition(position, isPlaying);
+ public void pausePlayback() {
+ mPosition = mMediaPlayer.getCurrentPosition();
+ mIsPlaying = false;
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
@@ -483,9 +498,6 @@ public class VoicemailPlaybackPresenter
// Always disable the proximity sensor on stop.
disableProximitySensor(true /* waitForFarState */);
-
- int duration = mDuration.get();
- mView.setClipPosition(position, duration);
}
/**
@@ -498,11 +510,11 @@ public class VoicemailPlaybackPresenter
}
public void resumePlaybackAfterSeeking(int desiredPosition) {
- setPosition(desiredPosition, mShouldResumePlaybackAfterSeeking);
+ mPosition = desiredPosition;
if (mShouldResumePlaybackAfterSeeking) {
+ mShouldResumePlaybackAfterSeeking = false;
resumePlayback();
}
- mShouldResumePlaybackAfterSeeking = false;
}
private void enableProximitySensor() {
diff --git a/src/com/android/dialerbind/ObjectFactory.java b/src/com/android/dialerbind/ObjectFactory.java
index 12607d9f3..43b237c1b 100644
--- a/src/com/android/dialerbind/ObjectFactory.java
+++ b/src/com/android/dialerbind/ObjectFactory.java
@@ -25,6 +25,7 @@ import com.android.dialer.calllog.CallLogAdapter;
import com.android.dialer.calllog.CallLogAdapter.OnReportButtonClickListener;
import com.android.dialer.calllog.ContactInfoHelper;
import com.android.dialer.service.CachedNumberLookupService;
+import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
/**
* Default static binding for various objects.
@@ -47,12 +48,14 @@ public class ObjectFactory {
Context context,
CallFetcher callFetcher,
ContactInfoHelper contactInfoHelper,
+ VoicemailPlaybackPresenter voicemailPlaybackPresenter,
boolean isShowingRecentsTab,
OnReportButtonClickListener onReportButtonClickListener) {
return new CallLogAdapter(
context,
callFetcher,
contactInfoHelper,
+ voicemailPlaybackPresenter,
isShowingRecentsTab,
onReportButtonClickListener);
}
diff --git a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
index 5f09cb74b..14e0aaf9e 100644
--- a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
@@ -204,7 +204,7 @@ public class CallLogAdapterTest extends AndroidTestCase {
private static final class TestCallLogAdapter extends CallLogAdapter {
public TestCallLogAdapter(Context context, CallFetcher callFetcher,
ContactInfoHelper contactInfoHelper) {
- super(context, callFetcher, contactInfoHelper, false, null);
+ super(context, callFetcher, contactInfoHelper, null, false, null);
mContactInfoCache = new TestContactInfoCache(
contactInfoHelper, mOnContactInfoChangedListener);
}
diff --git a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
index 0c19799cc..71554d6e1 100644
--- a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
@@ -335,28 +335,15 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme
}
@MediumTest
- public void testBindView_PlayButton() {
+ public void testBindView_VoicemailUri() {
mCursor.moveToFirst();
insertVoicemail(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0);
CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
bindViewForTest(viewHolder);
- IntentProvider intentProvider = (IntentProvider) viewHolder.voicemailButtonView.getTag();
- Intent intent = intentProvider.getIntent(mActivity);
- // Starts the call detail activity.
- assertEquals(new ComponentName(mActivity, CallDetailActivity.class),
- intent.getComponent());
- // With the given entry.
- assertEquals(ContentUris.withAppendedId(Calls.CONTENT_URI_WITH_VOICEMAIL, 1),
- intent.getData());
- // With the URI of the voicemail.
- assertEquals(
- ContentUris.withAppendedId(VoicemailContract.Voicemails.CONTENT_URI, 1),
- intent.getParcelableExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI));
- // And starts playback.
- assertTrue(
- intent.getBooleanExtra(CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK, false));
+ assertEquals(Uri.parse(viewHolder.voicemailUri),
+ ContentUris.withAppendedId(VoicemailContract.Voicemails.CONTENT_URI, 1));
}
/** Returns the label associated with a given phone type. */
@@ -453,11 +440,17 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme
* unit tests can access the buttons contained within.
*
* @param view The current call log row.
- * @param position The position of hte item.
+ * @param position The position of the item.
*/
- private void bindViewForTest(CallLogListItemViewHolder viewHolder, int position) {
+ private void bindViewForTest(final CallLogListItemViewHolder viewHolder, int position) {
mAdapter.onBindViewHolder(viewHolder, position);
- viewHolder.inflateActionViewStub(null);
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ viewHolder.inflateActionViewStub(null);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
viewHolder.updateCallButton();
}
diff --git a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
index 085ec9bb6..a7d9b9967 100644
--- a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
@@ -99,23 +99,23 @@ public class CallLogListItemHelperTest extends AndroidTestCase {
public void testSetPhoneCallDetails_VoicemailNumber() {
setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER,
Calls.PRESENTATION_ALLOWED, TEST_VOICEMAIL_NUMBER);
- assertEquals(View.VISIBLE, mViewHolder.voicemailButtonView.getVisibility());
+ assertEquals(View.VISIBLE, mViewHolder.voicemailPlaybackView.getVisibility());
}
public void testSetPhoneCallDetails_ReadVoicemail() {
setPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE);
- assertEquals(View.VISIBLE, mViewHolder.voicemailButtonView.getVisibility());
+ assertEquals(View.VISIBLE, mViewHolder.voicemailPlaybackView.getVisibility());
}
public void testSetPhoneCallDetails_UnreadVoicemail() {
setUnreadPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE);
- assertEquals(View.VISIBLE, mViewHolder.voicemailButtonView.getVisibility());
+ assertEquals(View.VISIBLE, mViewHolder.voicemailPlaybackView.getVisibility());
}
public void testSetPhoneCallDetails_VoicemailFromUnknown() {
setPhoneCallDetailsWithNumberAndType("", Calls.PRESENTATION_UNKNOWN,
"", Calls.VOICEMAIL_TYPE);
- assertEquals(View.VISIBLE, mViewHolder.voicemailButtonView.getVisibility());
+ assertEquals(View.VISIBLE, mViewHolder.voicemailPlaybackView.getVisibility());
}
/**
@@ -470,7 +470,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase {
/** Sets the details of a phone call using the specified call type. */
private void setPhoneCallDetailsWithTypes(int... types) {
- mHelper.setPhoneCallDetails(getContext() ,mViewHolder,
+ mHelper.setPhoneCallDetails(getContext(), mViewHolder,
new PhoneCallDetails(
mContext,
TEST_NUMBER,