From cdcda1a127c4841c2710c17f64a2f522c62cd512 Mon Sep 17 00:00:00 2001 From: uabdullah Date: Sun, 11 Feb 2018 16:49:45 -0800 Subject: Use UI Listeners for querying voicemail status table Earlier we were using the legacy CallLogQueryHandler for querying the voicemail status table. However we should be using UI Listeners instead in NUI. This CL queries the voicemail status table and returns a list of voicemail status', which are then used to display the corresponding error messages. This CL also moved VoicemailStatus out of the legacy dialer/database and moves it to dialer/voicemailstatus and ensures that there are no dependencies on the legacy dialer/database in the NUI. Bug: 73139237 Test: Unit tests PiperOrigin-RevId: 185321023 Change-Id: Id16ea475b6a52da380fbf8b3590dc75cbcdc370e --- .../dialer/database/CallLogQueryHandler.java | 1 + .../dialer/database/VoicemailStatusQuery.java | 91 ------------------ .../voicemail/listui/NewVoicemailAdapter.java | 41 +++----- .../voicemail/listui/NewVoicemailFragment.java | 104 ++++++++++++++++----- .../voicemail/listui/error/VoicemailStatus.java | 2 +- .../listui/error/VoicemailStatusWorker.java | 2 +- .../voicemailstatus/VoicemailStatusHelper.java | 1 - .../voicemailstatus/VoicemailStatusQuery.java | 91 ++++++++++++++++++ 8 files changed, 188 insertions(+), 145 deletions(-) delete mode 100644 java/com/android/dialer/database/VoicemailStatusQuery.java create mode 100644 java/com/android/dialer/voicemailstatus/VoicemailStatusQuery.java (limited to 'java') diff --git a/java/com/android/dialer/database/CallLogQueryHandler.java b/java/com/android/dialer/database/CallLogQueryHandler.java index 1aa125184..92c49a09e 100644 --- a/java/com/android/dialer/database/CallLogQueryHandler.java +++ b/java/com/android/dialer/database/CallLogQueryHandler.java @@ -40,6 +40,7 @@ import com.android.dialer.compat.SdkVersionOverride; import com.android.dialer.phonenumbercache.CallLogQuery; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.PermissionsUtil; +import com.android.dialer.voicemailstatus.VoicemailStatusQuery; import com.android.voicemail.VoicemailComponent; import java.lang.ref.WeakReference; import java.util.ArrayList; diff --git a/java/com/android/dialer/database/VoicemailStatusQuery.java b/java/com/android/dialer/database/VoicemailStatusQuery.java deleted file mode 100644 index dbd88be1f..000000000 --- a/java/com/android/dialer/database/VoicemailStatusQuery.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2016 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.database; - -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.provider.VoicemailContract.Status; -import android.support.annotation.RequiresApi; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** The query for the call voicemail status table. */ -public class VoicemailStatusQuery { - - // TODO(maxwelb): Column indices should be removed in favor of Cursor#getColumnIndex - public static final int SOURCE_PACKAGE_INDEX = 0; - public static final int SETTINGS_URI_INDEX = 1; - public static final int VOICEMAIL_ACCESS_URI_INDEX = 2; - public static final int CONFIGURATION_STATE_INDEX = 3; - public static final int DATA_CHANNEL_STATE_INDEX = 4; - public static final int NOTIFICATION_CHANNEL_STATE_INDEX = 5; - - @RequiresApi(VERSION_CODES.N) - public static final int QUOTA_OCCUPIED_INDEX = 6; - - @RequiresApi(VERSION_CODES.N) - public static final int QUOTA_TOTAL_INDEX = 7; - - @RequiresApi(VERSION_CODES.N_MR1) - // The PHONE_ACCOUNT columns were added in M, but aren't queryable until N MR1 - public static final int PHONE_ACCOUNT_COMPONENT_NAME = 8; - - @RequiresApi(VERSION_CODES.N_MR1) - public static final int PHONE_ACCOUNT_ID = 9; - - @RequiresApi(VERSION_CODES.N_MR1) - public static final int SOURCE_TYPE_INDEX = 10; - - private static final String[] PROJECTION_M = - new String[] { - Status.SOURCE_PACKAGE, // 0 - Status.SETTINGS_URI, // 1 - Status.VOICEMAIL_ACCESS_URI, // 2 - Status.CONFIGURATION_STATE, // 3 - Status.DATA_CHANNEL_STATE, // 4 - Status.NOTIFICATION_CHANNEL_STATE // 5 - }; - - @RequiresApi(VERSION_CODES.N) - private static final String[] PROJECTION_N; - - @RequiresApi(VERSION_CODES.N_MR1) - private static final String[] PROJECTION_NMR1; - - static { - List projectionList = new ArrayList<>(Arrays.asList(PROJECTION_M)); - projectionList.add(Status.QUOTA_OCCUPIED); // 6 - projectionList.add(Status.QUOTA_TOTAL); // 7 - PROJECTION_N = projectionList.toArray(new String[projectionList.size()]); - - projectionList.add(Status.PHONE_ACCOUNT_COMPONENT_NAME); // 8 - projectionList.add(Status.PHONE_ACCOUNT_ID); // 9 - projectionList.add(Status.SOURCE_TYPE); // 10 - PROJECTION_NMR1 = projectionList.toArray(new String[projectionList.size()]); - } - - public static String[] getProjection() { - if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) { - return PROJECTION_NMR1; - } - if (VERSION.SDK_INT >= VERSION_CODES.N) { - return PROJECTION_N; - } - return PROJECTION_M; - } -} diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java index 05a3bc951..044d8df6d 100644 --- a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java +++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java @@ -25,7 +25,6 @@ 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; @@ -49,10 +48,9 @@ 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 com.google.common.collect.ImmutableList; 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; @@ -74,7 +72,6 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter } private Cursor cursor; - private Cursor voicemailStatusCursor; private final Clock clock; private final GlidePhotoManager glidePhotoManager; @@ -880,6 +877,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter new OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { + LogUtil.e("NewVoicemailAdapter.onError", "onError, what:%d, extra:%d", what, extra); Assert.checkArgument( mediaPlayer.getMediaPlayer().equals(mp), "there should always only be one instance of the media player"); @@ -1009,36 +1007,24 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter } } - @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) - public void setVoicemailStatusCursor(Cursor voicemailStatusCursor) { - this.voicemailStatusCursor = voicemailStatusCursor; - } + /** + * Updates the voicemail alert message to reflect the state of the {@link VoicemailStatus} table. + * TODO(uabdullah): Handle ToS properly (a bug) + */ + public void updateVoicemailAlertWithMostRecentStatus( + Context context, ImmutableList voicemailStatuses) { - // TODO(uabdullah): Handle ToS properly - public void updateAlert(Context context) { - if (voicemailStatusCursor == null) { - LogUtil.i("NewVoicemailAdapter.updateAlert", "status cursor was null"); + if (voicemailStatuses.isEmpty()) { + LogUtil.i( + "NewVoicemailAdapter.updateVoicemailAlertWithMostRecentStatus", + "voicemailStatuses was empty"); return; } - LogUtil.i( - "NewVoicemailAdapter.updateAlert", - "status cursor size was " + voicemailStatusCursor.getCount()); - - List 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) { + for (VoicemailStatus status : voicemailStatuses) { voicemailErrorMessage = messageCreator.create(context, status, null); if (voicemailErrorMessage != null) { break; @@ -1046,6 +1032,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter } if (voicemailErrorMessage != null) { + LogUtil.i("NewVoicemailAdapter.updateVoicemailAlertWithMostRecentStatus", "showing alert"); voicemailAlertPosition = 0; updateHeaderPositions(); notifyItemChanged(0); diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java index 45a544323..8b6fcbc07 100644 --- a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java +++ b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java @@ -16,8 +16,10 @@ package com.android.dialer.voicemail.listui; +import android.content.Context; import android.database.Cursor; import android.os.Bundle; +import android.provider.VoicemailContract.Status; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; @@ -35,10 +37,14 @@ import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DialerExecutorComponent; import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.common.concurrent.UiListener; -import com.android.dialer.database.CallLogQueryHandler; -import com.android.dialer.database.CallLogQueryHandler.Listener; import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent; +import com.android.dialer.voicemail.listui.error.VoicemailStatus; +import com.android.dialer.voicemailstatus.VoicemailStatusQuery; +import com.android.voicemail.VoicemailComponent; +import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.ListenableFuture; +import java.util.ArrayList; +import java.util.List; // TODO(uabdullah): Register content observer for VoicemailContract.Status.CONTENT_URI in onStart /** Fragment for Dialer Voicemail Tab. */ @@ -57,8 +63,9 @@ public final class NewVoicemailFragment extends Fragment private UiListener refreshAnnotatedCallLogListener; @Nullable private Runnable refreshAnnotatedCallLogRunnable; + private UiListener> queryVoicemailStatusTableListener; + private RecyclerView recyclerView; - private CallLogQueryHandler callLogQueryHandler; public NewVoicemailFragment() { LogUtil.enterBlock("NewVoicemailFragment.NewVoicemailFragment"); @@ -79,6 +86,13 @@ public final class NewVoicemailFragment extends Fragment DialerExecutorComponent.get(getContext()) .createUiListener( getActivity().getFragmentManager(), "NewVoicemailFragment.refreshAnnotatedCallLog"); + + queryVoicemailStatusTableListener = + DialerExecutorComponent.get(getContext()) + .createUiListener( + getActivity().getFragmentManager(), + "NewVoicemailFragment.queryVoicemailStatusTable"); + refreshAnnotatedCallLogWorker = component.getRefreshAnnotatedCallLogWorker(); } @@ -192,31 +206,73 @@ public final class NewVoicemailFragment extends Fragment ((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()); - } + queryAndUpdateVoicemailStatusAlert(); + } - @Override - public void onVoicemailUnreadCountFetched(Cursor cursor) {} + private void queryAndUpdateVoicemailStatusAlert() { + queryVoicemailStatusTableListener.listen( + getContext(), + queryVoicemailStatus(getContext()), + this::updateVoicemailStatusAlert, + throwable -> { + throw new RuntimeException(throwable); + }); + } - @Override - public void onMissedCallsUnreadCountFetched(Cursor cursor) {} + private ListenableFuture> queryVoicemailStatus(Context context) { + return DialerExecutorComponent.get(context) + .backgroundExecutor() + .submit( + () -> { + StringBuilder where = new StringBuilder(); + List selectionArgs = new ArrayList<>(); + + VoicemailComponent.get(context) + .getVoicemailClient() + .appendOmtpVoicemailStatusSelectionClause(context, where, selectionArgs); + + ImmutableList.Builder statuses = ImmutableList.builder(); + + try (Cursor cursor = + context + .getContentResolver() + .query( + Status.CONTENT_URI, + VoicemailStatusQuery.getProjection(), + where.toString(), + selectionArgs.toArray(new String[selectionArgs.size()]), + null)) { + if (cursor == null) { + LogUtil.e( + "NewVoicemailFragment.queryVoicemailStatus", "query failed. Null cursor."); + return statuses.build(); + } + + LogUtil.i( + "NewVoicemailFragment.queryVoicemailStatus", + "cursor size:%d ", + cursor.getCount()); + + while (cursor.moveToNext()) { + VoicemailStatus status = new VoicemailStatus(context, cursor); + if (status.isActive()) { + statuses.add(status); + // TODO(a bug): Handle Service State Listeners + } + } + } + LogUtil.i( + "NewVoicemailFragment.queryVoicemailStatus", + "query returned %d results", + statuses.build().size()); + return statuses.build(); + }); + } - @Override - public boolean onCallsFetched(Cursor combinedCursor) { - return false; - } + private void updateVoicemailStatusAlert(ImmutableList voicemailStatuses) { + ((NewVoicemailAdapter) recyclerView.getAdapter()) + .updateVoicemailAlertWithMostRecentStatus(getContext(), voicemailStatuses); } @Override diff --git a/java/com/android/dialer/voicemail/listui/error/VoicemailStatus.java b/java/com/android/dialer/voicemail/listui/error/VoicemailStatus.java index 3447f03df..9b7b7fd86 100644 --- a/java/com/android/dialer/voicemail/listui/error/VoicemailStatus.java +++ b/java/com/android/dialer/voicemail/listui/error/VoicemailStatus.java @@ -33,7 +33,7 @@ import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.text.TextUtils; import com.android.dialer.common.LogUtil; -import com.android.dialer.database.VoicemailStatusQuery; +import com.android.dialer.voicemailstatus.VoicemailStatusQuery; /** Structured data from {@link android.provider.VoicemailContract.Status} */ public class VoicemailStatus { diff --git a/java/com/android/dialer/voicemail/listui/error/VoicemailStatusWorker.java b/java/com/android/dialer/voicemail/listui/error/VoicemailStatusWorker.java index 20e46ee2d..df58d419f 100644 --- a/java/com/android/dialer/voicemail/listui/error/VoicemailStatusWorker.java +++ b/java/com/android/dialer/voicemail/listui/error/VoicemailStatusWorker.java @@ -23,8 +23,8 @@ import android.os.Build.VERSION_CODES; import android.provider.VoicemailContract.Status; import android.support.annotation.Nullable; import com.android.dialer.common.concurrent.DialerExecutor.Worker; -import com.android.dialer.database.VoicemailStatusQuery; import com.android.dialer.telecom.TelecomUtil; +import com.android.dialer.voicemailstatus.VoicemailStatusQuery; import com.android.voicemail.VoicemailComponent; import java.util.ArrayList; import java.util.List; diff --git a/java/com/android/dialer/voicemailstatus/VoicemailStatusHelper.java b/java/com/android/dialer/voicemailstatus/VoicemailStatusHelper.java index 313fc1be1..16a8c7b69 100644 --- a/java/com/android/dialer/voicemailstatus/VoicemailStatusHelper.java +++ b/java/com/android/dialer/voicemailstatus/VoicemailStatusHelper.java @@ -18,7 +18,6 @@ package com.android.dialer.voicemailstatus; import android.database.Cursor; import android.provider.VoicemailContract.Status; -import com.android.dialer.database.VoicemailStatusQuery; /** * Utility used by the call log UI to determine what user message, if any, related to voicemail diff --git a/java/com/android/dialer/voicemailstatus/VoicemailStatusQuery.java b/java/com/android/dialer/voicemailstatus/VoicemailStatusQuery.java new file mode 100644 index 000000000..4a6e9f703 --- /dev/null +++ b/java/com/android/dialer/voicemailstatus/VoicemailStatusQuery.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016 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.voicemailstatus; + +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.provider.VoicemailContract.Status; +import android.support.annotation.RequiresApi; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** The query for the call voicemail status table. */ +public class VoicemailStatusQuery { + + // TODO(maxwelb): Column indices should be removed in favor of Cursor#getColumnIndex + public static final int SOURCE_PACKAGE_INDEX = 0; + public static final int SETTINGS_URI_INDEX = 1; + public static final int VOICEMAIL_ACCESS_URI_INDEX = 2; + public static final int CONFIGURATION_STATE_INDEX = 3; + public static final int DATA_CHANNEL_STATE_INDEX = 4; + public static final int NOTIFICATION_CHANNEL_STATE_INDEX = 5; + + @RequiresApi(VERSION_CODES.N) + public static final int QUOTA_OCCUPIED_INDEX = 6; + + @RequiresApi(VERSION_CODES.N) + public static final int QUOTA_TOTAL_INDEX = 7; + + @RequiresApi(VERSION_CODES.N_MR1) + // The PHONE_ACCOUNT columns were added in M, but aren't queryable until N MR1 + public static final int PHONE_ACCOUNT_COMPONENT_NAME = 8; + + @RequiresApi(VERSION_CODES.N_MR1) + public static final int PHONE_ACCOUNT_ID = 9; + + @RequiresApi(VERSION_CODES.N_MR1) + public static final int SOURCE_TYPE_INDEX = 10; + + private static final String[] PROJECTION_M = + new String[] { + Status.SOURCE_PACKAGE, // 0 + Status.SETTINGS_URI, // 1 + Status.VOICEMAIL_ACCESS_URI, // 2 + Status.CONFIGURATION_STATE, // 3 + Status.DATA_CHANNEL_STATE, // 4 + Status.NOTIFICATION_CHANNEL_STATE // 5 + }; + + @RequiresApi(VERSION_CODES.N) + private static final String[] PROJECTION_N; + + @RequiresApi(VERSION_CODES.N_MR1) + private static final String[] PROJECTION_NMR1; + + static { + List projectionList = new ArrayList<>(Arrays.asList(PROJECTION_M)); + projectionList.add(Status.QUOTA_OCCUPIED); // 6 + projectionList.add(Status.QUOTA_TOTAL); // 7 + PROJECTION_N = projectionList.toArray(new String[projectionList.size()]); + + projectionList.add(Status.PHONE_ACCOUNT_COMPONENT_NAME); // 8 + projectionList.add(Status.PHONE_ACCOUNT_ID); // 9 + projectionList.add(Status.SOURCE_TYPE); // 10 + PROJECTION_NMR1 = projectionList.toArray(new String[projectionList.size()]); + } + + public static String[] getProjection() { + if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) { + return PROJECTION_NMR1; + } + if (VERSION.SDK_INT >= VERSION_CODES.N) { + return PROJECTION_N; + } + return PROJECTION_M; + } +} -- cgit v1.2.3