• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.dialer.app.calllog;
18 
19 import android.content.Context;
20 import android.support.annotation.NonNull;
21 import android.support.annotation.Nullable;
22 import android.support.annotation.WorkerThread;
23 import android.text.TextUtils;
24 import android.util.ArrayMap;
25 import com.android.dialer.app.R;
26 import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall;
27 import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler;
28 import com.android.dialer.blocking.FilteredNumbersUtil;
29 import com.android.dialer.common.Assert;
30 import com.android.dialer.common.LogUtil;
31 import com.android.dialer.common.concurrent.DialerExecutor.Worker;
32 import com.android.dialer.common.concurrent.DialerExecutors;
33 import com.android.dialer.phonenumbercache.ContactInfo;
34 import com.android.dialer.telecom.TelecomUtil;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Map;
38 
39 /** Updates voicemail notifications in the background. */
40 class VisualVoicemailUpdateTask implements Worker<VisualVoicemailUpdateTask.Input, Void> {
41   @Nullable
42   @Override
doInBackground(@onNull Input input)43   public Void doInBackground(@NonNull Input input) throws Throwable {
44     updateNotification(input.context, input.queryHelper, input.queryHandler);
45     return null;
46   }
47 
48   /**
49    * Updates the notification and notifies of the call with the given URI.
50    *
51    * <p>Clears the notification if there are no new voicemails, and notifies if the given URI
52    * corresponds to a new voicemail.
53    */
54   @WorkerThread
updateNotification( Context context, CallLogNotificationsQueryHelper queryHelper, FilteredNumberAsyncQueryHandler queryHandler)55   private static void updateNotification(
56       Context context,
57       CallLogNotificationsQueryHelper queryHelper,
58       FilteredNumberAsyncQueryHandler queryHandler) {
59     Assert.isWorkerThread();
60 
61     List<NewCall> newCalls = queryHelper.getNewVoicemails();
62     if (newCalls == null) {
63       return;
64     }
65     newCalls = filterBlockedNumbers(context, queryHandler, newCalls);
66     if (newCalls.isEmpty()) {
67       return;
68     }
69 
70     // This represents a list of names to include in the notification.
71     String callers = null;
72 
73     // Maps each number into a name: if a number is in the map, it has already left a more
74     // recent voicemail.
75     Map<String, ContactInfo> contactInfos = new ArrayMap<>();
76     for (NewCall newCall : newCalls) {
77       if (!contactInfos.containsKey(newCall.number)) {
78         ContactInfo contactInfo =
79             queryHelper.getContactInfo(
80                 newCall.number, newCall.numberPresentation, newCall.countryIso);
81         contactInfos.put(newCall.number, contactInfo);
82 
83         // This is a new caller. Add it to the back of the list of callers.
84         if (TextUtils.isEmpty(callers)) {
85           callers = contactInfo.name;
86         } else {
87           callers =
88               context.getString(
89                   R.string.notification_voicemail_callers_list, callers, contactInfo.name);
90         }
91       }
92     }
93     VisualVoicemailNotifier.showNotifications(context, newCalls, contactInfos, callers);
94   }
95 
96   @WorkerThread
filterBlockedNumbers( Context context, FilteredNumberAsyncQueryHandler queryHandler, List<NewCall> newCalls)97   private static List<NewCall> filterBlockedNumbers(
98       Context context, FilteredNumberAsyncQueryHandler queryHandler, List<NewCall> newCalls) {
99     Assert.isWorkerThread();
100     if (FilteredNumbersUtil.hasRecentEmergencyCall(context)) {
101       LogUtil.i(
102           "VisualVoicemailUpdateTask.filterBlockedNumbers",
103           "not filtering due to recent emergency call");
104       return newCalls;
105     }
106 
107     List<NewCall> result = new ArrayList<>();
108     for (NewCall newCall : newCalls) {
109       if (queryHandler.getBlockedIdSynchronous(newCall.number, newCall.countryIso) != null) {
110         LogUtil.i(
111             "VisualVoicemailUpdateTask.filterBlockedNumbers",
112             "found voicemail from blocked number, deleting");
113         if (newCall.voicemailUri != null) {
114           // Delete the voicemail.
115           CallLogAsyncTaskUtil.deleteVoicemailSynchronous(context, newCall.voicemailUri);
116         }
117       } else {
118         result.add(newCall);
119       }
120     }
121     return result;
122   }
123 
124   /** Updates the voicemail notifications displayed. */
scheduleTask(@onNull Context context, @NonNull Runnable callback)125   static void scheduleTask(@NonNull Context context, @NonNull Runnable callback) {
126     Assert.isNotNull(context);
127     Assert.isNotNull(callback);
128     if (!TelecomUtil.isDefaultDialer(context)) {
129       LogUtil.i("VisualVoicemailUpdateTask.scheduleTask", "not default dialer, not running");
130       callback.run();
131       return;
132     }
133 
134     Input input =
135         new Input(
136             context,
137             CallLogNotificationsQueryHelper.getInstance(context),
138             new FilteredNumberAsyncQueryHandler(context));
139     DialerExecutors.createNonUiTaskBuilder(new VisualVoicemailUpdateTask())
140         .onSuccess(
141             output -> {
142               LogUtil.i("VisualVoicemailUpdateTask.scheduleTask", "update successful");
143               callback.run();
144             })
145         .onFailure(
146             throwable -> {
147               LogUtil.i("VisualVoicemailUpdateTask.scheduleTask", "update failed: " + throwable);
148               callback.run();
149             })
150         .build()
151         .executeParallel(input);
152   }
153 
154   static class Input {
155     @NonNull final Context context;
156     @NonNull final CallLogNotificationsQueryHelper queryHelper;
157     @NonNull final FilteredNumberAsyncQueryHandler queryHandler;
158 
Input( Context context, CallLogNotificationsQueryHelper queryHelper, FilteredNumberAsyncQueryHandler queryHandler)159     Input(
160         Context context,
161         CallLogNotificationsQueryHelper queryHelper,
162         FilteredNumberAsyncQueryHandler queryHandler) {
163       this.context = context;
164       this.queryHelper = queryHelper;
165       this.queryHandler = queryHandler;
166     }
167   }
168 }
169