MissedCallNotifierImpl.java revision e8b11f8edc4a684cab2d11426cfe465e66bdf18a
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 218755e29fd54403b404b4940d3dccebf83a8acbcfHall Liuimport android.annotation.NonNull; 2241045b499a47c00459986c96bbbb28ffee2cbefcBryce Leeimport android.content.ComponentName; 23a993094840386163e9c2aa65a05e14b49d122318Tony Makimport android.content.ContentProvider; 24a993094840386163e9c2aa65a05e14b49d122318Tony Makimport android.content.pm.PackageManager.NameNotFoundException; 25953e1af643b66df6f931d76c23bcc54147668cd4Brad Ebingerimport android.telecom.Logging.Runnable; 26a993094840386163e9c2aa65a05e14b49d122318Tony Makimport android.telecom.PhoneAccountHandle; 2741045b499a47c00459986c96bbbb28ffee2cbefcBryce Leeimport android.telecom.TelecomManager; 28a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 298755e29fd54403b404b4940d3dccebf83a8acbcfHall Liuimport com.android.server.telecom.CallerInfoLookupHelper; 308de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.CallsManagerListenerBase; 318de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.Constants; 328d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadimport com.android.server.telecom.MissedCallNotifier; 33a993094840386163e9c2aa65a05e14b49d122318Tony Makimport com.android.server.telecom.PhoneAccountRegistrar; 348de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.R; 358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport com.android.server.telecom.TelecomBroadcastIntentProcessor; 368d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadimport com.android.server.telecom.TelecomSystem; 37226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Leeimport com.android.server.telecom.components.TelecomBroadcastReceiver; 388de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 398de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.app.Notification; 408de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.app.NotificationManager; 418de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.app.PendingIntent; 428de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.app.TaskStackBuilder; 438de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.content.AsyncQueryHandler; 448de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.content.ContentValues; 458de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.content.Context; 468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.content.Intent; 4739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepalimport android.content.pm.ResolveInfo; 488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.database.Cursor; 498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.graphics.Bitmap; 508de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.graphics.drawable.BitmapDrawable; 518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.graphics.drawable.Drawable; 528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.net.Uri; 538de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.os.AsyncTask; 54761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Leeimport android.os.Binder; 558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.os.UserHandle; 568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.provider.CallLog.Calls; 5739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepalimport android.telecom.DefaultDialerManager; 58953e1af643b66df6f931d76c23bcc54147668cd4Brad Ebingerimport android.telecom.Log; 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; 728755e29fd54403b404b4940d3dccebf83a8acbcfHall Liuimport java.util.Objects; 73a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.ConcurrentHashMap; 74a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.ConcurrentMap; 75a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.atomic.AtomicInteger; 7641045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad// TODO: Needed for move to system service: import com.android.internal.R; 788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad/** 808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates a notification for calls that the user missed (neither answered nor rejected). 818de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 828de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * TODO: Make TelephonyManager.clearMissedCalls call into this class. 838de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 848d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadpublic class MissedCallNotifierImpl extends CallsManagerListenerBase implements MissedCallNotifier { 858de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 86a993094840386163e9c2aa65a05e14b49d122318Tony Mak public interface MissedCallNotifierImplFactory { 87a993094840386163e9c2aa65a05e14b49d122318Tony Mak MissedCallNotifier makeMissedCallNotifierImpl(Context context, 88a993094840386163e9c2aa65a05e14b49d122318Tony Mak PhoneAccountRegistrar phoneAccountRegistrar); 89a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 90a993094840386163e9c2aa65a05e14b49d122318Tony Mak 91a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public interface NotificationBuilderFactory { 92a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu Notification.Builder getBuilder(Context context); 93a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 94a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 95a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu private static class DefaultNotificationBuilderFactory implements NotificationBuilderFactory { 96a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public DefaultNotificationBuilderFactory() {} 97a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 98a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu @Override 99a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public Notification.Builder getBuilder(Context context) { 100a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu return new Notification.Builder(context); 101a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 102a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 103a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 1048de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private static final String[] CALL_LOG_PROJECTION = new String[] { 1058de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls._ID, 1068de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.NUMBER, 1078de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.NUMBER_PRESENTATION, 1088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.DATE, 1098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.DURATION, 1108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Calls.TYPE, 1118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad }; 1128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1138755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu private static final String CALL_LOG_WHERE_CLAUSE = "type=" + Calls.MISSED_TYPE + 1148755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu " AND new=1" + 1158755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu " AND is_read=0"; 1168755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu 1178755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public static final int CALL_LOG_COLUMN_ID = 0; 1188755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public static final int CALL_LOG_COLUMN_NUMBER = 1; 1198755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public static final int CALL_LOG_COLUMN_NUMBER_PRESENTATION = 2; 1208755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public static final int CALL_LOG_COLUMN_DATE = 3; 1218755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public static final int CALL_LOG_COLUMN_DURATION = 4; 1228755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public static final int CALL_LOG_COLUMN_TYPE = 5; 1238de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private static final int MISSED_CALL_NOTIFICATION_ID = 1; 1258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1268de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private final Context mContext; 127a993094840386163e9c2aa65a05e14b49d122318Tony Mak private final PhoneAccountRegistrar mPhoneAccountRegistrar; 1288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private final NotificationManager mNotificationManager; 129a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu private final NotificationBuilderFactory mNotificationBuilderFactory; 13041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee private final ComponentName mNotificationComponent; 131a993094840386163e9c2aa65a05e14b49d122318Tony Mak private UserHandle mCurrentUserHandle; 13241045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 1338de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Used to track the number of missed calls. 134a993094840386163e9c2aa65a05e14b49d122318Tony Mak private ConcurrentMap<UserHandle, AtomicInteger> mMissedCallCounts; 1358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1368755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu private UserHandle userToLoadAfterBootComplete; 1378755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu 138a993094840386163e9c2aa65a05e14b49d122318Tony Mak public MissedCallNotifierImpl(Context context, PhoneAccountRegistrar phoneAccountRegistrar) { 139a993094840386163e9c2aa65a05e14b49d122318Tony Mak this(context, phoneAccountRegistrar, new DefaultNotificationBuilderFactory()); 140a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 141a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 142a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public MissedCallNotifierImpl(Context context, 143a993094840386163e9c2aa65a05e14b49d122318Tony Mak PhoneAccountRegistrar phoneAccountRegistrar, 144a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu NotificationBuilderFactory notificationBuilderFactory) { 1458de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mContext = context; 146a993094840386163e9c2aa65a05e14b49d122318Tony Mak mPhoneAccountRegistrar = phoneAccountRegistrar; 1478de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mNotificationManager = 1488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 14941045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee final String notificationComponent = context.getString(R.string.notification_component); 15041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 151a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu mNotificationBuilderFactory = notificationBuilderFactory; 15241045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee mNotificationComponent = notificationComponent != null 15341045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee ? ComponentName.unflattenFromString(notificationComponent) : null; 154a993094840386163e9c2aa65a05e14b49d122318Tony Mak mMissedCallCounts = new ConcurrentHashMap<>(); 1558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 1568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1578de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** Clears missed call notification and marks the call log's missed calls as read. */ 158226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee @Override 15939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal public void clearMissedCalls(UserHandle userHandle) { 16039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal // If the default dialer is showing the missed call notification then it will modify the 16139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal // call log and we don't have to do anything here. 16239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (!shouldManageNotificationThroughDefaultDialer(userHandle)) { 16339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal markMissedCallsAsRead(userHandle); 16439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 16539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal cancelMissedCallNotification(userHandle); 16639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 16739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 16839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private void markMissedCallsAsRead(final UserHandle userHandle) { 169d608fcc41c5075903b560c1b2f50d1bfed287e18Brad Ebinger AsyncTask.execute(new Runnable("MCNI.mMCAR", null /*lock*/) { 1708de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad @Override 171e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger public void loggedRun() { 1728de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Clear the list of new missed calls from the call log. 1738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad ContentValues values = new ContentValues(); 1748de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad values.put(Calls.NEW, 0); 1758de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad values.put(Calls.IS_READ, 1); 1768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad StringBuilder where = new StringBuilder(); 1778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(Calls.NEW); 1788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(" = 1 AND "); 1798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(Calls.TYPE); 1808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(" = ?"); 1810f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh try { 182a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri callsUri = ContentProvider 183a993094840386163e9c2aa65a05e14b49d122318Tony Mak .maybeAddUserId(Calls.CONTENT_URI, userHandle.getIdentifier()); 184a993094840386163e9c2aa65a05e14b49d122318Tony Mak mContext.getContentResolver().update(callsUri, values, 1850f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh where.toString(), new String[]{ Integer.toString(Calls. 1860f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh MISSED_TYPE) }); 1870f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh } catch (IllegalArgumentException e) { 1880f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh Log.w(this, "ContactsProvider update command failed", e); 1890f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh } 1908de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 191e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger }.prepare()); 1928de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 1938de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 19541045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee * Broadcasts missed call notification to custom component if set. 196a993094840386163e9c2aa65a05e14b49d122318Tony Mak * Currently the component is set in phone capable android wear device. 197a993094840386163e9c2aa65a05e14b49d122318Tony Mak * @param userHandle The user that has the missed call(s). 19841045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee * @return {@code true} if the broadcast was sent. {@code false} otherwise. 19941045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee */ 2008755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu private boolean sendNotificationCustomComponent(CallInfo callInfo, UserHandle userHandle) { 20141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee if (mNotificationComponent != null) { 202a993094840386163e9c2aa65a05e14b49d122318Tony Mak int count = mMissedCallCounts.get(userHandle).get(); 20341045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee Intent intent = new Intent(); 20441045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 20541045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.setComponent(mNotificationComponent); 20641045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.setAction(TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION); 20741045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count); 20841045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER, 2098755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu callInfo == null ? null : callInfo.getPhoneNumber()); 21041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee intent.putExtra(TelecomManager.EXTRA_CLEAR_MISSED_CALLS_INTENT, 211a993094840386163e9c2aa65a05e14b49d122318Tony Mak createClearMissedCallsPendingIntent(userHandle)); 21241045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 2136134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee 2148755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu if (count == 1 && callInfo != null) { 2158755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu String handle = callInfo.getHandleSchemeSpecificPart(); 2166134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee 2176134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee if (!TextUtils.isEmpty(handle) && !TextUtils.equals(handle, 2186134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee mContext.getString(R.string.handle_restricted))) { 2196134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee intent.putExtra(TelecomManager.EXTRA_CALL_BACK_INTENT, 2208755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu createCallBackPendingIntent(callInfo.getHandle(), userHandle)); 2216134090794feafcbf3f09878a16b12f00d9b3215Bryce Lee } 22241045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 22341045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 22441045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee mContext.sendBroadcast(intent); 22541045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee return true; 22641045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 22741045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 22841045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee return false; 22941045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 23041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 23141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee /** 2328755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu * Returns the missed-call notification intent to send to the default dialer for the given user. 2338755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu * Note, the passed in userHandle is always the non-managed user for SIM calls (multi-user 23439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * calls). In this case we return the default dialer for the logged in user. This is never the 23539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * managed (work profile) dialer. 23639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * 23739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * For non-multi-user calls (3rd party phone accounts), the passed in userHandle is the user 23839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * handle of the phone account. This could be a managed user. In that case we return the default 23939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * dialer for the given user which could be a managed (work profile) dialer. 24039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal */ 24139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private Intent getShowMissedCallIntentForDefaultDialer(UserHandle userHandle) { 24239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal String dialerPackage = DefaultDialerManager 24339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .getDefaultDialerApplication(mContext, userHandle.getIdentifier()); 24439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (TextUtils.isEmpty(dialerPackage)) { 24539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return null; 24639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 24739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return new Intent(TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION) 24839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .setPackage(dialerPackage); 24939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 25039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 25139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private boolean shouldManageNotificationThroughDefaultDialer(UserHandle userHandle) { 25239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Intent intent = getShowMissedCallIntentForDefaultDialer(userHandle); 25339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (intent == null) { 25439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return false; 25539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 25639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 2574d34c5bc9ba32cb03c34fdb4186e084e85af79cfSailesh Nepal List<ResolveInfo> receivers = mContext.getPackageManager() 2584d34c5bc9ba32cb03c34fdb4186e084e85af79cfSailesh Nepal .queryBroadcastReceiversAsUser(intent, 0, userHandle.getIdentifier()); 25939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return receivers.size() > 0; 26039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 26139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 2628755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu private void sendNotificationThroughDefaultDialer(CallInfo callInfo, UserHandle userHandle) { 26339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal int count = mMissedCallCounts.get(userHandle).get(); 26439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Intent intent = getShowMissedCallIntentForDefaultDialer(userHandle) 26539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .setFlags(Intent.FLAG_RECEIVER_FOREGROUND) 26639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count) 26739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER, 2688755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu callInfo == null ? null : callInfo.getPhoneNumber()); 26939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 27039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Log.w(this, "Showing missed calls through default dialer."); 27139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal mContext.sendBroadcastAsUser(intent, userHandle, READ_PHONE_STATE); 27239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 27339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 27439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal /** 2758de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Create a system notification for the missed call. 2768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 2778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param call The missed call. 2788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 279226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee @Override 2808755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public void showMissedCallNotification(@NonNull CallInfo callInfo) { 2818755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu final PhoneAccountHandle phoneAccountHandle = callInfo.getPhoneAccountHandle(); 282a993094840386163e9c2aa65a05e14b49d122318Tony Mak final PhoneAccount phoneAccount = 283a993094840386163e9c2aa65a05e14b49d122318Tony Mak mPhoneAccountRegistrar.getPhoneAccountUnchecked(phoneAccountHandle); 284a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle; 285a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (phoneAccount != null && 286a993094840386163e9c2aa65a05e14b49d122318Tony Mak phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) { 287a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle = mCurrentUserHandle; 288a993094840386163e9c2aa65a05e14b49d122318Tony Mak } else { 289a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle = phoneAccountHandle.getUserHandle(); 290a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 2918755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu showMissedCallNotification(callInfo, userHandle); 292a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 2938de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 2948755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu private void showMissedCallNotification(@NonNull CallInfo callInfo, UserHandle userHandle) { 2958755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu Log.i(this, "showMissedCallNotification()"); 2963cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0)); 2973cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak int missCallCounts = mMissedCallCounts.get(userHandle).incrementAndGet(); 298a993094840386163e9c2aa65a05e14b49d122318Tony Mak 2998755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu if (sendNotificationCustomComponent(callInfo, userHandle)) { 30041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee return; 30141045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 30241045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 30339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (shouldManageNotificationThroughDefaultDialer(userHandle)) { 3048755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu sendNotificationThroughDefaultDialer(callInfo, userHandle); 30539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return; 30639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 30739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 3088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final int titleResId; 3098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final String expandedText; // The text in the notification's line 1 and 2. 3108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Display the first line of the notification: 3128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // 1 missed call: <caller name || handle> 3138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // More than 1 missed call: <number of calls> + "missed calls" 314a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (missCallCounts == 1) { 3158755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu expandedText = getNameForMissedCallNotification(callInfo); 3169e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang 3178755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu CallerInfo ci = callInfo.getCallerInfo(); 3189e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang if (ci != null && ci.userType == CallerInfo.USER_TYPE_WORK) { 3199e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang titleResId = R.string.notification_missedWorkCallTitle; 3209e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang } else { 3219e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang titleResId = R.string.notification_missedCallTitle; 3229e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang } 3238de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 3248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad titleResId = R.string.notification_missedCallsTitle; 3258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad expandedText = 326a993094840386163e9c2aa65a05e14b49d122318Tony Mak mContext.getString(R.string.notification_missedCallsMsg, missCallCounts); 3278de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3298fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Create a public viewable version of the notification, suitable for display when sensitive 3308fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // notification content is hidden. 331a993094840386163e9c2aa65a05e14b49d122318Tony Mak // We use user's context here to make sure notification is badged if it is a managed user. 332a993094840386163e9c2aa65a05e14b49d122318Tony Mak Context contextForUser = getContextForUser(userHandle); 333a993094840386163e9c2aa65a05e14b49d122318Tony Mak Notification.Builder publicBuilder = mNotificationBuilderFactory.getBuilder(contextForUser); 3348fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn publicBuilder.setSmallIcon(android.R.drawable.stat_notify_missed_call) 3358fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setColor(mContext.getResources().getColor(R.color.theme_color)) 3368755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu .setWhen(callInfo.getCreationTimeMillis()) 3378fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Show "Phone" for notification title. 3388fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setContentTitle(mContext.getText(R.string.userCallActivityLabel)) 3398fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Notification details shows that there are missed call(s), but does not reveal 3408fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // the missed caller information. 3418fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setContentText(mContext.getText(titleResId)) 342a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setContentIntent(createCallLogPendingIntent(userHandle)) 3438fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setAutoCancel(true) 344a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setDeleteIntent(createClearMissedCallsPendingIntent(userHandle)); 3458fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn 3468fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Create the notification suitable for display when sensitive information is showing. 347a993094840386163e9c2aa65a05e14b49d122318Tony Mak Notification.Builder builder = mNotificationBuilderFactory.getBuilder(contextForUser); 3488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setSmallIcon(android.R.drawable.stat_notify_missed_call) 3498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setColor(mContext.getResources().getColor(R.color.theme_color)) 3508755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu .setWhen(callInfo.getCreationTimeMillis()) 3518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setContentTitle(mContext.getText(titleResId)) 3528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setContentText(expandedText) 353a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setContentIntent(createCallLogPendingIntent(userHandle)) 3548de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setAutoCancel(true) 355a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setDeleteIntent(createClearMissedCallsPendingIntent(userHandle)) 3568fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Include a public version of the notification to be shown when the missed call 3578fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // notification is shown on the user's lock screen and they have chosen to hide 3588fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // sensitive notification information. 3598fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setPublicVersion(publicBuilder.build()); 3608de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3618755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu Uri handleUri = callInfo.getHandle(); 3628755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu String handle = callInfo.getHandleSchemeSpecificPart(); 3638de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3648de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Add additional actions when there is only 1 missed call, like call-back and SMS. 365a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (missCallCounts == 1) { 3668de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(this, "Add actions with number %s.", Log.piiHandle(handle)); 3678de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3688de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (!TextUtils.isEmpty(handle) 3698de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad && !TextUtils.equals(handle, mContext.getString(R.string.handle_restricted))) { 370bbdd44c57736b256ce118ce230ec95a1d42f30a7Andrew Lee builder.addAction(R.drawable.ic_phone_24dp, 3718de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mContext.getString(R.string.notification_missedCall_call_back), 372a993094840386163e9c2aa65a05e14b49d122318Tony Mak createCallBackPendingIntent(handleUri, userHandle)); 3738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3748755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu if (canRespondViaSms(callInfo)) { 37535ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon builder.addAction(R.drawable.ic_message_24dp, 37635ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon mContext.getString(R.string.notification_missedCall_message), 377a993094840386163e9c2aa65a05e14b49d122318Tony Mak createSendSmsFromNotificationPendingIntent(handleUri, userHandle)); 37835ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon } 3798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3818755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu Bitmap photoIcon = callInfo.getCallerInfo() == null ? 3828755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu null : callInfo.getCallerInfo().cachedPhotoIcon; 3838de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (photoIcon != null) { 3848de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setLargeIcon(photoIcon); 3858de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 3868755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu Drawable photo = callInfo.getCallerInfo() == null ? 3878755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu null : callInfo.getCallerInfo().cachedPhoto; 3888de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (photo != null && photo instanceof BitmapDrawable) { 3898de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setLargeIcon(((BitmapDrawable) photo).getBitmap()); 3908de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3918de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3928de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 3938de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(this, "Suppress actions. handle: %s, missedCalls: %d.", Log.piiHandle(handle), 394a993094840386163e9c2aa65a05e14b49d122318Tony Mak missCallCounts); 3958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3978de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Notification notification = builder.build(); 3988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad configureLedOnNotification(notification); 3998de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4008755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu Log.i(this, "Adding missed call notification for %s.", Log.pii(callInfo.getHandle())); 401761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee long token = Binder.clearCallingIdentity(); 402761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee try { 403761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee mNotificationManager.notifyAsUser( 404a993094840386163e9c2aa65a05e14b49d122318Tony Mak null /* tag */, MISSED_CALL_NOTIFICATION_ID, notification, userHandle); 405761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } finally { 406761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee Binder.restoreCallingIdentity(token); 407761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } 4088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 410a993094840386163e9c2aa65a05e14b49d122318Tony Mak 4118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** Cancels the "missed call" notification. */ 412a993094840386163e9c2aa65a05e14b49d122318Tony Mak private void cancelMissedCallNotification(UserHandle userHandle) { 4138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Reset the number of missed calls to 0. 4143cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0)); 4153cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.get(userHandle).set(0); 41641045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 417a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (sendNotificationCustomComponent(null, userHandle)) { 41841045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee return; 41941045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee } 42041045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 42139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (shouldManageNotificationThroughDefaultDialer(userHandle)) { 42239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal sendNotificationThroughDefaultDialer(null, userHandle); 42339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return; 42439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 42539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 426761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee long token = Binder.clearCallingIdentity(); 427761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee try { 428a993094840386163e9c2aa65a05e14b49d122318Tony Mak mNotificationManager.cancelAsUser(null, MISSED_CALL_NOTIFICATION_ID, userHandle); 429761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } finally { 430761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee Binder.restoreCallingIdentity(token); 431761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } 4328de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4338de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4348de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 4358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Returns the name to use in the missed call notification. 4368de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 4378755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu private String getNameForMissedCallNotification(@NonNull CallInfo callInfo) { 4388755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu String handle = callInfo.getHandleSchemeSpecificPart(); 4398755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu String name = callInfo.getName(); 4408de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 441c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (!TextUtils.isEmpty(handle)) { 442c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn String formattedNumber = PhoneNumberUtils.formatNumber(handle, 443c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn getCurrentCountryIso(mContext)); 444c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 445c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // The formatted number will be null if there was a problem formatting it, but we can 446c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // default to using the unformatted number instead (e.g. a SIP URI may not be able to 447c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // be formatted. 448c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (!TextUtils.isEmpty(formattedNumber)) { 449c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn handle = formattedNumber; 450c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 451c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 452c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 4538de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (!TextUtils.isEmpty(name) && TextUtils.isGraphic(name)) { 4548de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return name; 4558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else if (!TextUtils.isEmpty(handle)) { 4568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // A handle should always be displayed LTR using {@link BidiFormatter} regardless of the 4578de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // content of the rest of the notification. 4588de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // TODO: Does this apply to SIP addresses? 4598de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad BidiFormatter bidiFormatter = BidiFormatter.getInstance(); 4608de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return bidiFormatter.unicodeWrap(handle, TextDirectionHeuristics.LTR); 4618de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 4628de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Use "unknown" if the call is unidentifiable. 4638de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return mContext.getString(R.string.unknown); 4648de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4658de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4668de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4678de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 468c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * @return The ISO 3166-1 two letters country code of the country the user is in based on the 469c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * network location. If the network location does not exist, fall back to the locale 470c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * setting. 471c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn */ 472c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn private String getCurrentCountryIso(Context context) { 473c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // Without framework function calls, this seems to be the most accurate location service 474c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // we can rely on. 475c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn final TelephonyManager telephonyManager = 476c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 477c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn String countryIso = telephonyManager.getNetworkCountryIso().toUpperCase(); 478c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 479c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (countryIso == null) { 480c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn countryIso = Locale.getDefault().getCountry(); 481c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn Log.w(this, "No CountryDetector; falling back to countryIso based on locale: " 482c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn + countryIso); 483c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 484c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn return countryIso; 485c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 486c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 487c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn /** 4888de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates a new pending intent that sends the user to the call log. 4898de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 4908de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @return The pending intent. 4918de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 492a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createCallLogPendingIntent(UserHandle userHandle) { 4938de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Intent intent = new Intent(Intent.ACTION_VIEW, null); 4948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad intent.setType(Calls.CONTENT_TYPE); 4958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(mContext); 4978de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad taskStackBuilder.addNextIntent(intent); 4988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 499a993094840386163e9c2aa65a05e14b49d122318Tony Mak return taskStackBuilder.getPendingIntent(0, 0, null, userHandle); 5008de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5018de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5028de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5038de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the missed call notification is cleared. 5048de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 505a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createClearMissedCallsPendingIntent(UserHandle userHandle) { 5068de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 507a993094840386163e9c2aa65a05e14b49d122318Tony Mak TelecomBroadcastIntentProcessor.ACTION_CLEAR_MISSED_CALLS, null, userHandle); 5088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the user opts to "call back" from the missed call 5128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * notification. 5138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 5148de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param handle The handle to call back. 5158de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 516a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createCallBackPendingIntent(Uri handle, UserHandle userHandle) { 5178de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 518a993094840386163e9c2aa65a05e14b49d122318Tony Mak TelecomBroadcastIntentProcessor.ACTION_CALL_BACK_FROM_NOTIFICATION, handle, 519a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle); 5208de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5218de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5228de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5238de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the user opts to "send sms" from the missed call 5248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * notification. 5258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 526a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createSendSmsFromNotificationPendingIntent(Uri handle, 527a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle) { 5288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 5298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad TelecomBroadcastIntentProcessor.ACTION_SEND_SMS_FROM_NOTIFICATION, 530a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri.fromParts(Constants.SCHEME_SMSTO, handle.getSchemeSpecificPart(), null), 531a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle); 5328de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5338de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5348de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates generic pending intent from the specified parameters to be received by 5368de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * {@link TelecomBroadcastIntentProcessor}. 5378de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 5388de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param action The intent action. 5398de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param data The intent data. 5408de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 541a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createTelecomPendingIntent(String action, Uri data, 542a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle) { 543226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee Intent intent = new Intent(action, data, mContext, TelecomBroadcastReceiver.class); 544a993094840386163e9c2aa65a05e14b49d122318Tony Mak intent.putExtra(TelecomBroadcastIntentProcessor.EXTRA_USERHANDLE, userHandle); 545e8b11f8edc4a684cab2d11426cfe465e66bdf18aHonggang Luo return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 5468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5478de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Configures a notification to emit the blinky notification light. 5508de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 5518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private void configureLedOnNotification(Notification notification) { 5528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad notification.flags |= Notification.FLAG_SHOW_LIGHTS; 5538de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad notification.defaults |= Notification.DEFAULT_LIGHTS; 5548de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5568755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu private boolean canRespondViaSms(@NonNull CallInfo callInfo) { 55735ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon // Only allow respond-via-sms for "tel:" calls. 5588755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu return callInfo.getHandle() != null && 5598755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu PhoneAccount.SCHEME_TEL.equals(callInfo.getHandle().getScheme()); 56035ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon } 56135ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon 5628755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu @Override 5638755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public void reloadAfterBootComplete(final CallerInfoLookupHelper callerInfoLookupHelper, 5648755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu CallInfoFactory callInfoFactory) { 5658755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu if (userToLoadAfterBootComplete != null) { 5668755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu reloadFromDatabase(callerInfoLookupHelper, 5678755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu callInfoFactory, userToLoadAfterBootComplete); 5688755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu userToLoadAfterBootComplete = null; 5698755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu } 5708755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu } 5718de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5728de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Adds the missed call notification on startup if there are unread missed calls. 5738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 5748d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad @Override 5758755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public void reloadFromDatabase(final CallerInfoLookupHelper callerInfoLookupHelper, 5768755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu CallInfoFactory callInfoFactory, final UserHandle userHandle) { 577a993094840386163e9c2aa65a05e14b49d122318Tony Mak Log.d(this, "reloadFromDatabase()..."); 5788755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu if (TelecomSystem.getInstance() == null || !TelecomSystem.getInstance().isBootComplete()) { 5798755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu Log.i(this, "Boot not yet complete -- call log db may not be available. Deferring " + 5808755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu "loading until boot complete."); 5818755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu userToLoadAfterBootComplete = userHandle; 5828755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu return; 5838755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu } 5848de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5858de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // instantiate query handler 5868de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad AsyncQueryHandler queryHandler = new AsyncQueryHandler(mContext.getContentResolver()) { 5878de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad @Override 5888de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 5898de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(MissedCallNotifierImpl.this, "onQueryComplete()..."); 5908de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (cursor != null) { 5918de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad try { 592a993094840386163e9c2aa65a05e14b49d122318Tony Mak mMissedCallCounts.remove(userHandle); 5938de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad while (cursor.moveToNext()) { 5948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Get data about the missed call from the cursor 5958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final String handleString = cursor.getString(CALL_LOG_COLUMN_NUMBER); 5968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final int presentation = 5978de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad cursor.getInt(CALL_LOG_COLUMN_NUMBER_PRESENTATION); 5988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final long date = cursor.getLong(CALL_LOG_COLUMN_DATE); 5998de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 6008de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final Uri handle; 6018de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (presentation != Calls.PRESENTATION_ALLOWED 6028de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad || TextUtils.isEmpty(handleString)) { 6038de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handle = null; 6048de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 6058de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(handleString) ? 6068de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, 6078de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handleString, null); 6088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 6108755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu callerInfoLookupHelper.startLookup(handle, 6118755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu new CallerInfoLookupHelper.OnQueryCompleteListener() { 6128755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu @Override 6138755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public void onCallerInfoQueryComplete(Uri queryHandle, 6148755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu CallerInfo info) { 6158755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu if (!Objects.equals(queryHandle, handle)) { 6168755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu Log.w(MissedCallNotifierImpl.this, 6178755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu "CallerInfo query returned with " + 6188755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu "different handle."); 6198755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu return; 6208755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu } 6218755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu if (info.contactDisplayPhotoUri == null) { 6228755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu // If there is no photo, just show the notification. 6238755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu CallInfo callInfo = callInfoFactory.makeCallInfo( 6248755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu info, null, handle, date); 6258755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu showMissedCallNotification(callInfo, userHandle); 6268755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu } 6278755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu } 6288755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu 6298755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu @Override 6308755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu public void onContactPhotoQueryComplete(Uri queryHandle, 6318755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu CallerInfo info) { 6328755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu if (!Objects.equals(queryHandle, handle)) { 6338755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu Log.w(MissedCallNotifierImpl.this, 6348755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu "CallerInfo query for photo returned " + 6358755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu "with different handle."); 6368755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu return; 6378755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu } 6388755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu CallInfo callInfo = callInfoFactory.makeCallInfo( 6398755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu info, null, handle, date); 6408755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu showMissedCallNotification(callInfo, userHandle); 6418755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu } 6428d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad } 6438755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu ); 6448de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6458de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } finally { 6468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad cursor.close(); 6478de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6508de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad }; 6518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 6528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // setup query spec, look for all Missed calls that are new. 653a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri callsUri = 654a993094840386163e9c2aa65a05e14b49d122318Tony Mak ContentProvider.maybeAddUserId(Calls.CONTENT_URI, userHandle.getIdentifier()); 6558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // start the query 656a993094840386163e9c2aa65a05e14b49d122318Tony Mak queryHandler.startQuery(0, null, callsUri, CALL_LOG_PROJECTION, 6578755e29fd54403b404b4940d3dccebf83a8acbcfHall Liu CALL_LOG_WHERE_CLAUSE, null, Calls.DEFAULT_SORT_ORDER); 6588de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 659a993094840386163e9c2aa65a05e14b49d122318Tony Mak 660a993094840386163e9c2aa65a05e14b49d122318Tony Mak @Override 661a993094840386163e9c2aa65a05e14b49d122318Tony Mak public void setCurrentUserHandle(UserHandle currentUserHandle) { 662a993094840386163e9c2aa65a05e14b49d122318Tony Mak mCurrentUserHandle = currentUserHandle; 663a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 664a993094840386163e9c2aa65a05e14b49d122318Tony Mak 665a993094840386163e9c2aa65a05e14b49d122318Tony Mak private Context getContextForUser(UserHandle user) { 666a993094840386163e9c2aa65a05e14b49d122318Tony Mak try { 667a993094840386163e9c2aa65a05e14b49d122318Tony Mak return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user); 668a993094840386163e9c2aa65a05e14b49d122318Tony Mak } catch (NameNotFoundException e) { 669a993094840386163e9c2aa65a05e14b49d122318Tony Mak // Default to mContext, not finding the package system is running as is unlikely. 670a993094840386163e9c2aa65a05e14b49d122318Tony Mak return mContext; 671a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 672a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 6738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad} 674