summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/voicemail
diff options
context:
space:
mode:
authoruabdullah <uabdullah@google.com>2018-01-25 15:25:50 -0800
committerCopybara-Service <copybara-piper@google.com>2018-01-25 16:17:17 -0800
commitc5b58aa372390b544668c79550c70237399c8c0d (patch)
tree7ed3bed3f0ca69e0e98462140363d6fb52776c7a /java/com/android/dialer/voicemail
parent923e186f97b3aeb67f4ddbb686e7c92336a7a4ef (diff)
Show voicemail error messages for NUI
This CL shows the voicemail error messages for both VVM and OMTP type voicemails. It hooks upto the existing error framework and retrieves the voicemail error states and then displays it. Bug: 71700117 Test: Unit Tests PiperOrigin-RevId: 183301455 Change-Id: Ib2b7fb957fbfd2af2227747d327cef466259eb6f
Diffstat (limited to 'java/com/android/dialer/voicemail')
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java164
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java32
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java29
-rw-r--r--java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml101
-rw-r--r--java/com/android/dialer/voicemail/listui/res/values/dimens.xml9
5 files changed, 281 insertions, 54 deletions
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
index 5519aa486..318f79783 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
@@ -25,6 +25,7 @@ import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
@@ -43,9 +44,15 @@ import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.time.Clock;
import com.android.dialer.voicemail.listui.NewVoicemailViewHolder.NewVoicemailViewHolderListener;
+import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage;
+import com.android.dialer.voicemail.listui.error.VoicemailErrorMessageCreator;
+import com.android.dialer.voicemail.listui.error.VoicemailStatus;
import com.android.dialer.voicemail.model.VoicemailEntry;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
import java.util.Objects;
import java.util.Set;
@@ -66,6 +73,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
}
private Cursor cursor;
+ private Cursor voicemailStatusCursor;
private final Clock clock;
/** {@link Integer#MAX_VALUE} when the "Today" header should not be displayed. */
@@ -81,6 +89,8 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
/** A valid id for {@link VoicemailEntry} is greater than 0 */
private int currentlyExpandedViewHolderId = -1;
+ private VoicemailErrorMessage voicemailErrorMessage;
+
/**
* It takes time to delete voicemails from the server, so we "remove" them and remember the
* positions we removed until a new cursor is ready.
@@ -248,34 +258,14 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
if (viewHolder instanceof NewVoicemailHeaderViewHolder) {
LogUtil.i(
"NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d is a header", position);
- NewVoicemailHeaderViewHolder headerViewHolder = (NewVoicemailHeaderViewHolder) viewHolder;
- @RowType int viewType = getItemViewType(position);
- if (position == todayHeaderPosition) {
- headerViewHolder.setHeader(R.string.new_voicemail_header_today);
- } else if (position == yesterdayHeaderPosition) {
- headerViewHolder.setHeader(R.string.new_voicemail_header_yesterday);
- } else if (position == olderHeaderPosition) {
- headerViewHolder.setHeader(R.string.new_voicemail_header_older);
- } else {
- throw Assert.createIllegalStateFailException(
- "Unexpected view type " + viewType + " at position: " + position);
- }
+ onBindHeaderViewHolder(viewHolder, position);
return;
}
if (viewHolder instanceof NewVoicemailAlertViewHolder) {
LogUtil.i(
"NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d is a alert", position);
- NewVoicemailAlertViewHolder alertViewHolder = (NewVoicemailAlertViewHolder) viewHolder;
- @RowType int viewType = getItemViewType(position);
- Assert.checkArgument(position == 0);
- if (position == voicemailAlertPosition) {
- // TODO(a bug): Update this with the alert messages
- alertViewHolder.setHeader("Temporary placeholder, update this with the alert messages");
- } else {
- throw Assert.createIllegalStateFailException(
- "Unexpected view type " + viewType + " at position: " + position);
- }
+ onBindAlertViewHolder(viewHolder, position);
return;
}
@@ -285,26 +275,13 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
position);
NewVoicemailViewHolder newVoicemailViewHolder = (NewVoicemailViewHolder) viewHolder;
-
- int previousHeaders = 0;
- if (voicemailAlertPosition != Integer.MAX_VALUE && position > voicemailAlertPosition) {
- previousHeaders++;
- }
- if (todayHeaderPosition != Integer.MAX_VALUE && position > todayHeaderPosition) {
- previousHeaders++;
- }
- if (yesterdayHeaderPosition != Integer.MAX_VALUE && position > yesterdayHeaderPosition) {
- previousHeaders++;
- }
- if (olderHeaderPosition != Integer.MAX_VALUE && position > olderHeaderPosition) {
- previousHeaders++;
- }
+ int nonVoicemailEntryHeaders = getHeaderCountAtPosition(position);
LogUtil.i(
"NewVoicemailAdapter.onBindViewHolder",
- "view holder at pos:%d, prevHeaderCount:%d",
+ "view holder at pos:%d, nonVoicemailEntryHeaders:%d",
position,
- previousHeaders);
+ nonVoicemailEntryHeaders);
// Remove if the viewholder is being recycled.
if (newVoicemailViewHolderArrayMap.containsKey(newVoicemailViewHolder.getViewHolderId())) {
@@ -322,7 +299,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
}
newVoicemailViewHolder.reset();
- cursor.moveToPosition(position - previousHeaders);
+ cursor.moveToPosition(position - nonVoicemailEntryHeaders);
newVoicemailViewHolder.bindViewHolderValuesFromAdapter(
cursor, fragmentManager, mediaPlayer, position, currentlyExpandedViewHolderId);
@@ -378,6 +355,72 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
printArrayMap();
}
+ private int getHeaderCountAtPosition(int position) {
+ int previousHeaders = 0;
+ if (voicemailAlertPosition != Integer.MAX_VALUE && position > voicemailAlertPosition) {
+ previousHeaders++;
+ }
+ if (todayHeaderPosition != Integer.MAX_VALUE && position > todayHeaderPosition) {
+ previousHeaders++;
+ }
+ if (yesterdayHeaderPosition != Integer.MAX_VALUE && position > yesterdayHeaderPosition) {
+ previousHeaders++;
+ }
+ if (olderHeaderPosition != Integer.MAX_VALUE && position > olderHeaderPosition) {
+ previousHeaders++;
+ }
+ return previousHeaders;
+ }
+
+ private void onBindAlertViewHolder(ViewHolder viewHolder, int position) {
+ LogUtil.i(
+ "NewVoicemailAdapter.onBindAlertViewHolder",
+ "pos:%d, voicemailAlertPosition:%d",
+ position,
+ voicemailAlertPosition);
+
+ NewVoicemailAlertViewHolder alertViewHolder = (NewVoicemailAlertViewHolder) viewHolder;
+ @RowType int viewType = getItemViewType(position);
+
+ Assert.checkArgument(position == 0, "position is not 0");
+ Assert.checkArgument(
+ position == voicemailAlertPosition,
+ String.format(
+ Locale.US,
+ "position:%d and voicemailAlertPosition:%d are different",
+ position,
+ voicemailAlertPosition));
+ Assert.checkArgument(viewType == RowType.VOICEMAIL_ALERT, "Invalid row type: " + viewType);
+ Assert.checkArgument(
+ voicemailErrorMessage.getActions().size() <= 2,
+ "Too many actions: " + voicemailErrorMessage.getActions().size());
+
+ alertViewHolder.setTitle(voicemailErrorMessage.getTitle());
+ alertViewHolder.setDescription(voicemailErrorMessage.getDescription());
+
+ if (!voicemailErrorMessage.getActions().isEmpty()) {
+ alertViewHolder.setPrimaryButton(voicemailErrorMessage.getActions().get(0));
+ }
+ if (voicemailErrorMessage.getActions().size() > 1) {
+ alertViewHolder.setSecondaryButton(voicemailErrorMessage.getActions().get(1));
+ }
+ }
+
+ private void onBindHeaderViewHolder(ViewHolder viewHolder, int position) {
+ NewVoicemailHeaderViewHolder headerViewHolder = (NewVoicemailHeaderViewHolder) viewHolder;
+ @RowType int viewType = getItemViewType(position);
+ if (position == todayHeaderPosition) {
+ headerViewHolder.setHeader(R.string.new_voicemail_header_today);
+ } else if (position == yesterdayHeaderPosition) {
+ headerViewHolder.setHeader(R.string.new_voicemail_header_yesterday);
+ } else if (position == olderHeaderPosition) {
+ headerViewHolder.setHeader(R.string.new_voicemail_header_older);
+ } else {
+ throw Assert.createIllegalStateFailException(
+ "Unexpected view type " + viewType + " at position: " + position);
+ }
+ }
+
private void printArrayMap() {
LogUtil.i(
"NewVoicemailAdapter.printArrayMap",
@@ -958,4 +1001,47 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
LogUtil.i("NewVoicemailAdapter.checkAndPlayVoicemail", "not playing downloaded voicemail");
}
}
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ public void setVoicemailStatusCursor(Cursor voicemailStatusCursor) {
+ this.voicemailStatusCursor = voicemailStatusCursor;
+ }
+
+ // TODO(uabdullah): Handle ToS properly
+ public void updateAlert(Context context) {
+ if (voicemailStatusCursor == null) {
+ LogUtil.i("NewVoicemailAdapter.updateAlert", "status cursor was null");
+ return;
+ }
+
+ LogUtil.i(
+ "NewVoicemailAdapter.updateAlert",
+ "status cursor size was " + voicemailStatusCursor.getCount());
+
+ List<VoicemailStatus> statuses = new ArrayList<>();
+
+ while (voicemailStatusCursor.moveToNext()) {
+ VoicemailStatus status = new VoicemailStatus(context, voicemailStatusCursor);
+ if (status.isActive()) {
+ statuses.add(status);
+ // TODO(uabdullah): addServiceStateListener
+ }
+ }
+
+ voicemailErrorMessage = null;
+ VoicemailErrorMessageCreator messageCreator = new VoicemailErrorMessageCreator();
+
+ for (VoicemailStatus status : statuses) {
+ voicemailErrorMessage = messageCreator.create(context, status, null);
+ if (voicemailErrorMessage != null) {
+ break;
+ }
+ }
+
+ if (voicemailErrorMessage != null) {
+ voicemailAlertPosition = 0;
+ updateHeaderPositions();
+ notifyItemChanged(0);
+ }
+ }
}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java
index ec603b5c8..ac989a8df 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java
@@ -18,19 +18,43 @@ package com.android.dialer.voicemail.listui;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.View;
+import android.widget.Button;
import android.widget.TextView;
+import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage.Action;
/** ViewHolder for {@link NewVoicemailAdapter} to display voicemail error states. */
final class NewVoicemailAlertViewHolder extends ViewHolder {
- private final TextView errorTextView;
+ private final TextView voicemailErrorTitleTextView;
+ private final TextView voicemailErrorDetailsTextView;
+ private final Button primaryButton;
+ private final Button secondaryButton;
NewVoicemailAlertViewHolder(View view) {
super(view);
- errorTextView = view.findViewById(R.id.new_voicemail_alert_text);
+ voicemailErrorTitleTextView = view.findViewById(R.id.voicemail_alert_header);
+ voicemailErrorDetailsTextView = view.findViewById(R.id.voicemail_alert_details);
+ primaryButton = view.findViewById(R.id.voicemail_alert_primary_button);
+ secondaryButton = view.findViewById(R.id.voicemail_alert_primary_button);
}
- void setHeader(String error) {
- errorTextView.setText(error);
+ void setTitle(CharSequence error) {
+ voicemailErrorTitleTextView.setText(error);
+ }
+
+ void setDescription(CharSequence error) {
+ voicemailErrorDetailsTextView.setText(error);
+ }
+
+ void setPrimaryButton(Action action) {
+ primaryButton.setVisibility(View.VISIBLE);
+ primaryButton.setText(action.getText());
+ primaryButton.setOnClickListener(action.getListener());
+ }
+
+ void setSecondaryButton(Action action) {
+ secondaryButton.setVisibility(View.VISIBLE);
+ secondaryButton.setText(action.getText());
+ secondaryButton.setOnClickListener(action.getListener());
}
}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
index b4be42455..0d91f0158 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
@@ -28,11 +28,15 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.database.CallLogQueryHandler;
+import com.android.dialer.database.CallLogQueryHandler.Listener;
+// TODO(uabdullah): Register content observer for VoicemailContract.Status.CONTENT_URI in onStart
/** Fragment for Dialer Voicemail Tab. */
public final class NewVoicemailFragment extends Fragment implements LoaderCallbacks<Cursor> {
private RecyclerView recyclerView;
+ private CallLogQueryHandler callLogQueryHandler;
@Nullable
@Override
@@ -72,6 +76,31 @@ public final class NewVoicemailFragment extends Fragment implements LoaderCallba
((NewVoicemailAdapter) recyclerView.getAdapter()).updateCursor(data);
((NewVoicemailAdapter) recyclerView.getAdapter()).checkAndPlayVoicemail();
}
+ callLogQueryHandler =
+ new CallLogQueryHandler(
+ getContext(), getContext().getContentResolver(), new NewVoicemailFragmentListener());
+ callLogQueryHandler.fetchVoicemailStatus();
+ }
+
+ private final class NewVoicemailFragmentListener implements Listener {
+
+ @Override
+ public void onVoicemailStatusFetched(Cursor statusCursor) {
+ LogUtil.enterBlock("NewVoicemailFragmentListener.onVoicemailStatusFetched");
+ ((NewVoicemailAdapter) recyclerView.getAdapter()).setVoicemailStatusCursor(statusCursor);
+ ((NewVoicemailAdapter) recyclerView.getAdapter()).updateAlert(getContext());
+ }
+
+ @Override
+ public void onVoicemailUnreadCountFetched(Cursor cursor) {}
+
+ @Override
+ public void onMissedCallsUnreadCountFetched(Cursor cursor) {}
+
+ @Override
+ public boolean onCallsFetched(Cursor combinedCursor) {
+ return false;
+ }
}
@Override
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml
index e8dcd02d6..28d639118 100644
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml
+++ b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml
@@ -14,17 +14,96 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<RelativeLayout
+
+<!-- TODO(uabdullah): Use a relative layout instead of nested linear layouts.-->
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="48dp"
+ android:id="@+id/voicemail_alert_content"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <!-- TODO(uabdullah): Confirm with UX on mocks -->
- <TextView
- android:id="@+id/new_voicemail_alert_text"
- style="@style/SecondaryText"
- android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/voicemail_header_margin_start"
- android:layout_centerVertical="true"/>
-</RelativeLayout>
+ android:paddingTop="@dimen/alert_main_padding"
+ android:paddingBottom="@dimen/alert_main_padding"
+ android:paddingStart="@dimen/alert_main_padding"
+ android:paddingEnd="@dimen/alert_main_padding"
+ android:gravity="top"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/voicemail_alert_icon"
+ android:layout_width="@dimen/voicemail_promo_card_icon_size"
+ android:layout_height="@dimen/voicemail_promo_card_icon_size"
+ android:layout_gravity="top"
+ android:src="@drawable/ic_voicemail_error_24px"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/voicemail_promo_card_main_padding"
+ android:gravity="center_vertical"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/voicemail_alert_header"
+ android:textStyle="bold"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/voicemail_promo_card_title_padding"
+ android:layout_gravity="center_vertical"
+ android:singleLine="false"
+ android:text="Voicemail Alert"
+ android:textSize="@dimen/voicemail_promo_card_title_text_size"/>
+
+ <TextView
+ android:id="@+id/voicemail_alert_details"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:lineSpacingExtra="@dimen/voicemail_promo_card_line_spacing"
+ android:singleLine="false"
+ android:text="This is a voicemail alert message."
+ android:textSize="@dimen/voicemail_promo_card_message_size"/>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/voicemail_alert_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end"
+ android:paddingTop="10dp"
+ android:paddingBottom="10dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:gravity="end"
+ android:minHeight="56dp"
+ android:orientation="horizontal">
+ <Button
+ android:id="@+id/voicemail_alert_secondary_button"
+ style="@style/TosButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/dialer_theme_color"/>
+
+ <Button
+ android:id="@+id/voicemail_alert_primary_button"
+ style="@style/TosButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/dialer_theme_color"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:layout_gravity="center"
+ android:divider="?android:dividerHorizontal"
+ android:gravity="center"
+ android:orientation="vertical"
+ android:showDividers="middle">
+ </LinearLayout>
+</LinearLayout>
diff --git a/java/com/android/dialer/voicemail/listui/res/values/dimens.xml b/java/com/android/dialer/voicemail/listui/res/values/dimens.xml
index 59da7f288..960d327b2 100644
--- a/java/com/android/dialer/voicemail/listui/res/values/dimens.xml
+++ b/java/com/android/dialer/voicemail/listui/res/values/dimens.xml
@@ -41,4 +41,13 @@
<dimen name="voicemail_tos_image_size">280dp</dimen>
+ <!-- Dimensions for voicemail alert -->
+ <dimen name="alert_main_padding">24dp</dimen>
+ <dimen name="voicemail_promo_card_icon_size">24dp</dimen>
+ <dimen name="voicemail_promo_card_main_padding">24dp</dimen>
+ <dimen name="voicemail_promo_card_title_padding">12dp</dimen>
+ <dimen name="voicemail_promo_card_title_text_size">16sp</dimen>
+ <dimen name="voicemail_promo_card_line_spacing">4dp</dimen>
+ <dimen name="voicemail_promo_card_message_size">14sp</dimen>
+
</resources>