1 /* 2 * Copyright (C) 2015 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.dialer.app.calllog; 18 19 import android.content.ContentValues; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.net.Uri; 23 import android.os.AsyncTask; 24 import android.provider.CallLog; 25 import android.provider.VoicemailContract.Voicemails; 26 import android.support.annotation.NonNull; 27 import android.support.annotation.Nullable; 28 import android.text.TextUtils; 29 import com.android.dialer.common.LogUtil; 30 import com.android.dialer.common.concurrent.AsyncTaskExecutor; 31 import com.android.dialer.common.concurrent.AsyncTaskExecutors; 32 import com.android.dialer.util.PermissionsUtil; 33 import com.android.voicemail.VoicemailClient; 34 35 /** TODO(calderwoodra): documentation */ 36 public class CallLogAsyncTaskUtil { 37 38 private static final String TAG = "CallLogAsyncTaskUtil"; 39 private static AsyncTaskExecutor asyncTaskExecutor; 40 initTaskExecutor()41 private static void initTaskExecutor() { 42 asyncTaskExecutor = AsyncTaskExecutors.createThreadPoolExecutor(); 43 } 44 markVoicemailAsRead( @onNull final Context context, @NonNull final Uri voicemailUri)45 public static void markVoicemailAsRead( 46 @NonNull final Context context, @NonNull final Uri voicemailUri) { 47 LogUtil.enterBlock("CallLogAsyncTaskUtil.markVoicemailAsRead, voicemailUri: " + voicemailUri); 48 if (asyncTaskExecutor == null) { 49 initTaskExecutor(); 50 } 51 52 asyncTaskExecutor.submit( 53 Tasks.MARK_VOICEMAIL_READ, 54 new AsyncTask<Void, Void, Void>() { 55 @Override 56 public Void doInBackground(Void... params) { 57 ContentValues values = new ContentValues(); 58 values.put(Voicemails.IS_READ, true); 59 // "External" changes to the database will be automatically marked as dirty, but this 60 // voicemail might be from dialer so it need to be marked manually. 61 values.put(Voicemails.DIRTY, 1); 62 if (context 63 .getContentResolver() 64 .update(voicemailUri, values, Voicemails.IS_READ + " = 0", null) 65 > 0) { 66 uploadVoicemailLocalChangesToServer(context); 67 CallLogNotificationsService.markAllNewVoicemailsAsOld(context); 68 } 69 return null; 70 } 71 }); 72 } 73 deleteVoicemail( @onNull final Context context, final Uri voicemailUri, @Nullable final CallLogAsyncTaskListener callLogAsyncTaskListener)74 public static void deleteVoicemail( 75 @NonNull final Context context, 76 final Uri voicemailUri, 77 @Nullable final CallLogAsyncTaskListener callLogAsyncTaskListener) { 78 if (asyncTaskExecutor == null) { 79 initTaskExecutor(); 80 } 81 82 asyncTaskExecutor.submit( 83 Tasks.DELETE_VOICEMAIL, 84 new AsyncTask<Void, Void, Void>() { 85 @Override 86 public Void doInBackground(Void... params) { 87 deleteVoicemailSynchronous(context, voicemailUri); 88 return null; 89 } 90 91 @Override 92 public void onPostExecute(Void result) { 93 if (callLogAsyncTaskListener != null) { 94 callLogAsyncTaskListener.onDeleteVoicemail(); 95 } 96 } 97 }); 98 } 99 deleteVoicemailSynchronous(Context context, Uri voicemailUri)100 public static void deleteVoicemailSynchronous(Context context, Uri voicemailUri) { 101 ContentValues values = new ContentValues(); 102 values.put(Voicemails.DELETED, "1"); 103 context.getContentResolver().update(voicemailUri, values, null, null); 104 // TODO(a bug): check which source package is changed. Don't need 105 // to upload changes on foreign voicemails, they will get a PROVIDER_CHANGED 106 uploadVoicemailLocalChangesToServer(context); 107 } 108 markCallAsRead(@onNull final Context context, @NonNull final long[] callIds)109 public static void markCallAsRead(@NonNull final Context context, @NonNull final long[] callIds) { 110 if (!PermissionsUtil.hasPhonePermissions(context) 111 || !PermissionsUtil.hasCallLogWritePermissions(context)) { 112 return; 113 } 114 if (asyncTaskExecutor == null) { 115 initTaskExecutor(); 116 } 117 118 asyncTaskExecutor.submit( 119 Tasks.MARK_CALL_READ, 120 new AsyncTask<Void, Void, Void>() { 121 @Override 122 public Void doInBackground(Void... params) { 123 124 StringBuilder where = new StringBuilder(); 125 where.append(CallLog.Calls.TYPE).append(" = ").append(CallLog.Calls.MISSED_TYPE); 126 where.append(" AND "); 127 128 Long[] callIdLongs = new Long[callIds.length]; 129 for (int i = 0; i < callIds.length; i++) { 130 callIdLongs[i] = callIds[i]; 131 } 132 where 133 .append(CallLog.Calls._ID) 134 .append(" IN (" + TextUtils.join(",", callIdLongs) + ")"); 135 136 ContentValues values = new ContentValues(1); 137 values.put(CallLog.Calls.IS_READ, "1"); 138 context 139 .getContentResolver() 140 .update(CallLog.Calls.CONTENT_URI, values, where.toString(), null); 141 return null; 142 } 143 }); 144 } 145 146 /** The enumeration of {@link AsyncTask} objects used in this class. */ 147 public enum Tasks { 148 DELETE_VOICEMAIL, 149 DELETE_CALL, 150 MARK_VOICEMAIL_READ, 151 MARK_CALL_READ, 152 GET_CALL_DETAILS, 153 UPDATE_DURATION, 154 } 155 156 /** TODO(calderwoodra): documentation */ 157 public interface CallLogAsyncTaskListener { onDeleteVoicemail()158 void onDeleteVoicemail(); 159 } 160 uploadVoicemailLocalChangesToServer(Context context)161 private static void uploadVoicemailLocalChangesToServer(Context context) { 162 Intent intent = new Intent(VoicemailClient.ACTION_UPLOAD); 163 intent.setPackage(context.getPackageName()); 164 context.sendBroadcast(intent); 165 } 166 } 167