MissedCallNotifierImpl.java revision 3037ac6f171b6a3627494bb10042ab7adb34366a
18de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad/* 28de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Copyright 2014, The Android Open Source Project 38de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 48de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Licensed under the Apache License, Version 2.0 (the "License"); 58de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * you may not use this file except in compliance with the License. 68de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * You may obtain a copy of the License at 78de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 88de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * http://www.apache.org/licenses/LICENSE-2.0 98de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Unless required by applicable law or agreed to in writing, software 118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * distributed under the License is distributed on an "AS IS" BASIS, 128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * See the License for the specific language governing permissions and 148de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * limitations under the License. 158de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 168de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 178de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadpackage com.android.server.telecom.ui; 188de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepalimport static android.Manifest.permission.READ_PHONE_STATE; 2039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 213037ac6f171b6a3627494bb10042ab7adb34366aHall Liuimport android.annotation.NonNull; 2241045b499a47c00459986c96bbbb28ffee2cbefcBryce Leeimport android.content.ComponentName; 23a993094840386163e9c2aa65a05e14b49d122318Tony Makimport android.content.ContentProvider; 24a993094840386163e9c2aa65a05e14b49d122318Tony Makimport android.content.pm.PackageManager.NameNotFoundException; 25a993094840386163e9c2aa65a05e14b49d122318Tony Makimport android.telecom.PhoneAccountHandle; 2641045b499a47c00459986c96bbbb28ffee2cbefcBryce Leeimport android.telecom.TelecomManager; 27a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 283037ac6f171b6a3627494bb10042ab7adb34366aHall Liuimport com.android.server.telecom.CallerInfoLookupHelper; 298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.CallsManagerListenerBase; 308de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.Constants; 318de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.Log; 328d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadimport com.android.server.telecom.MissedCallNotifier; 33a993094840386163e9c2aa65a05e14b49d122318Tony Makimport com.android.server.telecom.PhoneAccountRegistrar; 348de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.R; 35e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebingerimport com.android.server.telecom.Runnable; 368de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.TelecomBroadcastIntentProcessor; 378d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadimport com.android.server.telecom.TelecomSystem; 38226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Leeimport com.android.server.telecom.components.TelecomBroadcastReceiver; 398de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 408de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.app.Notification; 418de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.app.NotificationManager; 428de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.app.PendingIntent; 438de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.app.TaskStackBuilder; 448de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.content.AsyncQueryHandler; 458de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.content.ContentValues; 468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.content.Context; 478de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.content.Intent; 4839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepalimport android.content.pm.ResolveInfo; 498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.database.Cursor; 508de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.graphics.Bitmap; 518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.graphics.drawable.BitmapDrawable; 528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.graphics.drawable.Drawable; 538de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.net.Uri; 548de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.os.AsyncTask; 55761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Leeimport android.os.Binder; 568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.os.UserHandle; 578de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.provider.CallLog.Calls; 5839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepalimport android.telecom.DefaultDialerManager; 598de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.telecom.PhoneAccount; 608de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.telephony.PhoneNumberUtils; 61c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunnimport android.telephony.TelephonyManager; 628de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.text.BidiFormatter; 638de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.text.TextDirectionHeuristics; 648de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.text.TextUtils; 658de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 669e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Changimport com.android.internal.telephony.CallerInfo; 679e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang 6841045b499a47c00459986c96bbbb28ffee2cbefcBryce Leeimport java.lang.Override; 6941045b499a47c00459986c96bbbb28ffee2cbefcBryce Leeimport java.lang.String; 7039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepalimport java.util.List; 71c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunnimport java.util.Locale; 723037ac6f171b6a3627494bb10042ab7adb34366aHall Liuimport java.util.Objects; 733037ac6f171b6a3627494bb10042ab7adb34366aHall Liuimport java.util.Set; 74a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.ConcurrentHashMap; 75a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.ConcurrentMap; 76a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.atomic.AtomicInteger; 7741045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad// TODO: Needed for move to system service: import com.android.internal.R; 798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad/** 818de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates a notification for calls that the user missed (neither answered nor rejected). 828de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 838de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * TODO: Make TelephonyManager.clearMissedCalls call into this class. 848de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 858d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadpublic class MissedCallNotifierImpl extends CallsManagerListenerBase implements MissedCallNotifier { 868de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 87a993094840386163e9c2aa65a05e14b49d122318Tony Mak public interface MissedCallNotifierImplFactory { 88a993094840386163e9c2aa65a05e14b49d122318Tony Mak MissedCallNotifier makeMissedCallNotifierImpl(Context context, 893037ac6f171b6a3627494bb10042ab7adb34366aHall Liu PhoneAccountRegistrar phoneAccountRegistrar); 90a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 91a993094840386163e9c2aa65a05e14b49d122318Tony Mak 92a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public interface NotificationBuilderFactory { 93a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu Notification.Builder getBuilder(Context context); 94a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 95a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 96a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu private static class DefaultNotificationBuilderFactory implements NotificationBuilderFactory { 97a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public DefaultNotificationBuilderFactory() {} 98a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 99a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu @Override 100a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public Notification.Builder getBuilder(Context context) { 101a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu return new Notification.Builder(context); 102a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 103a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 104a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 1058de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private static final String[] CALL_LOG_PROJECTION = new String[] { 1068de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls._ID, 1078de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.NUMBER, 1088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.NUMBER_PRESENTATION, 1098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.DATE, 1108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.DURATION, 1118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.TYPE, 1128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad }; 1138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1143037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private static final String CALL_LOG_WHERE_CLAUSE = "type=" + Calls.MISSED_TYPE + 1153037ac6f171b6a3627494bb10042ab7adb34366aHall Liu " AND new=1" + 1163037ac6f171b6a3627494bb10042ab7adb34366aHall Liu " AND is_read=0"; 1173037ac6f171b6a3627494bb10042ab7adb34366aHall Liu 1183037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_ID = 0; 1193037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_NUMBER = 1; 1203037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_NUMBER_PRESENTATION = 2; 1213037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_DATE = 3; 1223037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_DURATION = 4; 1233037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_TYPE = 5; 1248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private static final int MISSED_CALL_NOTIFICATION_ID = 1; 1268de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1278de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private final Context mContext; 128a993094840386163e9c2aa65a05e14b49d122318Tony Mak private final PhoneAccountRegistrar mPhoneAccountRegistrar; 1298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private final NotificationManager mNotificationManager; 130a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu private final NotificationBuilderFactory mNotificationBuilderFactory; 13141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee private final ComponentName mNotificationComponent; 132a993094840386163e9c2aa65a05e14b49d122318Tony Mak private UserHandle mCurrentUserHandle; 13341045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 1348de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Used to track the number of missed calls. 135a993094840386163e9c2aa65a05e14b49d122318Tony Mak private ConcurrentMap<UserHandle, AtomicInteger> mMissedCallCounts; 1368de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1373037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private UserHandle userToLoadAfterBootComplete; 1383037ac6f171b6a3627494bb10042ab7adb34366aHall Liu 1393037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public MissedCallNotifierImpl(Context context, PhoneAccountRegistrar phoneAccountRegistrar) { 1403037ac6f171b6a3627494bb10042ab7adb34366aHall Liu this(context, phoneAccountRegistrar, new DefaultNotificationBuilderFactory()); 141a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 142a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 143a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public MissedCallNotifierImpl(Context context, 144a993094840386163e9c2aa65a05e14b49d122318Tony Mak PhoneAccountRegistrar phoneAccountRegistrar, 145a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu NotificationBuilderFactory notificationBuilderFactory) { 1468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mContext = context; 147a993094840386163e9c2aa65a05e14b49d122318Tony Mak mPhoneAccountRegistrar = phoneAccountRegistrar; 1488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mNotificationManager = 1498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 15041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee final String notificationComponent = context.getString(R.string.notification_component); 15141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 152a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu mNotificationBuilderFactory = notificationBuilderFactory; 15341045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee mNotificationComponent = notificationComponent != null 15441045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee ? ComponentName.unflattenFromString(notificationComponent) : null; 155a993094840386163e9c2aa65a05e14b49d122318Tony Mak mMissedCallCounts = new ConcurrentHashMap<>(); 1568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 1578de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1588de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** Clears missed call notification and marks the call log's missed calls as read. */ 159226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee @Override 16039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal public void clearMissedCalls(UserHandle userHandle) { 16139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal // If the default dialer is showing the missed call notification then it will modify the 16239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal // call log and we don't have to do anything here. 16339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (!shouldManageNotificationThroughDefaultDialer(userHandle)) { 16439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal markMissedCallsAsRead(userHandle); 16539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 16639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal cancelMissedCallNotification(userHandle); 16739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 16839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 16939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private void markMissedCallsAsRead(final UserHandle userHandle) { 170f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger AsyncTask.execute(new Runnable("MCNI.mMCAR", null /*lock*/) { 1718de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad @Override 172e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger public void loggedRun() { 1738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Clear the list of new missed calls from the call log. 1748de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad ContentValues values = new ContentValues(); 1758de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad values.put(Calls.NEW, 0); 1768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad values.put(Calls.IS_READ, 1); 1778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad StringBuilder where = new StringBuilder(); 1788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(Calls.NEW); 1798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(" = 1 AND "); 1808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(Calls.TYPE); 1818de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(" = ?"); 1820f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh try { 183a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri callsUri = ContentProvider 184a993094840386163e9c2aa65a05e14b49d122318Tony Mak .maybeAddUserId(Calls.CONTENT_URI, userHandle.getIdentifier()); 185a993094840386163e9c2aa65a05e14b49d122318Tony Mak mContext.getContentResolver().update(callsUri, values, 1860f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh where.toString(), new String[]{ Integer.toString(Calls. 1870f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh MISSED_TYPE) }); 1880f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh } catch (IllegalArgumentException e) { 1890f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh Log.w(this, "ContactsProvider update command failed", e); 1900f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh } 1918de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 192e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger }.prepare()); 1938de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 1948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 19641045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee * Broadcasts missed call notification to custom component if set. 197a993094840386163e9c2aa65a05e14b49d122318Tony Mak * Currently the component is set in phone capable android wear device. 198a993094840386163e9c2aa65a05e14b49d122318Tony Mak * @param userHandle The user that has the missed call(s). 19941045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee * @return {@code true} if the broadcast was sent. {@code false} otherwise. 20041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee */ 2013037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private boolean sendNotificationCustomComponent(CallInfo callInfo, UserHandle userHandle) { 20241045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee if (mNotificationComponent != null) { 203a993094840386163e9c2aa65a05e14b49d122318Tony Mak int count = mMissedCallCounts.get(userHandle).get(); 20441045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee Intent intent = new Intent(); 20541045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 20641045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.setComponent(mNotificationComponent); 20741045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.setAction(TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION); 20841045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count); 20941045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER, 2103037ac6f171b6a3627494bb10042ab7adb34366aHall Liu callInfo == null ? null : callInfo.getPhoneNumber()); 21141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.putExtra(TelecomManager.EXTRA_CLEAR_MISSED_CALLS_INTENT, 212a993094840386163e9c2aa65a05e14b49d122318Tony Mak createClearMissedCallsPendingIntent(userHandle)); 21341045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 2146134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee 2153037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (count == 1 && callInfo != null) { 2163037ac6f171b6a3627494bb10042ab7adb34366aHall Liu String handle = callInfo.getHandleSchemeSpecificPart(); 2176134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee 2186134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee if (!TextUtils.isEmpty(handle) && !TextUtils.equals(handle, 2196134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee mContext.getString(R.string.handle_restricted))) { 2206134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee intent.putExtra(TelecomManager.EXTRA_CALL_BACK_INTENT, 2213037ac6f171b6a3627494bb10042ab7adb34366aHall Liu createCallBackPendingIntent(callInfo.getHandle(), userHandle)); 2226134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee } 22341045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 22441045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 22541045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee mContext.sendBroadcast(intent); 22641045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee return true; 22741045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 22841045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 22941045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee return false; 23041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 23141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 23241045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee /** 2333037ac6f171b6a3627494bb10042ab7adb34366aHall Liu * Returns the missed-call notification intent to send to the default dialer for the given user. 2343037ac6f171b6a3627494bb10042ab7adb34366aHall Liu * Note, the passed in userHandle is always the non-managed user for SIM calls (multi-user 23539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * calls). In this case we return the default dialer for the logged in user. This is never the 23639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * managed (work profile) dialer. 23739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * 23839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * For non-multi-user calls (3rd party phone accounts), the passed in userHandle is the user 23939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * handle of the phone account. This could be a managed user. In that case we return the default 24039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * dialer for the given user which could be a managed (work profile) dialer. 24139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal */ 24239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private Intent getShowMissedCallIntentForDefaultDialer(UserHandle userHandle) { 24339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal String dialerPackage = DefaultDialerManager 24439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .getDefaultDialerApplication(mContext, userHandle.getIdentifier()); 24539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (TextUtils.isEmpty(dialerPackage)) { 24639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return null; 24739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 24839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return new Intent(TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION) 24939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .setPackage(dialerPackage); 25039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 25139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 25239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private boolean shouldManageNotificationThroughDefaultDialer(UserHandle userHandle) { 25339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Intent intent = getShowMissedCallIntentForDefaultDialer(userHandle); 25439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (intent == null) { 25539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return false; 25639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 25739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 2584d34c5bc9ba32cb03c34fdb4186e084e85af79cfSailesh Nepal List<ResolveInfo> receivers = mContext.getPackageManager() 2594d34c5bc9ba32cb03c34fdb4186e084e85af79cfSailesh Nepal .queryBroadcastReceiversAsUser(intent, 0, userHandle.getIdentifier()); 26039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return receivers.size() > 0; 26139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 26239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 2633037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private void sendNotificationThroughDefaultDialer(CallInfo callInfo, UserHandle userHandle) { 26439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal int count = mMissedCallCounts.get(userHandle).get(); 26539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Intent intent = getShowMissedCallIntentForDefaultDialer(userHandle) 26639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .setFlags(Intent.FLAG_RECEIVER_FOREGROUND) 26739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count) 26839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER, 2693037ac6f171b6a3627494bb10042ab7adb34366aHall Liu callInfo == null ? null : callInfo.getPhoneNumber()); 27039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 27139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Log.w(this, "Showing missed calls through default dialer."); 27239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal mContext.sendBroadcastAsUser(intent, userHandle, READ_PHONE_STATE); 27339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 27439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 27539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal /** 2768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Create a system notification for the missed call. 2778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 2788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param call The missed call. 2798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 280226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee @Override 2813037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void showMissedCallNotification(@NonNull CallInfo callInfo) { 2823037ac6f171b6a3627494bb10042ab7adb34366aHall Liu final PhoneAccountHandle phoneAccountHandle = callInfo.getPhoneAccountHandle(); 283a993094840386163e9c2aa65a05e14b49d122318Tony Mak final PhoneAccount phoneAccount = 284a993094840386163e9c2aa65a05e14b49d122318Tony Mak mPhoneAccountRegistrar.getPhoneAccountUnchecked(phoneAccountHandle); 285a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle; 286a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (phoneAccount != null && 287a993094840386163e9c2aa65a05e14b49d122318Tony Mak phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) { 288a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle = mCurrentUserHandle; 289a993094840386163e9c2aa65a05e14b49d122318Tony Mak } else { 290a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle = phoneAccountHandle.getUserHandle(); 291a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 2923037ac6f171b6a3627494bb10042ab7adb34366aHall Liu showMissedCallNotification(callInfo, userHandle); 293a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 2948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 2953037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private void showMissedCallNotification(@NonNull CallInfo callInfo, UserHandle userHandle) { 2963037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.i(this, "showMissedCallNotification()"); 2973cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0)); 2983cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak int missCallCounts = mMissedCallCounts.get(userHandle).incrementAndGet(); 299a993094840386163e9c2aa65a05e14b49d122318Tony Mak 3003037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (sendNotificationCustomComponent(callInfo, userHandle)) { 30141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee return; 30241045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 30341045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 30439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (shouldManageNotificationThroughDefaultDialer(userHandle)) { 3053037ac6f171b6a3627494bb10042ab7adb34366aHall Liu sendNotificationThroughDefaultDialer(callInfo, userHandle); 30639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return; 30739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 30839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 3098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final int titleResId; 3108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final String expandedText; // The text in the notification's line 1 and 2. 3118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Display the first line of the notification: 3138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // 1 missed call: <caller name || handle> 3148de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // More than 1 missed call: <number of calls> + "missed calls" 315a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (missCallCounts == 1) { 3163037ac6f171b6a3627494bb10042ab7adb34366aHall Liu expandedText = getNameForMissedCallNotification(callInfo); 3179e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang 3183037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallerInfo ci = callInfo.getCallerInfo(); 3199e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang if (ci != null && ci.userType == CallerInfo.USER_TYPE_WORK) { 3209e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang titleResId = R.string.notification_missedWorkCallTitle; 3219e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang } else { 3229e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang titleResId = R.string.notification_missedCallTitle; 3239e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang } 3248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 3258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad titleResId = R.string.notification_missedCallsTitle; 3268de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad expandedText = 327a993094840386163e9c2aa65a05e14b49d122318Tony Mak mContext.getString(R.string.notification_missedCallsMsg, missCallCounts); 3288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3308fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Create a public viewable version of the notification, suitable for display when sensitive 3318fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // notification content is hidden. 332a993094840386163e9c2aa65a05e14b49d122318Tony Mak // We use user's context here to make sure notification is badged if it is a managed user. 333a993094840386163e9c2aa65a05e14b49d122318Tony Mak Context contextForUser = getContextForUser(userHandle); 334a993094840386163e9c2aa65a05e14b49d122318Tony Mak Notification.Builder publicBuilder = mNotificationBuilderFactory.getBuilder(contextForUser); 3358fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn publicBuilder.setSmallIcon(android.R.drawable.stat_notify_missed_call) 3368fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setColor(mContext.getResources().getColor(R.color.theme_color)) 3373037ac6f171b6a3627494bb10042ab7adb34366aHall Liu .setWhen(callInfo.getCreationTimeMillis()) 3388fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Show "Phone" for notification title. 3398fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setContentTitle(mContext.getText(R.string.userCallActivityLabel)) 3408fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Notification details shows that there are missed call(s), but does not reveal 3418fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // the missed caller information. 3428fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setContentText(mContext.getText(titleResId)) 343a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setContentIntent(createCallLogPendingIntent(userHandle)) 3448fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setAutoCancel(true) 345a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setDeleteIntent(createClearMissedCallsPendingIntent(userHandle)); 3468fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn 3478fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Create the notification suitable for display when sensitive information is showing. 348a993094840386163e9c2aa65a05e14b49d122318Tony Mak Notification.Builder builder = mNotificationBuilderFactory.getBuilder(contextForUser); 3498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setSmallIcon(android.R.drawable.stat_notify_missed_call) 3508de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setColor(mContext.getResources().getColor(R.color.theme_color)) 3513037ac6f171b6a3627494bb10042ab7adb34366aHall Liu .setWhen(callInfo.getCreationTimeMillis()) 3528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setContentTitle(mContext.getText(titleResId)) 3538de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setContentText(expandedText) 354a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setContentIntent(createCallLogPendingIntent(userHandle)) 3558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setAutoCancel(true) 356a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setDeleteIntent(createClearMissedCallsPendingIntent(userHandle)) 3578fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Include a public version of the notification to be shown when the missed call 3588fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // notification is shown on the user's lock screen and they have chosen to hide 3598fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // sensitive notification information. 3608fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setPublicVersion(publicBuilder.build()); 3618de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3623037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Uri handleUri = callInfo.getHandle(); 3633037ac6f171b6a3627494bb10042ab7adb34366aHall Liu String handle = callInfo.getHandleSchemeSpecificPart(); 3648de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3658de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Add additional actions when there is only 1 missed call, like call-back and SMS. 366a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (missCallCounts == 1) { 3678de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(this, "Add actions with number %s.", Log.piiHandle(handle)); 3688de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3698de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (!TextUtils.isEmpty(handle) 3708de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad && !TextUtils.equals(handle, mContext.getString(R.string.handle_restricted))) { 371bbdd44c57736b256ce118ce230ec95a1d42f30a7Andrew Lee builder.addAction(R.drawable.ic_phone_24dp, 3728de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mContext.getString(R.string.notification_missedCall_call_back), 373a993094840386163e9c2aa65a05e14b49d122318Tony Mak createCallBackPendingIntent(handleUri, userHandle)); 3748de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3753037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (canRespondViaSms(callInfo)) { 37635ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon builder.addAction(R.drawable.ic_message_24dp, 37735ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon mContext.getString(R.string.notification_missedCall_message), 378a993094840386163e9c2aa65a05e14b49d122318Tony Mak createSendSmsFromNotificationPendingIntent(handleUri, userHandle)); 37935ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon } 3808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3818de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3823037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Bitmap photoIcon = callInfo.getCallerInfo() == null ? 3833037ac6f171b6a3627494bb10042ab7adb34366aHall Liu null : callInfo.getCallerInfo().cachedPhotoIcon; 3848de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (photoIcon != null) { 3858de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setLargeIcon(photoIcon); 3868de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 3873037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Drawable photo = callInfo.getCallerInfo() == null ? 3883037ac6f171b6a3627494bb10042ab7adb34366aHall Liu null : callInfo.getCallerInfo().cachedPhoto; 3898de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (photo != null && photo instanceof BitmapDrawable) { 3908de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setLargeIcon(((BitmapDrawable) photo).getBitmap()); 3918de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3928de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3938de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 3948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(this, "Suppress actions. handle: %s, missedCalls: %d.", Log.piiHandle(handle), 395a993094840386163e9c2aa65a05e14b49d122318Tony Mak missCallCounts); 3968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3978de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Notification notification = builder.build(); 3998de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad configureLedOnNotification(notification); 4008de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4013037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.i(this, "Adding missed call notification for %s.", Log.pii(callInfo.getHandle())); 402761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee long token = Binder.clearCallingIdentity(); 403761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee try { 404761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee mNotificationManager.notifyAsUser( 405a993094840386163e9c2aa65a05e14b49d122318Tony Mak null /* tag */, MISSED_CALL_NOTIFICATION_ID, notification, userHandle); 406761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } finally { 407761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee Binder.restoreCallingIdentity(token); 408761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } 4098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 411a993094840386163e9c2aa65a05e14b49d122318Tony Mak 4128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** Cancels the "missed call" notification. */ 413a993094840386163e9c2aa65a05e14b49d122318Tony Mak private void cancelMissedCallNotification(UserHandle userHandle) { 4148de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Reset the number of missed calls to 0. 4153cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0)); 4163cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.get(userHandle).set(0); 41741045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 418a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (sendNotificationCustomComponent(null, userHandle)) { 41941045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee return; 42041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 42141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 42239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (shouldManageNotificationThroughDefaultDialer(userHandle)) { 42339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal sendNotificationThroughDefaultDialer(null, userHandle); 42439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return; 42539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 42639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 427761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee long token = Binder.clearCallingIdentity(); 428761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee try { 429a993094840386163e9c2aa65a05e14b49d122318Tony Mak mNotificationManager.cancelAsUser(null, MISSED_CALL_NOTIFICATION_ID, userHandle); 430761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } finally { 431761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee Binder.restoreCallingIdentity(token); 432761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } 4338de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4348de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 4368de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Returns the name to use in the missed call notification. 4378de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 4383037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private String getNameForMissedCallNotification(@NonNull CallInfo callInfo) { 4393037ac6f171b6a3627494bb10042ab7adb34366aHall Liu String handle = callInfo.getHandleSchemeSpecificPart(); 4403037ac6f171b6a3627494bb10042ab7adb34366aHall Liu String name = callInfo.getName(); 4418de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 442c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (!TextUtils.isEmpty(handle)) { 443c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn String formattedNumber = PhoneNumberUtils.formatNumber(handle, 444c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn getCurrentCountryIso(mContext)); 445c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 446c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // The formatted number will be null if there was a problem formatting it, but we can 447c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // default to using the unformatted number instead (e.g. a SIP URI may not be able to 448c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // be formatted. 449c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (!TextUtils.isEmpty(formattedNumber)) { 450c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn handle = formattedNumber; 451c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 452c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 453c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 4548de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (!TextUtils.isEmpty(name) && TextUtils.isGraphic(name)) { 4558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return name; 4568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else if (!TextUtils.isEmpty(handle)) { 4578de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // A handle should always be displayed LTR using {@link BidiFormatter} regardless of the 4588de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // content of the rest of the notification. 4598de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // TODO: Does this apply to SIP addresses? 4608de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad BidiFormatter bidiFormatter = BidiFormatter.getInstance(); 4618de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return bidiFormatter.unicodeWrap(handle, TextDirectionHeuristics.LTR); 4628de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 4638de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Use "unknown" if the call is unidentifiable. 4648de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return mContext.getString(R.string.unknown); 4658de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4668de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4678de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4688de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 469c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * @return The ISO 3166-1 two letters country code of the country the user is in based on the 470c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * network location. If the network location does not exist, fall back to the locale 471c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * setting. 472c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn */ 473c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn private String getCurrentCountryIso(Context context) { 474c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // Without framework function calls, this seems to be the most accurate location service 475c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // we can rely on. 476c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn final TelephonyManager telephonyManager = 477c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 478c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn String countryIso = telephonyManager.getNetworkCountryIso().toUpperCase(); 479c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 480c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (countryIso == null) { 481c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn countryIso = Locale.getDefault().getCountry(); 482c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn Log.w(this, "No CountryDetector; falling back to countryIso based on locale: " 483c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn + countryIso); 484c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 485c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn return countryIso; 486c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 487c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 488c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn /** 4898de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates a new pending intent that sends the user to the call log. 4908de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 4918de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @return The pending intent. 4928de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 493a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createCallLogPendingIntent(UserHandle userHandle) { 4948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Intent intent = new Intent(Intent.ACTION_VIEW, null); 4958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad intent.setType(Calls.CONTENT_TYPE); 4968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4978de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(mContext); 4988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad taskStackBuilder.addNextIntent(intent); 4998de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 500a993094840386163e9c2aa65a05e14b49d122318Tony Mak return taskStackBuilder.getPendingIntent(0, 0, null, userHandle); 5018de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5028de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5038de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5048de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the missed call notification is cleared. 5058de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 506a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createClearMissedCallsPendingIntent(UserHandle userHandle) { 5078de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 508a993094840386163e9c2aa65a05e14b49d122318Tony Mak TelecomBroadcastIntentProcessor.ACTION_CLEAR_MISSED_CALLS, null, userHandle); 5098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the user opts to "call back" from the missed call 5138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * notification. 5148de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 5158de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param handle The handle to call back. 5168de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 517a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createCallBackPendingIntent(Uri handle, UserHandle userHandle) { 5188de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 519a993094840386163e9c2aa65a05e14b49d122318Tony Mak TelecomBroadcastIntentProcessor.ACTION_CALL_BACK_FROM_NOTIFICATION, handle, 520a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle); 5218de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5228de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5238de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the user opts to "send sms" from the missed call 5258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * notification. 5268de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 527a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createSendSmsFromNotificationPendingIntent(Uri handle, 528a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle) { 5298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 5308de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad TelecomBroadcastIntentProcessor.ACTION_SEND_SMS_FROM_NOTIFICATION, 531a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri.fromParts(Constants.SCHEME_SMSTO, handle.getSchemeSpecificPart(), null), 532a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle); 5338de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5348de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5368de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates generic pending intent from the specified parameters to be received by 5378de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * {@link TelecomBroadcastIntentProcessor}. 5388de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 5398de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param action The intent action. 5408de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param data The intent data. 5418de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 542a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createTelecomPendingIntent(String action, Uri data, 543a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle) { 544226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee Intent intent = new Intent(action, data, mContext, TelecomBroadcastReceiver.class); 545a993094840386163e9c2aa65a05e14b49d122318Tony Mak intent.putExtra(TelecomBroadcastIntentProcessor.EXTRA_USERHANDLE, userHandle); 5468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return PendingIntent.getBroadcast(mContext, 0, intent, 0); 5478de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5508de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Configures a notification to emit the blinky notification light. 5518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 5528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private void configureLedOnNotification(Notification notification) { 5538de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad notification.flags |= Notification.FLAG_SHOW_LIGHTS; 5548de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad notification.defaults |= Notification.DEFAULT_LIGHTS; 5558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5573037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private boolean canRespondViaSms(@NonNull CallInfo callInfo) { 55835ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon // Only allow respond-via-sms for "tel:" calls. 5593037ac6f171b6a3627494bb10042ab7adb34366aHall Liu return callInfo.getHandle() != null && 5603037ac6f171b6a3627494bb10042ab7adb34366aHall Liu PhoneAccount.SCHEME_TEL.equals(callInfo.getHandle().getScheme()); 56135ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon } 56235ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon 5633037ac6f171b6a3627494bb10042ab7adb34366aHall Liu @Override 5643037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void reloadAfterBootComplete(final CallerInfoLookupHelper callerInfoLookupHelper, 5653037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallInfoFactory callInfoFactory) { 5663037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (userToLoadAfterBootComplete != null) { 5673037ac6f171b6a3627494bb10042ab7adb34366aHall Liu reloadFromDatabase(callerInfoLookupHelper, 5683037ac6f171b6a3627494bb10042ab7adb34366aHall Liu callInfoFactory, userToLoadAfterBootComplete); 5693037ac6f171b6a3627494bb10042ab7adb34366aHall Liu userToLoadAfterBootComplete = null; 5703037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 5713037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 5728de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Adds the missed call notification on startup if there are unread missed calls. 5748de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 5758d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad @Override 5763037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void reloadFromDatabase(final CallerInfoLookupHelper callerInfoLookupHelper, 5773037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallInfoFactory callInfoFactory, final UserHandle userHandle) { 578a993094840386163e9c2aa65a05e14b49d122318Tony Mak Log.d(this, "reloadFromDatabase()..."); 5793037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (TelecomSystem.getInstance() == null || !TelecomSystem.getInstance().isBootComplete()) { 5803037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.i(this, "Boot not yet complete -- call log db may not be available. Deferring " + 5813037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "loading until boot complete."); 5823037ac6f171b6a3627494bb10042ab7adb34366aHall Liu userToLoadAfterBootComplete = userHandle; 5833037ac6f171b6a3627494bb10042ab7adb34366aHall Liu return; 5843037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 5858de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5868de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // instantiate query handler 5878de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad AsyncQueryHandler queryHandler = new AsyncQueryHandler(mContext.getContentResolver()) { 5888de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad @Override 5898de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 5908de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(MissedCallNotifierImpl.this, "onQueryComplete()..."); 5918de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (cursor != null) { 5928de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad try { 593a993094840386163e9c2aa65a05e14b49d122318Tony Mak mMissedCallCounts.remove(userHandle); 5948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad while (cursor.moveToNext()) { 5958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Get data about the missed call from the cursor 5968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final String handleString = cursor.getString(CALL_LOG_COLUMN_NUMBER); 5978de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final int presentation = 5988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad cursor.getInt(CALL_LOG_COLUMN_NUMBER_PRESENTATION); 5998de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final long date = cursor.getLong(CALL_LOG_COLUMN_DATE); 6008de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 6018de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final Uri handle; 6028de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (presentation != Calls.PRESENTATION_ALLOWED 6038de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad || TextUtils.isEmpty(handleString)) { 6048de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handle = null; 6058de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 6068de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(handleString) ? 6078de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, 6088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handleString, null); 6098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 6113037ac6f171b6a3627494bb10042ab7adb34366aHall Liu callerInfoLookupHelper.startLookup(handle, 6123037ac6f171b6a3627494bb10042ab7adb34366aHall Liu new CallerInfoLookupHelper.OnQueryCompleteListener() { 6133037ac6f171b6a3627494bb10042ab7adb34366aHall Liu @Override 6143037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void onCallerInfoQueryComplete(Uri queryHandle, 6153037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallerInfo info) { 6163037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (!Objects.equals(queryHandle, handle)) { 6173037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.w(MissedCallNotifierImpl.this, 6183037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "CallerInfo query returned with " + 6193037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "different handle."); 6203037ac6f171b6a3627494bb10042ab7adb34366aHall Liu return; 6213037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6223037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (info.contactDisplayPhotoUri == null) { 6233037ac6f171b6a3627494bb10042ab7adb34366aHall Liu // If there is no photo, just show the notification. 6243037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallInfo callInfo = callInfoFactory.makeCallInfo( 6253037ac6f171b6a3627494bb10042ab7adb34366aHall Liu info, null, handle, date); 6263037ac6f171b6a3627494bb10042ab7adb34366aHall Liu showMissedCallNotification(callInfo, userHandle); 6273037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6283037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6293037ac6f171b6a3627494bb10042ab7adb34366aHall Liu 6303037ac6f171b6a3627494bb10042ab7adb34366aHall Liu @Override 6313037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void onContactPhotoQueryComplete(Uri queryHandle, 6323037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallerInfo info) { 6333037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (!Objects.equals(queryHandle, handle)) { 6343037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.w(MissedCallNotifierImpl.this, 6353037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "CallerInfo query for photo returned " + 6363037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "with different handle."); 6373037ac6f171b6a3627494bb10042ab7adb34366aHall Liu return; 6383037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6393037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallInfo callInfo = callInfoFactory.makeCallInfo( 6403037ac6f171b6a3627494bb10042ab7adb34366aHall Liu info, null, handle, date); 6413037ac6f171b6a3627494bb10042ab7adb34366aHall Liu showMissedCallNotification(callInfo, userHandle); 6423037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6438d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad } 6443037ac6f171b6a3627494bb10042ab7adb34366aHall Liu ); 6458de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } finally { 6478de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad cursor.close(); 6488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6508de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad }; 6528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 6538de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // setup query spec, look for all Missed calls that are new. 654a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri callsUri = 655a993094840386163e9c2aa65a05e14b49d122318Tony Mak ContentProvider.maybeAddUserId(Calls.CONTENT_URI, userHandle.getIdentifier()); 6568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // start the query 657a993094840386163e9c2aa65a05e14b49d122318Tony Mak queryHandler.startQuery(0, null, callsUri, CALL_LOG_PROJECTION, 6583037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CALL_LOG_WHERE_CLAUSE, null, Calls.DEFAULT_SORT_ORDER); 6598de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 660a993094840386163e9c2aa65a05e14b49d122318Tony Mak 661a993094840386163e9c2aa65a05e14b49d122318Tony Mak @Override 662a993094840386163e9c2aa65a05e14b49d122318Tony Mak public void setCurrentUserHandle(UserHandle currentUserHandle) { 663a993094840386163e9c2aa65a05e14b49d122318Tony Mak mCurrentUserHandle = currentUserHandle; 664a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 665a993094840386163e9c2aa65a05e14b49d122318Tony Mak 666a993094840386163e9c2aa65a05e14b49d122318Tony Mak private Context getContextForUser(UserHandle user) { 667a993094840386163e9c2aa65a05e14b49d122318Tony Mak try { 668a993094840386163e9c2aa65a05e14b49d122318Tony Mak return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user); 669a993094840386163e9c2aa65a05e14b49d122318Tony Mak } catch (NameNotFoundException e) { 670a993094840386163e9c2aa65a05e14b49d122318Tony Mak // Default to mContext, not finding the package system is running as is unlikely. 671a993094840386163e9c2aa65a05e14b49d122318Tony Mak return mContext; 672a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 673a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 6748de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad} 675