1 /*
2  * Copyright (C) 2018 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.calllog.ui.menu;
18 
19 import android.Manifest.permission;
20 import android.content.Context;
21 import android.provider.CallLog;
22 import android.provider.CallLog.Calls;
23 import android.support.annotation.Nullable;
24 import android.support.annotation.RequiresPermission;
25 import com.android.dialer.CoalescedIds;
26 import com.android.dialer.common.Assert;
27 import com.android.dialer.common.LogUtil;
28 import com.android.dialer.common.concurrent.DialerExecutor.Worker;
29 import com.android.dialer.common.concurrent.DialerExecutorComponent;
30 import com.android.dialer.common.database.Selection;
31 import com.android.dialer.historyitemactions.HistoryItemActionModule;
32 import com.android.dialer.logging.DialerImpression;
33 import com.android.dialer.logging.Logger;
34 import java.lang.ref.WeakReference;
35 import java.util.ArrayList;
36 import java.util.List;
37 
38 /** {@link HistoryItemActionModule} for deleting a call log item in the new call log. */
39 final class DeleteCallLogItemModule implements HistoryItemActionModule {
40   private static final String TAG = DeleteCallLogItemModule.class.getName();
41 
42   private final Context context;
43   private final CoalescedIds coalescedIds;
44 
DeleteCallLogItemModule(Context context, CoalescedIds coalescedIds)45   DeleteCallLogItemModule(Context context, CoalescedIds coalescedIds) {
46     this.context = context;
47     this.coalescedIds = coalescedIds;
48   }
49 
50   @Override
getStringId()51   public int getStringId() {
52     return R.string.delete;
53   }
54 
55   @Override
getDrawableId()56   public int getDrawableId() {
57     return R.drawable.quantum_ic_delete_vd_theme_24;
58   }
59 
60   @Override
onClick()61   public boolean onClick() {
62     DialerExecutorComponent.get(context)
63         .dialerExecutorFactory()
64         .createNonUiTaskBuilder(new CallLogItemDeletionWorker(context))
65         .build()
66         .executeSerial(coalescedIds);
67 
68     Logger.get(context).logImpression(DialerImpression.Type.USER_DELETED_CALL_LOG_ITEM);
69     return true;
70   }
71 
72   /**
73    * A {@link Worker} that deletes a call log item.
74    *
75    * <p>It takes as input the IDs of all call log records that are coalesced into the item to be
76    * deleted.
77    */
78   private static class CallLogItemDeletionWorker implements Worker<CoalescedIds, Void> {
79     private final WeakReference<Context> contextWeakReference;
80 
CallLogItemDeletionWorker(Context context)81     CallLogItemDeletionWorker(Context context) {
82       contextWeakReference = new WeakReference<>(context);
83     }
84 
85     @Nullable
86     @Override
87     @RequiresPermission(value = permission.WRITE_CALL_LOG)
doInBackground(CoalescedIds coalescedIds)88     public Void doInBackground(CoalescedIds coalescedIds) throws Throwable {
89       Context context = contextWeakReference.get();
90       if (context == null) {
91         LogUtil.e(TAG, "Unable to delete an call log item due to null context.");
92         return null;
93       }
94 
95       Selection selection =
96           Selection.builder()
97               .and(Selection.column(CallLog.Calls._ID).in(getCallLogIdsAsStrings(coalescedIds)))
98               .build();
99       int numRowsDeleted =
100           context
101               .getContentResolver()
102               .delete(Calls.CONTENT_URI, selection.getSelection(), selection.getSelectionArgs());
103 
104       if (numRowsDeleted != coalescedIds.getCoalescedIdCount()) {
105         LogUtil.e(
106             TAG,
107             "Deleting call log item is unsuccessful. %d of %d rows are deleted.",
108             numRowsDeleted,
109             coalescedIds.getCoalescedIdCount());
110       }
111 
112       return null;
113     }
114 
getCallLogIdsAsStrings(CoalescedIds coalescedIds)115     private static List<String> getCallLogIdsAsStrings(CoalescedIds coalescedIds) {
116       Assert.checkArgument(coalescedIds.getCoalescedIdCount() > 0);
117 
118       List<String> idStrings = new ArrayList<>(coalescedIds.getCoalescedIdCount());
119 
120       for (long callLogId : coalescedIds.getCoalescedIdList()) {
121         idStrings.add(String.valueOf(callLogId));
122       }
123 
124       return idStrings;
125     }
126   }
127 }
128