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