1 /* 2 * Copyright (C) 2017 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 package com.android.dialer.calllog.database; 17 18 import android.content.ContentProviderOperation; 19 import android.content.ContentUris; 20 import android.content.ContentValues; 21 import android.content.Context; 22 import android.content.OperationApplicationException; 23 import android.os.RemoteException; 24 import android.support.annotation.WorkerThread; 25 import android.text.TextUtils; 26 import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract; 27 import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; 28 import com.android.dialer.calllog.datasources.CallLogMutations; 29 import com.android.dialer.common.Assert; 30 import com.android.dialer.common.LogUtil; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.Map.Entry; 34 import javax.inject.Inject; 35 36 /** Applies {@link CallLogMutations} to the annotated call log. */ 37 public class MutationApplier { 38 39 @Inject 40 MutationApplier() {} 41 42 /** Applies the provided {@link CallLogMutations} to the annotated call log. */ 43 @WorkerThread 44 public void applyToDatabase(CallLogMutations mutations, Context appContext) 45 throws RemoteException, OperationApplicationException { 46 Assert.isWorkerThread(); 47 48 if (mutations.isEmpty()) { 49 return; 50 } 51 52 ArrayList<ContentProviderOperation> operations = new ArrayList<>(); 53 54 if (!mutations.getInserts().isEmpty()) { 55 LogUtil.i( 56 "CallLogMutations.applyToDatabase", "inserting %d rows", mutations.getInserts().size()); 57 for (Entry<Long, ContentValues> entry : mutations.getInserts().entrySet()) { 58 long id = entry.getKey(); 59 ContentValues contentValues = entry.getValue(); 60 operations.add( 61 ContentProviderOperation.newInsert( 62 ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id)) 63 .withValues(contentValues) 64 .build()); 65 } 66 } 67 68 if (!mutations.getUpdates().isEmpty()) { 69 LogUtil.i( 70 "CallLogMutations.applyToDatabase", "updating %d rows", mutations.getUpdates().size()); 71 for (Entry<Long, ContentValues> entry : mutations.getUpdates().entrySet()) { 72 long id = entry.getKey(); 73 ContentValues contentValues = entry.getValue(); 74 operations.add( 75 ContentProviderOperation.newUpdate( 76 ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id)) 77 .withValues(contentValues) 78 .build()); 79 } 80 } 81 82 if (!mutations.getDeletes().isEmpty()) { 83 LogUtil.i( 84 "CallLogMutations.applyToDatabase", "deleting %d rows", mutations.getDeletes().size()); 85 String[] questionMarks = new String[mutations.getDeletes().size()]; 86 Arrays.fill(questionMarks, "?"); 87 88 String whereClause = 89 (AnnotatedCallLog._ID + " in (") + TextUtils.join(",", questionMarks) + ")"; 90 91 String[] whereArgs = new String[mutations.getDeletes().size()]; 92 int i = 0; 93 for (long id : mutations.getDeletes()) { 94 whereArgs[i++] = String.valueOf(id); 95 } 96 97 operations.add( 98 ContentProviderOperation.newDelete(AnnotatedCallLog.CONTENT_URI) 99 .withSelection(whereClause, whereArgs) 100 .build()); 101 } 102 103 appContext.getContentResolver().applyBatch(AnnotatedCallLogContract.AUTHORITY, operations); 104 } 105 } 106