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