1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.contacts; 18 19 import com.android.common.io.MoreCloseables; 20 import com.android.contacts.voicemail.VoicemailStatusHelperImpl; 21 22 import android.content.AsyncQueryHandler; 23 import android.database.Cursor; 24 import android.net.Uri; 25 import android.provider.VoicemailContract.Status; 26 import android.provider.VoicemailContract.Voicemails; 27 import android.util.Log; 28 29 /** 30 * Class used by {@link CallDetailActivity} to fire async content resolver queries. 31 */ 32 public class CallDetailActivityQueryHandler extends AsyncQueryHandler { 33 private static final String TAG = "CallDetail"; 34 private static final int QUERY_VOICEMAIL_CONTENT_TOKEN = 101; 35 private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 102; 36 37 private final String[] VOICEMAIL_CONTENT_PROJECTION = new String[] { 38 Voicemails.SOURCE_PACKAGE, 39 Voicemails.HAS_CONTENT 40 }; 41 private static final int SOURCE_PACKAGE_COLUMN_INDEX = 0; 42 private static final int HAS_CONTENT_COLUMN_INDEX = 1; 43 44 private final CallDetailActivity mCallDetailActivity; 45 46 public CallDetailActivityQueryHandler(CallDetailActivity callDetailActivity) { 47 super(callDetailActivity.getContentResolver()); 48 mCallDetailActivity = callDetailActivity; 49 } 50 51 /** 52 * Fires a query to update voicemail status for the given voicemail record. On completion of the 53 * query a call to {@link CallDetailActivity#updateVoicemailStatusMessage(Cursor)} is made. 54 * <p> 55 * if this is a voicemail record then it makes up to two asynchronous content resolver queries. 56 * The first one to fetch voicemail content details and check if the voicemail record has audio. 57 * If the voicemail record does not have an audio yet then it fires the second query to get the 58 * voicemail status of the associated source. 59 */ 60 public void startVoicemailStatusQuery(Uri voicemailUri) { 61 startQuery(QUERY_VOICEMAIL_CONTENT_TOKEN, null, voicemailUri, VOICEMAIL_CONTENT_PROJECTION, 62 null, null, null); 63 } 64 65 @Override 66 protected synchronized void onQueryComplete(int token, Object cookie, Cursor cursor) { 67 try { 68 if (token == QUERY_VOICEMAIL_CONTENT_TOKEN) { 69 // Query voicemail status only if this voicemail record does not have audio. 70 if (moveToFirst(cursor) && hasNoAudio(cursor)) { 71 startQuery(QUERY_VOICEMAIL_STATUS_TOKEN, null, 72 Status.buildSourceUri(getSourcePackage(cursor)), 73 VoicemailStatusHelperImpl.PROJECTION, null, null, null); 74 } else { 75 // nothing to show in status 76 mCallDetailActivity.updateVoicemailStatusMessage(null); 77 } 78 } else if (token == QUERY_VOICEMAIL_STATUS_TOKEN) { 79 mCallDetailActivity.updateVoicemailStatusMessage(cursor); 80 } else { 81 Log.w(TAG, "Unknown query completed: ignoring: " + token); 82 } 83 } finally { 84 MoreCloseables.closeQuietly(cursor); 85 } 86 } 87 88 /** Check that the cursor is non-null and can be moved to first. */ 89 private boolean moveToFirst(Cursor cursor) { 90 if (cursor == null || !cursor.moveToFirst()) { 91 Log.e(TAG, "Cursor not valid, could not move to first"); 92 return false; 93 } 94 return true; 95 } 96 97 private boolean hasNoAudio(Cursor voicemailCursor) { 98 return voicemailCursor.getInt(HAS_CONTENT_COLUMN_INDEX) == 0; 99 } 100 101 private String getSourcePackage(Cursor voicemailCursor) { 102 return voicemailCursor.getString(SOURCE_PACKAGE_COLUMN_INDEX); 103 } 104 } 105