summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/voicemail/listui
diff options
context:
space:
mode:
authoruabdullah <uabdullah@google.com>2017-11-13 14:42:50 -0800
committerzachh <zachh@google.com>2017-11-18 04:18:35 +0000
commit1ecb3e2751218d377cfd75d9623c6715174c8dc5 (patch)
tree7f13d22f07de2dfbb5586136ead7c1bb61e934bf /java/com/android/dialer/voicemail/listui
parent7c46fa934858992f76153f9886efd34f08da03ce (diff)
Play voicemails downloaded from the voicemail server in the NUI VM Fragment
Voicemails that are available locally on the device (have been downloaded from the voicemail server) will have their "HAS_CONTENT" column set to one. This CL adds the plumbing logic of checking that when a user presses the play button, if the voicemail is available locally, it is played. Bug: 64882313,68382421 Test: Existing unit tests PiperOrigin-RevId: 175590204 Change-Id: Id164d08c16b89c84a75af0c4a7c899c02d64fff7
Diffstat (limited to 'java/com/android/dialer/voicemail/listui')
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java10
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java4
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayer.java87
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java221
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java11
-rw-r--r--java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry.xml2
6 files changed, 241 insertions, 94 deletions
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
index d04143f59..6f6a87cef 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
@@ -15,6 +15,7 @@
*/
package com.android.dialer.voicemail.listui;
+import android.app.FragmentManager;
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.util.ArraySet;
@@ -33,6 +34,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<NewVoicemailViewHol
private final Cursor cursor;
private final Clock clock;
+ private final FragmentManager fragmentManager;
/** A valid id for {@link VoicemailEntry} is greater than 0 */
private int currentlyExpandedViewHolderId = -1;
@@ -40,13 +42,16 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<NewVoicemailViewHol
private final Set<NewVoicemailViewHolder> newVoicemailViewHolderSet = new ArraySet<>();
/** @param cursor whose projection is {@link VoicemailCursorLoader.VOICEMAIL_COLUMNS} */
- NewVoicemailAdapter(Cursor cursor, Clock clock) {
+ NewVoicemailAdapter(Cursor cursor, Clock clock, FragmentManager fragmentManager) {
+ LogUtil.enterBlock("NewVoicemailAdapter");
this.cursor = cursor;
this.clock = clock;
+ this.fragmentManager = fragmentManager;
}
@Override
public NewVoicemailViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
+ LogUtil.enterBlock("NewVoicemailAdapter.onCreateViewHolder");
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View view = inflater.inflate(R.layout.new_voicemail_entry, viewGroup, false);
NewVoicemailViewHolder newVoicemailViewHolder = new NewVoicemailViewHolder(view, clock, this);
@@ -56,9 +61,8 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<NewVoicemailViewHol
@Override
public void onBindViewHolder(NewVoicemailViewHolder viewHolder, int position) {
- LogUtil.i("onBindViewHolder", "position" + position);
cursor.moveToPosition(position);
- viewHolder.bind(cursor);
+ viewHolder.bind(cursor, fragmentManager);
expandOrCollapseViewHolder(viewHolder);
}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
index 9c1fd8b85..9a89dbe3e 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
@@ -54,7 +54,9 @@ public final class NewVoicemailFragment extends Fragment implements LoaderCallba
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
LogUtil.i("NewVoicemailFragment.onCreateLoader", "cursor size is %d", data.getCount());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
- recyclerView.setAdapter(new NewVoicemailAdapter(data, System::currentTimeMillis));
+ recyclerView.setAdapter(
+ new NewVoicemailAdapter(
+ data, System::currentTimeMillis, getActivity().getFragmentManager()));
}
@Override
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayer.java b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayer.java
deleted file mode 100644
index 11aa9ac2e..000000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayer.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2017 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.dialer.voicemail.listui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import com.android.dialer.common.LogUtil;
-
-/**
- * The view of the media player that is visible when a {@link NewVoicemailViewHolder} is expanded.
- */
-public class NewVoicemailMediaPlayer extends LinearLayout {
-
- private Button playButton;
- private Button speakerButton;
- private Button deleteButton;
-
- public NewVoicemailMediaPlayer(Context context, AttributeSet attrs) {
- super(context, attrs);
- LogUtil.enterBlock("NewVoicemailMediaPlayer");
- LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.new_voicemail_media_player_layout, this);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- LogUtil.enterBlock("NewVoicemailMediaPlayer.onFinishInflate");
- initializeMediaPlayerButtons();
- setupListenersForMediaPlayerButtons();
- }
-
- private void initializeMediaPlayerButtons() {
- playButton = findViewById(R.id.playButton);
- speakerButton = findViewById(R.id.speakerButton);
- deleteButton = findViewById(R.id.deleteButton);
- }
-
- private void setupListenersForMediaPlayerButtons() {
- playButton.setOnClickListener(playButtonListener);
- speakerButton.setOnClickListener(speakerButtonListener);
- deleteButton.setOnClickListener(deleteButtonListener);
- }
-
- private final View.OnClickListener playButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i("NewVoicemailMediaPlayer.playButtonListener", "onClick");
- }
- };
-
- private final View.OnClickListener speakerButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i("NewVoicemailMediaPlayer.speakerButtonListener", "onClick");
- }
- };
-
- private final View.OnClickListener deleteButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i("NewVoicemailMediaPlayer.deleteButtonListener", "onClick");
- }
- };
-}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
new file mode 100644
index 000000000..1e56a8189
--- /dev/null
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2017 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.dialer.voicemail.listui;
+
+import android.app.FragmentManager;
+import android.content.Context;
+import android.database.Cursor;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.provider.VoicemailContract;
+import android.support.annotation.VisibleForTesting;
+import android.support.v4.util.Pair;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
+import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
+
+/**
+ * The view of the media player that is visible when a {@link NewVoicemailViewHolder} is expanded.
+ */
+public class NewVoicemailMediaPlayerView extends LinearLayout {
+
+ private Button playButton;
+ private Button speakerButton;
+ private Button deleteButton;
+ private Uri voicemailUri;
+ private FragmentManager fragmentManager;
+ private MediaPlayer mediaPlayer;
+
+ public NewVoicemailMediaPlayerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ LogUtil.enterBlock("NewVoicemailMediaPlayer");
+ LayoutInflater inflater =
+ (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.new_voicemail_media_player_layout, this);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ LogUtil.enterBlock("NewVoicemailMediaPlayer.onFinishInflate");
+ initializeMediaPlayerButtons();
+ setupListenersForMediaPlayerButtons();
+ }
+
+ private void initializeMediaPlayerButtons() {
+ playButton = findViewById(R.id.playButton);
+ speakerButton = findViewById(R.id.speakerButton);
+ deleteButton = findViewById(R.id.deleteButton);
+ }
+
+ private void setupListenersForMediaPlayerButtons() {
+ playButton.setOnClickListener(playButtonListener);
+ speakerButton.setOnClickListener(speakerButtonListener);
+ deleteButton.setOnClickListener(deleteButtonListener);
+ }
+
+ private final View.OnClickListener playButtonListener =
+ view -> playVoicemailWhenAvailableLocally();
+
+ /**
+ * Plays the voicemail when we are able to play the voicemail locally from the device. This
+ * involves checking if the voicemail is available to play locally, if it is, then we setup the
+ * Media Player to play the voicemail. If the voicemail is not available, then we need download
+ * the voicemail from the voicemail server to the device, and then have the Media player play it.
+ */
+ private void playVoicemailWhenAvailableLocally() {
+ LogUtil.enterBlock("playVoicemailWhenAvailableLocally");
+ Worker<Pair<Context, Uri>, Pair<Boolean, Uri>> checkVoicemailHasContent =
+ this::queryVoicemailHasContent;
+ SuccessListener<Pair<Boolean, Uri>> checkVoicemailHasContentCallBack = this::prepareMediaPlayer;
+
+ DialerExecutorComponent.get(getContext())
+ .dialerExecutorFactory()
+ .createUiTaskBuilder(fragmentManager, "lookup_voicemail_content", checkVoicemailHasContent)
+ .onSuccess(checkVoicemailHasContentCallBack)
+ .build()
+ .executeSerial(new Pair<>(getContext(), voicemailUri));
+ }
+
+ private Pair<Boolean, Uri> queryVoicemailHasContent(Pair<Context, Uri> contextUriPair) {
+ Context context = contextUriPair.first;
+ Uri uri = contextUriPair.second;
+
+ try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
+ if (cursor != null && cursor.moveToNext()) {
+ return new Pair<>(
+ cursor.getInt(cursor.getColumnIndex(VoicemailContract.Voicemails.HAS_CONTENT)) == 1,
+ uri);
+ }
+ return new Pair<>(false, uri);
+ }
+ }
+
+ /**
+ * If the voicemail is available to play locally, setup the media player to play it. Otherwise
+ * send a request to download the voicemail and then play it.
+ */
+ private void prepareMediaPlayer(Pair<Boolean, Uri> booleanUriPair) {
+ boolean voicemailAvailableLocally = booleanUriPair.first;
+ Uri uri = booleanUriPair.second;
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.prepareMediaPlayer",
+ "voicemail available locally: %b for voicemailUri: %s",
+ voicemailAvailableLocally,
+ uri.toString());
+
+ if (voicemailAvailableLocally) {
+ try {
+ mediaPlayer = new MediaPlayer();
+ mediaPlayer.setOnPreparedListener(onPreparedListener);
+ mediaPlayer.setOnErrorListener(onErrorListener);
+ mediaPlayer.setOnCompletionListener(onCompletionListener);
+
+ mediaPlayer.reset();
+ mediaPlayer.setDataSource(getContext(), uri);
+
+ mediaPlayer.prepareAsync();
+ } catch (Exception e) {
+ LogUtil.e("NewVoicemailMediaPlayer.prepareMediaPlayer", "IOException " + e);
+ }
+ } else {
+ // TODO(a bug): Add logic for downloading voicemail content from the server.
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.prepareVoicemailForMediaPlayer", "need to download content");
+ }
+ }
+
+ private final View.OnClickListener speakerButtonListener =
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.speakerButtonListener",
+ "speaker request for voicemailUri: %s",
+ voicemailUri.toString());
+ }
+ };
+
+ private final View.OnClickListener deleteButtonListener =
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.deleteButtonListener",
+ "delete voicemailUri %s",
+ voicemailUri.toString());
+ }
+ };
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ OnCompletionListener onCompletionListener =
+ new OnCompletionListener() {
+
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.onCompletionListener",
+ "completed playing voicemailUri: %s",
+ voicemailUri.toString());
+ }
+ };
+
+ private final OnPreparedListener onPreparedListener =
+ new OnPreparedListener() {
+
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.onPreparedListener",
+ "about to play voicemailUri: %s",
+ voicemailUri.toString());
+ mediaPlayer.start();
+ }
+ };
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ OnErrorListener onErrorListener =
+ new OnErrorListener() {
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.onErrorListener",
+ "error playing voicemailUri: %s",
+ voicemailUri.toString());
+ return false;
+ }
+ };
+
+ public void setVoicemailUri(Uri voicemailUri) {
+ Assert.isNotNull(voicemailUri);
+ this.voicemailUri = voicemailUri;
+ }
+
+ public void setFragmentManager(FragmentManager fragmentManager) {
+ this.fragmentManager = fragmentManager;
+ }
+}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
index d4bfefd22..078a029c9 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
@@ -15,6 +15,7 @@
*/
package com.android.dialer.voicemail.listui;
+import android.app.FragmentManager;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
@@ -25,6 +26,7 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.widget.QuickContactBadge;
import android.widget.TextView;
+import com.android.dialer.common.LogUtil;
import com.android.dialer.contactphoto.ContactPhotoManager;
import com.android.dialer.lettertile.LetterTileDrawable;
import com.android.dialer.time.Clock;
@@ -38,7 +40,7 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
private final TextView secondaryTextView;
private final TextView transcriptionTextView;
private final QuickContactBadge quickContactBadge;
- private final View mediaPlayerView;
+ private final NewVoicemailMediaPlayerView mediaPlayerView;
private final Clock clock;
private boolean isViewHolderExpanded;
private int viewHolderId;
@@ -47,6 +49,7 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
NewVoicemailViewHolder(
View view, Clock clock, NewVoicemailViewHolderListener newVoicemailViewHolderListener) {
super(view);
+ LogUtil.enterBlock("NewVoicemailViewHolder");
this.context = view.getContext();
primaryTextView = view.findViewById(R.id.primary_text);
secondaryTextView = view.findViewById(R.id.secondary_text);
@@ -57,7 +60,7 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
voicemailViewHolderListener = newVoicemailViewHolderListener;
}
- void bind(Cursor cursor) {
+ void bind(Cursor cursor, FragmentManager fragmentManager) {
VoicemailEntry voicemailEntry = VoicemailCursorLoader.toVoicemailEntry(cursor);
viewHolderId = voicemailEntry.id();
primaryTextView.setText(VoicemailEntryText.buildPrimaryVoicemailText(context, voicemailEntry));
@@ -76,6 +79,8 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
itemView.setOnClickListener(this);
setPhoto(voicemailEntry);
+ mediaPlayerView.setVoicemailUri(Uri.parse(voicemailEntry.voicemailUri()));
+ mediaPlayerView.setFragmentManager(fragmentManager);
}
// TODO(uabdullah): Consider/Implement TYPE (e.g Spam, TYPE_VOICEMAIL)
@@ -97,6 +102,7 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
}
void expandViewHolder() {
+ LogUtil.i("NewVoicemailViewHolder.expandViewHolder", "voicemail id: %d", viewHolderId);
transcriptionTextView.setMaxLines(999);
isViewHolderExpanded = true;
mediaPlayerView.setVisibility(View.VISIBLE);
@@ -117,6 +123,7 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
@Override
public void onClick(View v) {
+ LogUtil.i("NewVoicemailViewHolder.onClick", "voicemail id: %d", viewHolderId);
if (isViewHolderExpanded) {
collapseViewHolder();
} else {
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry.xml
index 80bb1b593..78d2785e9 100644
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry.xml
+++ b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry.xml
@@ -82,7 +82,7 @@
android:layout_gravity="center_vertical"
android:visibility="gone"/>
- <com.android.dialer.voicemail.listui.NewVoicemailMediaPlayer
+ <com.android.dialer.voicemail.listui.NewVoicemailMediaPlayerView
android:id="@+id/new_voicemail_media_player"
android:layout_width="match_parent"
android:layout_height="wrap_content"