Changes in CallDetailActivity to show voicemail status message.
- call details page now show a voicemail status message if the call in
question is a voicemail and does not have audio available.
- moved VoicemailStatusHelper and related classes into
contacts.voicemail package as it is used by CallDetailActivity as well
as calllog.CallLogFragment
Bug: 5040099
Change-Id: I9ad0c1fb60526ef55d7f38dbd2157b14af9d5b55
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index d2c193e..23436b4 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -20,6 +20,9 @@
import com.android.contacts.calllog.CallTypeHelper;
import com.android.contacts.calllog.PhoneNumberHelper;
import com.android.contacts.voicemail.VoicemailPlaybackFragment;
+import com.android.contacts.voicemail.VoicemailStatusHelper;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
import android.app.FragmentManager;
import android.app.ListActivity;
@@ -87,6 +90,14 @@
/* package */ Resources mResources;
/** Helper to load contact photos. */
private ContactPhotoManager mContactPhotoManager;
+ /** Helper to make async queries to content resolver. */
+ private CallDetailActivityQueryHandler mAsyncQueryHandler;
+ /** Helper to get voicemail status messages. */
+ private VoicemailStatusHelper mVoicemailStatusHelper;
+ // Views related to voicemail status message.
+ private View mStatusMessageView;
+ private TextView mStatusMessageText;
+ private TextView mStatusMessageAction;
static final String[] CALL_LOG_PROJECTION = new String[] {
CallLog.Calls.DATE,
@@ -137,6 +148,11 @@
mPhoneNumberHelper = new PhoneNumberHelper(mResources, getVoicemailNumber());
mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(this, mResources, mCallTypeHelper,
mPhoneNumberHelper);
+ mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
+ mAsyncQueryHandler = new CallDetailActivityQueryHandler(this);
+ mStatusMessageView = findViewById(R.id.voicemail_status);
+ mStatusMessageText = (TextView) findViewById(R.id.voicemail_status_message);
+ mStatusMessageAction = (TextView) findViewById(R.id.voicemail_status_action);
mHomeActionView = findViewById(R.id.action_bar_home);
mMainActionView = (ImageView) findViewById(R.id.main_action);
mContactBackgroundView = (ImageView) findViewById(R.id.contact_background);
@@ -153,11 +169,18 @@
});
}
+
@Override
public void onResume() {
super.onResume();
updateData(getCallLogEntryUris());
- optionallyHandleVoicemail();
+ Uri voicemailUri = getIntent().getExtras().getParcelable(EXTRA_VOICEMAIL_URI);
+ optionallyHandleVoicemail(voicemailUri);
+ if (voicemailUri != null) {
+ mAsyncQueryHandler.startVoicemailStatusQuery(voicemailUri);
+ } else {
+ mStatusMessageView.setVisibility(View.GONE);
+ }
}
/**
@@ -166,11 +189,10 @@
* If the Intent used to start this Activity contains the suitable extras, then start voicemail
* playback. If it doesn't, then hide the voicemail ui.
*/
- private void optionallyHandleVoicemail() {
+ private void optionallyHandleVoicemail(Uri voicemailUri) {
FragmentManager manager = getFragmentManager();
VoicemailPlaybackFragment fragment = (VoicemailPlaybackFragment) manager.findFragmentById(
R.id.voicemail_playback_fragment);
- Uri voicemailUri = getIntent().getExtras().getParcelable(EXTRA_VOICEMAIL_URI);
if (voicemailUri == null) {
// No voicemail uri: hide the voicemail fragment.
manager.beginTransaction().hide(fragment).commit();
@@ -554,4 +576,48 @@
ContactsSearchManager.startSearch(this, initialQuery);
}
}
+
+ protected void updateVoicemailStatusMessage(Cursor statusCursor) {
+ if (statusCursor == null) {
+ mStatusMessageView.setVisibility(View.GONE);
+ return;
+ }
+ final StatusMessage message = getStatusMessage(statusCursor);
+ if (message == null || !message.showInCallDetails()) {
+ mStatusMessageView.setVisibility(View.GONE);
+ return;
+ }
+
+ mStatusMessageView.setVisibility(View.VISIBLE);
+ mStatusMessageText.setText(message.callDetailsMessageId);
+ if (message.actionMessageId != -1) {
+ mStatusMessageAction.setText(message.actionMessageId);
+ }
+ if (message.actionUri != null) {
+ mStatusMessageAction.setClickable(true);
+ mStatusMessageAction.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startActivity(new Intent(Intent.ACTION_VIEW, message.actionUri));
+ }
+ });
+ } else {
+ mStatusMessageAction.setClickable(false);
+ }
+ }
+
+ private StatusMessage getStatusMessage(Cursor statusCursor) {
+ List<StatusMessage> messages = mVoicemailStatusHelper.getStatusMessages(statusCursor);
+ Log.d(TAG, "Num status messages: " + messages.size());
+ if (messages.size() == 0) {
+ return null;
+ }
+ // There can only be a single status message per source package, so num of messages can
+ // at most be 1.
+ if (messages.size() > 1) {
+ Log.w(TAG, String.format("Expected 1, found (%d) num of status messages." +
+ " Will use the first one.", messages.size()));
+ }
+ return messages.get(0);
+ }
}
diff --git a/src/com/android/contacts/CallDetailActivityQueryHandler.java b/src/com/android/contacts/CallDetailActivityQueryHandler.java
new file mode 100644
index 0000000..c1d87b2
--- /dev/null
+++ b/src/com/android/contacts/CallDetailActivityQueryHandler.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 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.contacts;
+
+import com.android.common.io.MoreCloseables;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+
+import android.content.AsyncQueryHandler;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.VoicemailContract.Status;
+import android.provider.VoicemailContract.Voicemails;
+import android.util.Log;
+
+/**
+ * Class used by {@link CallDetailActivity} to fire async content resolver queries.
+ */
+public class CallDetailActivityQueryHandler extends AsyncQueryHandler {
+ private static final String TAG = "CallDetail";
+ private static final int QUERY_VOICEMAIL_CONTENT_TOKEN = 101;
+ private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 102;
+
+ private final String[] VOICEMAIL_CONTENT_PROJECTION = new String[] {
+ Voicemails.SOURCE_PACKAGE,
+ Voicemails.HAS_CONTENT
+ };
+ private static final int SOURCE_PACKAGE_COLUMN_INDEX = 0;
+ private static final int HAS_CONTENT_COLUMN_INDEX = 1;
+
+ private final CallDetailActivity mCallDetailActivity;
+
+ public CallDetailActivityQueryHandler(CallDetailActivity callDetailActivity) {
+ super(callDetailActivity.getContentResolver());
+ mCallDetailActivity = callDetailActivity;
+ }
+
+ /**
+ * Fires a query to update voicemail status for the given voicemail record. On completion of the
+ * query a call to {@link CallDetailActivity#updateVoicemailStatusMessage(Cursor)} is made.
+ * <p>
+ * if this is a voicemail record then it makes up to two asynchronous content resolver queries.
+ * The first one to fetch voicemail content details and check if the voicemail record has audio.
+ * If the voicemail record does not have an audio yet then it fires the second query to get the
+ * voicemail status of the associated source.
+ */
+ public void startVoicemailStatusQuery(Uri voicemaiUri) {
+ startQuery(QUERY_VOICEMAIL_CONTENT_TOKEN, null, voicemaiUri, VOICEMAIL_CONTENT_PROJECTION,
+ null, null, null);
+ }
+
+ @Override
+ protected synchronized void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ try {
+ if (token == QUERY_VOICEMAIL_CONTENT_TOKEN) {
+ // Query voicemail status only if this voicemail record does not have audio.
+ if (cursor.moveToFirst() && hasNoAudio(cursor)) {
+ startQuery(QUERY_VOICEMAIL_STATUS_TOKEN, null,
+ Status.buildSourceUri(getSourcePackage(cursor)),
+ VoicemailStatusHelperImpl.PROJECTION, null, null, null);
+ } else {
+ mCallDetailActivity.updateVoicemailStatusMessage(null);
+ }
+ } else if (token == QUERY_VOICEMAIL_STATUS_TOKEN) {
+ mCallDetailActivity.updateVoicemailStatusMessage(cursor);
+ } else {
+ Log.w(TAG, "Unknown query completed: ignoring: " + token);
+ }
+ } finally {
+ MoreCloseables.closeQuietly(cursor);
+ }
+ }
+
+ private boolean hasNoAudio(Cursor voicemailCursor) {
+ return voicemailCursor.getInt(HAS_CONTENT_COLUMN_INDEX) == 0;
+ }
+
+ private String getSourcePackage(Cursor voicemailCursor) {
+ return voicemailCursor.getString(SOURCE_PACKAGE_COLUMN_INDEX);
+ }
+}
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 1aa4d3d..28f642c 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -25,8 +25,10 @@
import com.android.contacts.R;
import com.android.contacts.activities.DialtactsActivity;
import com.android.contacts.activities.DialtactsActivity.ViewPagerVisibilityListener;
-import com.android.contacts.calllog.VoicemailStatusHelper.StatusMessage;
import com.android.contacts.util.ExpirableCache;
+import com.android.contacts.voicemail.VoicemailStatusHelper;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
import com.android.internal.telephony.CallerInfo;
import com.google.common.annotations.VisibleForTesting;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index 62e308c..8569190 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -18,6 +18,7 @@
import com.android.common.io.MoreCloseables;
import com.android.contacts.calllog.CallLogFragment.CallLogQuery;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
import android.content.AsyncQueryHandler;
import android.content.ContentValues;
diff --git a/src/com/android/contacts/calllog/VoicemailStatusHelper.java b/src/com/android/contacts/voicemail/VoicemailStatusHelper.java
similarity index 98%
rename from src/com/android/contacts/calllog/VoicemailStatusHelper.java
rename to src/com/android/contacts/voicemail/VoicemailStatusHelper.java
index f6def45..1eab749 100644
--- a/src/com/android/contacts/calllog/VoicemailStatusHelper.java
+++ b/src/com/android/contacts/voicemail/VoicemailStatusHelper.java
@@ -14,7 +14,7 @@
* limitations under the License
*/
-package com.android.contacts.calllog;
+package com.android.contacts.voicemail;
import android.database.Cursor;
import android.net.Uri;
diff --git a/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java b/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
similarity index 98%
rename from src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
rename to src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
index 972fbd5..7332e89 100644
--- a/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
+++ b/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
@@ -14,7 +14,7 @@
* limitations under the License
*/
-package com.android.contacts.calllog;
+package com.android.contacts.voicemail;
import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE_CAN_BE_CONFIGURED;
import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE_OK;
@@ -46,7 +46,7 @@
private static final int VOICEMAIL_ACCESS_URI_INDEX = 5;
private static final int NUM_COLUMNS = 6;
/** Projection on the voicemail_status table used by this class. */
- protected static final String[] PROJECTION = new String[NUM_COLUMNS];
+ public static final String[] PROJECTION = new String[NUM_COLUMNS];
static {
PROJECTION[SOURCE_PACKAGE_INDEX] = Status.SOURCE_PACKAGE;
PROJECTION[CONFIGURATION_STATE_INDEX] = Status.CONFIGURATION_STATE;
diff --git a/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java b/tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
similarity index 97%
rename from tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
rename to tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
index 9b293c4..7ac7e49 100644
--- a/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
+++ b/tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.contacts.calllog;
+package com.android.contacts.voicemail;
import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE;
import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE_CAN_BE_CONFIGURED;
@@ -28,7 +28,9 @@
import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK;
import com.android.contacts.R;
-import com.android.contacts.calllog.VoicemailStatusHelper.StatusMessage;
+import com.android.contacts.voicemail.VoicemailStatusHelper;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
import android.content.ContentResolver;
import android.content.ContentValues;