12f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian/* 22f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * Copyright (C) 2017 The Android Open Source Project 32f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * 42f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License"); 52f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * you may not use this file except in compliance with the License. 62f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * You may obtain a copy of the License at 72f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * 82f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * http://www.apache.org/licenses/LICENSE-2.0 92f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * 102f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * Unless required by applicable law or agreed to in writing, software 112f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS, 122f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * See the License for the specific language governing permissions and 142f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian * limitations under the License 152f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian */ 162f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianpackage com.android.dialer.calllog.database; 172f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 182f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.ContentProviderOperation; 192f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.ContentUris; 202f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.ContentValues; 212f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.Context; 222f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.content.OperationApplicationException; 232f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.os.RemoteException; 242f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.support.annotation.WorkerThread; 252f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport android.text.TextUtils; 262f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.calllog.database.contract.AnnotatedCallLogContract; 272f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; 282f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.calllog.datasources.CallLogMutations; 292f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.common.Assert; 302f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport com.android.dialer.common.LogUtil; 312f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport java.util.ArrayList; 322f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport java.util.Arrays; 332f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport java.util.Map.Entry; 342f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianimport javax.inject.Inject; 352f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 362f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian/** Applies {@link CallLogMutations} to the annotated call log. */ 372f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanianpublic class MutationApplier { 382f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 392f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian @Inject 402f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian MutationApplier() {} 412f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 422f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian /** Applies the provided {@link CallLogMutations} to the annotated call log. */ 432f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian @WorkerThread 442f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian public void applyToDatabase(CallLogMutations mutations, Context appContext) 452f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian throws RemoteException, OperationApplicationException { 462f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian Assert.isWorkerThread(); 472f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 482f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian if (mutations.isEmpty()) { 492f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian return; 502f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 512f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 522f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian ArrayList<ContentProviderOperation> operations = new ArrayList<>(); 532f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 542f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian if (!mutations.getInserts().isEmpty()) { 552f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian LogUtil.i( 562f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian "CallLogMutations.applyToDatabase", "inserting %d rows", mutations.getInserts().size()); 572f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian for (Entry<Long, ContentValues> entry : mutations.getInserts().entrySet()) { 582f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian long id = entry.getKey(); 592f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian ContentValues contentValues = entry.getValue(); 602f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian operations.add( 612f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian ContentProviderOperation.newInsert( 622f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id)) 632f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .withValues(contentValues) 642f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .build()); 652f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 662f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 672f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 682f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian if (!mutations.getUpdates().isEmpty()) { 692f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian LogUtil.i( 702f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian "CallLogMutations.applyToDatabase", "updating %d rows", mutations.getUpdates().size()); 712f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian for (Entry<Long, ContentValues> entry : mutations.getUpdates().entrySet()) { 722f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian long id = entry.getKey(); 732f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian ContentValues contentValues = entry.getValue(); 742f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian operations.add( 752f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian ContentProviderOperation.newUpdate( 762f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id)) 772f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .withValues(contentValues) 782f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .build()); 792f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 802f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 812f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 822f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian if (!mutations.getDeletes().isEmpty()) { 832f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian LogUtil.i( 842f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian "CallLogMutations.applyToDatabase", "deleting %d rows", mutations.getDeletes().size()); 852f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian String[] questionMarks = new String[mutations.getDeletes().size()]; 862f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian Arrays.fill(questionMarks, "?"); 872f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 882f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian String whereClause = 892f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian (AnnotatedCallLog._ID + " in (") + TextUtils.join(",", questionMarks) + ")"; 902f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 912f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian String[] whereArgs = new String[mutations.getDeletes().size()]; 922f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian int i = 0; 932f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian for (long id : mutations.getDeletes()) { 942f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian whereArgs[i++] = String.valueOf(id); 952f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 962f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 972f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian operations.add( 982f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian ContentProviderOperation.newDelete(AnnotatedCallLog.CONTENT_URI) 992f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .withSelection(whereClause, whereArgs) 1002f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian .build()); 1012f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 1022f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian 1032f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian appContext.getContentResolver().applyBatch(AnnotatedCallLogContract.AUTHORITY, operations); 1042f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian } 1052f1c7586bcce334ca69022eb8dc6d8965ceb6a05Eric Erfanian} 106