VisualVoicemailUpdateTask.java revision 2f1c7586bcce334ca69022eb8dc6d8965ceb6a05
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
17package com.android.dialer.app.calllog;
18
19import android.content.Context;
20import android.support.annotation.NonNull;
21import android.support.annotation.Nullable;
22import android.support.annotation.WorkerThread;
23import android.text.TextUtils;
24import android.util.ArrayMap;
25import com.android.dialer.app.R;
26import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall;
27import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler;
28import com.android.dialer.blocking.FilteredNumbersUtil;
29import com.android.dialer.common.Assert;
30import com.android.dialer.common.LogUtil;
31import com.android.dialer.common.concurrent.DialerExecutor.Worker;
32import com.android.dialer.common.concurrent.DialerExecutors;
33import com.android.dialer.phonenumbercache.ContactInfo;
34import com.android.dialer.telecom.TelecomUtil;
35import java.util.ArrayList;
36import java.util.List;
37import java.util.Map;
38
39/** Updates voicemail notifications in the background. */
40class VisualVoicemailUpdateTask implements Worker<VisualVoicemailUpdateTask.Input, Void> {
41  @Nullable
42  @Override
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
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
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. */
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
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