Made voicemail status query from calllogfragment asynchronous.
callLogQueryHandler is now used to fetch voicemail_status cursor and
pass that to VoicemailStatusHelper to compute the messages for display.
VoicemailStatusHelper no longer make direct call to the content
provider, so is now safe to be used from the ui thread.
Also, modified status message layout to have visibility=gone as a
default value.
Change-Id: I2dce71080d974c318adcbd134e91df85ac6ce611
diff --git a/res/layout/call_log_voicemail_status.xml b/res/layout/call_log_voicemail_status.xml
index 1abe998..fee2210 100644
--- a/res/layout/call_log_voicemail_status.xml
+++ b/res/layout/call_log_voicemail_status.xml
@@ -20,7 +20,8 @@
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:background="?attr/call_log_voicemail_status_background_color"
- android:baselineAligned="false">
+ android:baselineAligned="false"
+ android:visibility="gone">
<TextView
android:id="@+id/voicemail_status_message"
android:layout_width="wrap_content"
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 7db5281..0f95700 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -334,7 +334,7 @@
@Override
protected void onContentChanged() {
// Start async requery
- startQuery();
+ startCallsQuery();
}
void setLoading(boolean loading) {
@@ -887,10 +887,20 @@
}
}
+ /**
+ * Called by {@link CallLogQueryHandler} after a successful query to voicemail status provider.
+ */
+ public void onVoicemailStatusFetched(Cursor statusCursor) {
+ if (getActivity() == null || getActivity().isFinishing()) {
+ return;
+ }
+ updateVoicemailStatusMessage(statusCursor);
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
View view = inflater.inflate(R.layout.call_log_fragment, container, false);
- mVoicemailStatusHelper = new VoicemailStatusHelperImpl(getActivity().getContentResolver());
+ mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
mStatusMessageView = view.findViewById(R.id.voicemail_status);
mStatusMessageText = (TextView) view.findViewById(R.id.voicemail_status_message);
mStatusMessageAction = (TextView) view.findViewById(R.id.voicemail_status_action);
@@ -918,17 +928,16 @@
mAdapter.invalidateCache();
}
- startQuery();
+ startCallsQuery();
resetNewCallsFlag();
- updateVoicemailStatusMessage();
+ startVoicemailStatusQuery();
super.onResume();
mAdapter.mPreDrawListener = null; // Let it restart the thread after next draw
}
- private void updateVoicemailStatusMessage() {
- // TODO: make call to mVoicemailStatusHelper asynchronously.
- List<StatusMessage> messages = mVoicemailStatusHelper.getStatusMessages();
+ private void updateVoicemailStatusMessage(Cursor statusCursor) {
+ List<StatusMessage> messages = mVoicemailStatusHelper.getStatusMessages(statusCursor);
if (messages.size() == 0) {
mStatusMessageView.setVisibility(View.GONE);
} else {
@@ -1000,11 +1009,15 @@
mCallLogQueryHandler.updateMissedCalls();
}
- private void startQuery() {
+ private void startCallsQuery() {
mAdapter.setLoading(true);
mCallLogQueryHandler.fetchCalls();
}
+ private void startVoicemailStatusQuery() {
+ mCallLogQueryHandler.fetchVoicemailStatus();
+ }
+
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index 977c84a..a56f778 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -32,6 +32,7 @@
import android.os.Looper;
import android.os.Message;
import android.provider.CallLog.Calls;
+import android.provider.VoicemailContract.Status;
import android.util.Log;
import java.lang.ref.WeakReference;
@@ -49,6 +50,9 @@
/** The token for the query to mark all missed calls as old after seeing the call log. */
private static final int UPDATE_MISSED_CALLS_TOKEN = 55;
+ /** The token for the query to fetch voicemail status messages. */
+ private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 56;
+
private final WeakReference<CallLogFragment> mFragment;
/** The cursor containing the new calls, or null if they have not yet been fetched. */
@@ -131,6 +135,11 @@
fetchOldCalls();
}
+ public void fetchVoicemailStatus() {
+ startQuery(QUERY_VOICEMAIL_STATUS_TOKEN, null, Status.CONTENT_URI,
+ VoicemailStatusHelperImpl.PROJECTION, null, null, null);
+ }
+
/** Fetches the list of new calls in the call log. */
private void fetchNewCalls() {
fetchCalls(QUERY_NEW_CALLS_TOKEN, true);
@@ -204,6 +213,9 @@
// Store the returned cursor.
mOldCallsCursor = new ExtendedCursor(
cursor, CallLogQuery.SECTION_NAME, CallLogQuery.SECTION_OLD_ITEM);
+ } else if (token == QUERY_VOICEMAIL_STATUS_TOKEN) {
+ updateVoicemailStatus(cursor);
+ return;
} else {
Log.w(TAG, "Unknown query completed: ignoring: " + token);
return;
@@ -253,4 +265,11 @@
fragment.onCallsFetched(combinedCursor);
}
}
-}
+
+ private void updateVoicemailStatus(Cursor statusCursor) {
+ final CallLogFragment fragment = mFragment.get();
+ if (fragment != null) {
+ fragment.onVoicemailStatusFetched(statusCursor);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/calllog/VoicemailStatusHelper.java b/src/com/android/contacts/calllog/VoicemailStatusHelper.java
index 607d31a..910a4f7 100644
--- a/src/com/android/contacts/calllog/VoicemailStatusHelper.java
+++ b/src/com/android/contacts/calllog/VoicemailStatusHelper.java
@@ -16,7 +16,9 @@
package com.android.contacts.calllog;
+import android.database.Cursor;
import android.net.Uri;
+import android.provider.VoicemailContract.Status;
import java.util.List;
@@ -51,6 +53,10 @@
/**
* Returns a list of messages, in the order or priority that should be shown to the user. An
* empty list is returned if no message needs to be shown.
+ * @param cursor The cursor pointing to the query on {@link Status#CONTENT_URI}. The projection
+ * to be used is defined by the implementation class of this interface.
+ * The class takes over the ownership of the cursor and closes it after processing the
+ * request.
*/
- public List<StatusMessage> getStatusMessages();
+ public List<StatusMessage> getStatusMessages(Cursor cursor);
}
diff --git a/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java b/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
index 690f102..6296542 100644
--- a/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
+++ b/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
@@ -27,7 +27,6 @@
import com.android.common.io.MoreCloseables;
import com.android.contacts.R;
-import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.VoicemailContract.Status;
@@ -46,7 +45,8 @@
private static final int SETTINGS_URI_INDEX = 4;
private static final int VOICEMAIL_ACCESS_URI_INDEX = 5;
private static final int NUM_COLUMNS = 6;
- private static final String[] PROJECTION = new String[NUM_COLUMNS];
+ /** Projection on the voicemail_status table used by this class. */
+ protected static final String[] PROJECTION = new String[NUM_COLUMNS];
static {
PROJECTION[SOURCE_PACKAGE_INDEX] = Status.SOURCE_PACKAGE;
PROJECTION[CONFIGURATION_STATE_INDEX] = Status.CONFIGURATION_STATE;
@@ -127,12 +127,6 @@
}
}
- private final ContentResolver mContentResolver;
-
- public VoicemailStatusHelperImpl(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- }
-
/** A wrapper on {@link StatusMessage} which additionally stores the priority of the message. */
private static class MessageStatusWithPriority {
private final StatusMessage mMessage;
@@ -145,12 +139,10 @@
}
@Override
- public List<StatusMessage> getStatusMessages() {
- Cursor cursor = null;
+ public List<StatusMessage> getStatusMessages(Cursor cursor) {
try {
- cursor = mContentResolver.query(Status.CONTENT_URI, PROJECTION, null, null, null);
List<MessageStatusWithPriority> messages =
- new ArrayList<VoicemailStatusHelperImpl.MessageStatusWithPriority>();
+ new ArrayList<VoicemailStatusHelperImpl.MessageStatusWithPriority>();
while(cursor.moveToNext()) {
MessageStatusWithPriority message = getMessageForStatusEntry(cursor);
if (message != null) {
diff --git a/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java b/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
index c6bff13..0501a9a 100644
--- a/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
+++ b/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
@@ -32,6 +32,7 @@
import android.content.ContentResolver;
import android.content.ContentValues;
+import android.database.Cursor;
import android.net.Uri;
import android.provider.VoicemailContract.Status;
import android.test.AndroidTestCase;
@@ -71,7 +72,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mStatusHelper = new VoicemailStatusHelperImpl(getContentResolver());
+ mStatusHelper = new VoicemailStatusHelperImpl();
}
@Override
@@ -87,14 +88,15 @@
super.tearDown();
}
+
public void testNoStatusEntries() {
- assertEquals(0, mStatusHelper.getStatusMessages().size());
+ assertEquals(0, getStatusMessages().size());
}
public void testAllOK() {
insertEntryForPackage(TEST_PACKAGE_1, getAllOkStatusValues());
insertEntryForPackage(TEST_PACKAGE_2, getAllOkStatusValues());
- assertEquals(0, mStatusHelper.getStatusMessages().size());
+ assertEquals(0, getStatusMessages().size());
}
public void testNotAllOKForOnePackage() {
@@ -167,7 +169,7 @@
// package2 with valuesNoNotificationNoDataChannel. Package2 should be above.
updateEntryForPackage(TEST_PACKAGE_1, valuesNoNotificationGoodDataChannel);
updateEntryForPackage(TEST_PACKAGE_2, valuesNoNotificationNoDataChannel);
- List<StatusMessage> messages = mStatusHelper.getStatusMessages();
+ List<StatusMessage> messages = getStatusMessages();
assertEquals(2, messages.size());
assertEquals(TEST_PACKAGE_1, messages.get(1).sourcePackage);
assertEquals(TEST_PACKAGE_2, messages.get(0).sourcePackage);
@@ -175,7 +177,7 @@
// Now reverse the values - ordering should be reversed as well.
updateEntryForPackage(TEST_PACKAGE_1, valuesNoNotificationNoDataChannel);
updateEntryForPackage(TEST_PACKAGE_2, valuesNoNotificationGoodDataChannel);
- messages = mStatusHelper.getStatusMessages();
+ messages = getStatusMessages();
assertEquals(2, messages.size());
assertEquals(TEST_PACKAGE_1, messages.get(0).sourcePackage);
assertEquals(TEST_PACKAGE_2, messages.get(1).sourcePackage);
@@ -190,7 +192,7 @@
private void checkExpectedMessage(String sourcePackage, ContentValues values,
int expectedStatusMsg, int expectedActionMsg, Uri expectedUri) {
- List<StatusMessage> messages = mStatusHelper.getStatusMessages();
+ List<StatusMessage> messages = getStatusMessages();
assertEquals(1, messages.size());
checkMessageMatches(messages.get(0), sourcePackage, expectedStatusMsg, expectedActionMsg,
expectedUri);
@@ -210,7 +212,7 @@
private void checkNoMessages(String sourcePackage, ContentValues values) {
assertEquals(1, updateEntryForPackage(sourcePackage, values));
- List<StatusMessage> messages = mStatusHelper.getStatusMessages();
+ List<StatusMessage> messages = getStatusMessages();
assertEquals(0, messages.size());
}
@@ -241,6 +243,12 @@
Status.buildSourceUri(sourcePackage), values, null, null);
}
+ private List<StatusMessage> getStatusMessages() {
+ Cursor cursor = getContentResolver().query(Status.CONTENT_URI,
+ VoicemailStatusHelperImpl.PROJECTION, null, null, null);
+ return mStatusHelper.getStatusMessages(cursor);
+ }
+
private ContentResolver getContentResolver() {
return getContext().getContentResolver();
}