1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/*
2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2017 The Android Open Source Project
3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License");
5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License.
6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at
7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *      http://www.apache.org/licenses/LICENSE-2.0
9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software
11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS,
12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and
14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License
15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */
16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.incallui;
18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.annotation.TargetApi;
20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.Notification;
21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.NotificationManager;
22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.app.PendingIntent;
23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context;
24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Intent;
25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.graphics.Bitmap;
26ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.graphics.BitmapFactory;
27ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.graphics.drawable.BitmapDrawable;
28ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.net.Uri;
29ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Build.VERSION_CODES;
30ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.NonNull;
31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.Nullable;
32ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.Call;
33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.PhoneAccount;
34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.VideoProfile;
35ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.BidiFormatter;
36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.TextDirectionHeuristics;
37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.text.TextUtils;
38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.util.ArrayMap;
39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.ContactsUtils;
40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.compat.CallCompat;
41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.preference.ContactsPreferences;
42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.util.BitmapUtil;
43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.util.ContactDisplayUtils;
44d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport com.android.dialer.notification.NotificationChannelManager;
45d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanianimport com.android.dialer.notification.NotificationChannelManager.Channel;
46ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.DialerCall;
47ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.DialerCallDelegate;
48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.call.ExternalCallList;
49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.latencyreport.LatencyReport;
50ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.util.TelecomCallUtil;
51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Map;
52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/**
54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Handles the display of notifications for "external calls".
55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * <p>External calls are a representation of a call which is in progress on the user's other device
57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * (e.g. another phone, or a watch).
58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */
59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic class ExternalCallNotifier implements ExternalCallList.ExternalCallListener {
60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Tag used with the notification manager to uniquely identify external call notifications. */
62d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  private static final int NOTIFICATION_ID = R.id.notification_external_call;
63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
64d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  private static final String NOTIFICATION_GROUP = "ExternalCallNotifier";
65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final Context mContext;
66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private final ContactInfoCache mContactInfoCache;
67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private Map<Call, NotificationInfo> mNotifications = new ArrayMap<>();
68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private int mNextUniqueNotificationId;
69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private ContactsPreferences mContactsPreferences;
70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private boolean mShowingSummary;
71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Initializes a new instance of the external call notifier. */
73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public ExternalCallNotifier(
74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      @NonNull Context context, @NonNull ContactInfoCache contactInfoCache) {
75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mContext = context;
76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mContactsPreferences = ContactsPreferencesFactory.newContactsPreferences(mContext);
77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mContactInfoCache = contactInfoCache;
78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Handles the addition of a new external call by showing a new notification. Triggered by {@link
82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * CallList#onCallAdded(android.telecom.Call)}.
83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onExternalCallAdded(android.telecom.Call call) {
86ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Log.i(this, "onExternalCallAdded " + call);
87ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (mNotifications.containsKey(call)) {
88ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      throw new IllegalArgumentException();
89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    NotificationInfo info = new NotificationInfo(call, mNextUniqueNotificationId++);
91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mNotifications.put(call, info);
92ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
93ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    showNotifcation(info);
94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
95ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
96ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
97ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Handles the removal of an external call by hiding its associated notification. Triggered by
98ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * {@link CallList#onCallRemoved(android.telecom.Call)}.
99ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
100ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
101ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onExternalCallRemoved(android.telecom.Call call) {
102ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Log.i(this, "onExternalCallRemoved " + call);
103ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
104ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    dismissNotification(call);
105ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
106ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
107ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Handles updates to an external call. */
108ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
109ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onExternalCallUpdated(Call call) {
110ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (!mNotifications.containsKey(call)) {
111ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      throw new IllegalArgumentException();
112ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
113ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    postNotification(mNotifications.get(call));
114ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
115ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
116ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
117ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onExternalCallPulled(Call call) {
118ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // no-op; if an external call is pulled, it will be removed via onExternalCallRemoved.
119ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
120ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
121ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
122ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Initiates a call pull given a notification ID.
123ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
124ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param notificationId The notification ID associated with the external call which is to be
125ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *     pulled.
126ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
127ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @TargetApi(VERSION_CODES.N_MR1)
128ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void pullExternalCall(int notificationId) {
129ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    for (NotificationInfo info : mNotifications.values()) {
130ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (info.getNotificationId() == notificationId
131ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          && CallCompat.canPullExternalCall(info.getCall())) {
132ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        info.getCall().pullExternalCall();
133ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        return;
134ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
135ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
136ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
137ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
138ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
139ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Shows a notification for a new external call. Performs a contact cache lookup to find any
140ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * associated photo and information for the call.
141ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
142ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void showNotifcation(final NotificationInfo info) {
143ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // We make a call to the contact info cache to query for supplemental data to what the
144ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // call provides.  This includes the contact name and photo.
145ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // This callback will always get called immediately and synchronously with whatever data
146ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // it has available, and may make a subsequent call later (same thread) if it had to
147ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // call into the contacts provider for more data.
148ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    DialerCall dialerCall =
149ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new DialerCall(
150ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            mContext,
151ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            new DialerCallDelegateStub(),
152ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            info.getCall(),
153ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            new LatencyReport(),
154ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            false /* registerCallback */);
155ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
156ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mContactInfoCache.findInfo(
157ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        dialerCall,
158ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        false /* isIncoming */,
159ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new ContactInfoCache.ContactInfoCacheCallback() {
160ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          @Override
161ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          public void onContactInfoComplete(
162ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              String callId, ContactInfoCache.ContactCacheEntry entry) {
163ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
164ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            // Ensure notification still exists as the external call could have been
165ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            // removed during async contact info lookup.
166ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            if (mNotifications.containsKey(info.getCall())) {
167ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              saveContactInfo(info, entry);
168ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            }
169ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          }
170ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
171ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          @Override
172ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          public void onImageLoadComplete(String callId, ContactInfoCache.ContactCacheEntry entry) {
173ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
174ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            // Ensure notification still exists as the external call could have been
175ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            // removed during async contact info lookup.
176ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            if (mNotifications.containsKey(info.getCall())) {
177ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              savePhoto(info, entry);
178ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            }
179ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          }
180ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        });
181ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
182ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
183ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Dismisses a notification for an external call. */
184ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void dismissNotification(Call call) {
185ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (!mNotifications.containsKey(call)) {
186ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      throw new IllegalArgumentException();
187ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
188ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
189ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    NotificationManager notificationManager =
190ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
191d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    notificationManager.cancel(
192d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        String.valueOf(mNotifications.get(call).getNotificationId()), NOTIFICATION_ID);
193ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
194ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    mNotifications.remove(call);
195ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
196ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (mShowingSummary && mNotifications.size() <= 1) {
197ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Where a summary notification is showing and there is now not enough notifications to
198ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // necessitate a summary, cancel the summary.
199d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      notificationManager.cancel(NOTIFICATION_GROUP, NOTIFICATION_ID);
200ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mShowingSummary = false;
201ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
202ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // If there is still a single call requiring a notification, re-post the notification as a
203ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // standalone notification without a summary notification.
204ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (mNotifications.size() == 1) {
205ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        postNotification(mNotifications.values().iterator().next());
206ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
207ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
208ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
209ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
210ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
211ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Attempts to build a large icon to use for the notification based on the contact info and post
212ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * the updated notification to the notification manager.
213ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
214ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void savePhoto(NotificationInfo info, ContactInfoCache.ContactCacheEntry entry) {
215ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Bitmap largeIcon = getLargeIconToDisplay(mContext, entry, info.getCall());
216ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (largeIcon != null) {
217ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      largeIcon = getRoundedIcon(mContext, largeIcon);
218ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
219ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    info.setLargeIcon(largeIcon);
220ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    postNotification(info);
221ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
222ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
223ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
224ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Builds and stores the contact information the notification will display and posts the updated
225ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * notification to the notification manager.
226ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
227ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void saveContactInfo(NotificationInfo info, ContactInfoCache.ContactCacheEntry entry) {
228ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    info.setContentTitle(getContentTitle(mContext, mContactsPreferences, entry, info.getCall()));
229ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    info.setPersonReference(getPersonReference(entry, info.getCall()));
230ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    postNotification(info);
231ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
232ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
233ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Rebuild an existing or show a new notification given {@link NotificationInfo}. */
234ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private void postNotification(NotificationInfo info) {
235ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Notification.Builder builder = new Notification.Builder(mContext);
236ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Set notification as ongoing since calls are long-running versus a point-in-time notice.
237ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setOngoing(true);
238ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Make the notification prioritized over the other normal notifications.
239ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setPriority(Notification.PRIORITY_HIGH);
240d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    builder.setGroup(NOTIFICATION_GROUP);
241ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
242ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    boolean isVideoCall = VideoProfile.isVideo(info.getCall().getDetails().getVideoState());
243ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Set the content ("Ongoing call on another device")
244ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setContentText(
245ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        mContext.getString(
246ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            isVideoCall
247ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                ? R.string.notification_external_video_call
248ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                : R.string.notification_external_call));
249ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setSmallIcon(R.drawable.quantum_ic_call_white_24);
250ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setContentTitle(info.getContentTitle());
251ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setLargeIcon(info.getLargeIcon());
252ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setColor(mContext.getResources().getColor(R.color.dialer_theme_color));
253ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.addPerson(info.getPersonReference());
254ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
255d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    NotificationChannelManager.applyChannel(
256d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        builder, mContext, Channel.EXTERNAL_CALL, info.getCall().getDetails().getAccountHandle());
257d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
258ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Where the external call supports being transferred to the local device, add an action
259ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // to the notification to initiate the call pull process.
260ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (CallCompat.canPullExternalCall(info.getCall())) {
261ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
262ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      Intent intent =
263ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          new Intent(
264ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              NotificationBroadcastReceiver.ACTION_PULL_EXTERNAL_CALL,
265ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              null,
266ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              mContext,
267ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              NotificationBroadcastReceiver.class);
268ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      intent.putExtra(
269ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          NotificationBroadcastReceiver.EXTRA_NOTIFICATION_ID, info.getNotificationId());
270ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      builder.addAction(
271ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          new Notification.Action.Builder(
272ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                  R.drawable.quantum_ic_call_white_24,
273ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                  mContext.getString(
274ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                      isVideoCall
275ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                          ? R.string.notification_take_video_call
276ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                          : R.string.notification_take_call),
277ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian                  PendingIntent.getBroadcast(mContext, info.getNotificationId(), intent, 0))
278ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              .build());
279ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
280ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
281ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    /**
282ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian     * This builder is used for the notification shown when the device is locked and the user has
283ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian     * set their notification settings to 'hide sensitive content' {@see
284ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian     * Notification.Builder#setPublicVersion}.
285ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian     */
286ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Notification.Builder publicBuilder = new Notification.Builder(mContext);
287ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    publicBuilder.setSmallIcon(R.drawable.quantum_ic_call_white_24);
288ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    publicBuilder.setColor(mContext.getResources().getColor(R.color.dialer_theme_color));
289ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
290d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    NotificationChannelManager.applyChannel(
291d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        publicBuilder,
292d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        mContext,
293d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        Channel.EXTERNAL_CALL,
294d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        info.getCall().getDetails().getAccountHandle());
295d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
296ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    builder.setPublicVersion(publicBuilder.build());
297ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Notification notification = builder.build();
298ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
299ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    NotificationManager notificationManager =
300ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
301d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    notificationManager.notify(
302d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian        String.valueOf(info.getNotificationId()), NOTIFICATION_ID, notification);
303ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
304ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (!mShowingSummary && mNotifications.size() > 1) {
305ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // If the number of notifications shown is > 1, and we're not already showing a group summary,
306ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // build one now.  This will ensure the like notifications are grouped together.
307ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
308ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      Notification.Builder summary = new Notification.Builder(mContext);
309ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Set notification as ongoing since calls are long-running versus a point-in-time notice.
310ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      summary.setOngoing(true);
311ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Make the notification prioritized over the other normal notifications.
312ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      summary.setPriority(Notification.PRIORITY_HIGH);
313d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      summary.setGroup(NOTIFICATION_GROUP);
314ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      summary.setGroupSummary(true);
315ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      summary.setSmallIcon(R.drawable.quantum_ic_call_white_24);
316d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      NotificationChannelManager.applyChannel(
317d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          summary, mContext, Channel.EXTERNAL_CALL, info.getCall().getDetails().getAccountHandle());
318d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      notificationManager.notify(NOTIFICATION_GROUP, NOTIFICATION_ID, summary.build());
319ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mShowingSummary = true;
320ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
321ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
322ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
323ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
324ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Finds a large icon to display in a notification for a call. For conference calls, a conference
325ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * call icon is used, otherwise if contact info is specified, the user's contact photo or avatar
326ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * is used.
327ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
328ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param context The context.
329ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param contactInfo The contact cache info.
330ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param call The call.
331ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @return The large icon to use for the notification.
332ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
333ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private @Nullable Bitmap getLargeIconToDisplay(
334ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      Context context, ContactInfoCache.ContactCacheEntry contactInfo, android.telecom.Call call) {
335ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
336ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Bitmap largeIcon = null;
337ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call.getDetails().hasProperty(android.telecom.Call.Details.PROPERTY_CONFERENCE)
338ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        && !call.getDetails()
339ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            .hasProperty(android.telecom.Call.Details.PROPERTY_GENERIC_CONFERENCE)) {
340ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
34183b20211c3be04a850de3674977deee8e448d17fEric Erfanian      largeIcon =
34283b20211c3be04a850de3674977deee8e448d17fEric Erfanian          BitmapFactory.decodeResource(
34383b20211c3be04a850de3674977deee8e448d17fEric Erfanian              context.getResources(), R.drawable.quantum_ic_group_vd_theme_24);
344ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
345ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (contactInfo.photo != null && (contactInfo.photo instanceof BitmapDrawable)) {
346ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      largeIcon = ((BitmapDrawable) contactInfo.photo).getBitmap();
347ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
348ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return largeIcon;
349ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
350ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
351ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
352ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Given a bitmap, returns a rounded version of the icon suitable for display in a notification.
353ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
354ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param context The context.
355ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param bitmap The bitmap to round.
356ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @return The rounded bitmap.
357ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
358ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private @Nullable Bitmap getRoundedIcon(Context context, @Nullable Bitmap bitmap) {
359ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (bitmap == null) {
360ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return null;
361ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
362ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final int height =
363ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (int) context.getResources().getDimension(android.R.dimen.notification_large_icon_height);
364ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    final int width =
365ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        (int) context.getResources().getDimension(android.R.dimen.notification_large_icon_width);
366ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return BitmapUtil.getRoundedBitmap(bitmap, width, height);
367ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
368ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
369ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
370ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Builds a notification content title for a call. If the call is a conference call, it is
371ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * identified as such. Otherwise an attempt is made to show an associated contact name or phone
372ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * number.
373ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
374ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param context The context.
375ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param contactsPreferences Contacts preferences, used to determine the preferred formatting for
376ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *     contact names.
377ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param contactInfo The contact info which was looked up in the contact cache.
378ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param call The call to generate a title for.
379ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @return The content title.
380ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
381ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private @Nullable String getContentTitle(
382ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      Context context,
383ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      @Nullable ContactsPreferences contactsPreferences,
384ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      ContactInfoCache.ContactCacheEntry contactInfo,
385ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      android.telecom.Call call) {
386ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
387ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (call.getDetails().hasProperty(android.telecom.Call.Details.PROPERTY_CONFERENCE)
388ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        && !call.getDetails()
389ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            .hasProperty(android.telecom.Call.Details.PROPERTY_GENERIC_CONFERENCE)) {
390ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
391ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return context.getResources().getString(R.string.conference_call_name);
392ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
393ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
394ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    String preferredName =
395ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        ContactDisplayUtils.getPreferredDisplayName(
396ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            contactInfo.namePrimary, contactInfo.nameAlternative, contactsPreferences);
397ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (TextUtils.isEmpty(preferredName)) {
398ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return TextUtils.isEmpty(contactInfo.number)
399ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          ? null
400ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          : BidiFormatter.getInstance()
401ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              .unicodeWrap(contactInfo.number, TextDirectionHeuristics.LTR);
402ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
403ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return preferredName;
404ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
405ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
406ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /**
407ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * Gets a "person reference" for a notification, used by the system to determine whether the
408ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * notification should be allowed past notification interruption filters.
409ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   *
410ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param contactInfo The contact info from cache.
411ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @param call The call.
412ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   * @return the person reference.
413ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian   */
414ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private String getPersonReference(ContactInfoCache.ContactCacheEntry contactInfo, Call call) {
415ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
416ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    String number = TelecomCallUtil.getNumber(call);
417ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Query {@link Contacts#CONTENT_LOOKUP_URI} directly with work lookup key is not allowed.
418ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // So, do not pass {@link Contacts#CONTENT_LOOKUP_URI} to NotificationManager to avoid
419ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // NotificationManager using it.
420ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (contactInfo.lookupUri != null && contactInfo.userType != ContactsUtils.USER_TYPE_WORK) {
421ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return contactInfo.lookupUri.toString();
422ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else if (!TextUtils.isEmpty(number)) {
423ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null).toString();
424ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
425ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return "";
426ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
427ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
428ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static class DialerCallDelegateStub implements DialerCallDelegate {
429ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
430ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Override
431ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public DialerCall getDialerCallFromTelecomCall(Call telecomCall) {
432ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return null;
433ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
434ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
435ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
436ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  /** Represents a call and associated cached notification data. */
437ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static class NotificationInfo {
438ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
439ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @NonNull private final Call mCall;
440ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    private final int mNotificationId;
441ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Nullable private String mContentTitle;
442ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Nullable private Bitmap mLargeIcon;
443ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    @Nullable private String mPersonReference;
444ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
445ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public NotificationInfo(@NonNull Call call, int notificationId) {
446ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mCall = call;
447ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mNotificationId = notificationId;
448ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
449ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
450ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public Call getCall() {
451ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return mCall;
452ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
453ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
454ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public int getNotificationId() {
455ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return mNotificationId;
456ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
457ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
458ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public @Nullable String getContentTitle() {
459ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return mContentTitle;
460ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
461ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
462ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void setContentTitle(@Nullable String contentTitle) {
463ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mContentTitle = contentTitle;
464ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
465ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
466ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public @Nullable Bitmap getLargeIcon() {
467ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return mLargeIcon;
468ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
469ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
470ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void setLargeIcon(@Nullable Bitmap largeIcon) {
471ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mLargeIcon = largeIcon;
472ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
473ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
474ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public @Nullable String getPersonReference() {
475ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return mPersonReference;
476ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
477ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
478ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    public void setPersonReference(@Nullable String personReference) {
479ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      mPersonReference = personReference;
480ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
481ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
482ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian}
483