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; 22a993094840386163e9c2aa65a05e14b49d122318Tony Makimport android.content.ContentProvider; 23a993094840386163e9c2aa65a05e14b49d122318Tony Makimport android.content.pm.PackageManager.NameNotFoundException; 24a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Logging.Runnable; 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; 317c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liuimport com.android.server.telecom.DefaultDialerCache; 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; 57a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Log; 588de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.telecom.PhoneAccount; 598de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.telephony.PhoneNumberUtils; 60c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunnimport android.telephony.TelephonyManager; 618de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.text.BidiFormatter; 628de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.text.TextDirectionHeuristics; 638de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awadimport android.text.TextUtils; 648de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 659e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Changimport com.android.internal.telephony.CallerInfo; 669e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang 6741045b499a47c00459986c96bbbb28ffee2cbefcBryce Leeimport java.lang.Override; 6841045b499a47c00459986c96bbbb28ffee2cbefcBryce Leeimport java.lang.String; 6939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepalimport java.util.List; 70c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunnimport java.util.Locale; 713037ac6f171b6a3627494bb10042ab7adb34366aHall Liuimport java.util.Objects; 72a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.ConcurrentHashMap; 73a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.ConcurrentMap; 74a993094840386163e9c2aa65a05e14b49d122318Tony Makimport java.util.concurrent.atomic.AtomicInteger; 7541045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad// TODO: Needed for move to system service: import com.android.internal.R; 778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad/** 798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates a notification for calls that the user missed (neither answered nor rejected). 808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 818de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * TODO: Make TelephonyManager.clearMissedCalls call into this class. 828de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 838d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadpublic class MissedCallNotifierImpl extends CallsManagerListenerBase implements MissedCallNotifier { 848de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 85a993094840386163e9c2aa65a05e14b49d122318Tony Mak public interface MissedCallNotifierImplFactory { 86a993094840386163e9c2aa65a05e14b49d122318Tony Mak MissedCallNotifier makeMissedCallNotifierImpl(Context context, 877c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu PhoneAccountRegistrar phoneAccountRegistrar, 887c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu DefaultDialerCache defaultDialerCache); 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 1133037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private static final String CALL_LOG_WHERE_CLAUSE = "type=" + Calls.MISSED_TYPE + 1143037ac6f171b6a3627494bb10042ab7adb34366aHall Liu " AND new=1" + 1153037ac6f171b6a3627494bb10042ab7adb34366aHall Liu " AND is_read=0"; 1163037ac6f171b6a3627494bb10042ab7adb34366aHall Liu 1173037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_ID = 0; 1183037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_NUMBER = 1; 1193037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_NUMBER_PRESENTATION = 2; 1203037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_DATE = 3; 1213037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_DURATION = 4; 1223037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public static final int CALL_LOG_COLUMN_TYPE = 5; 1238de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private static final int MISSED_CALL_NOTIFICATION_ID = 1; 125ca766d28471cc41d9ef33682a41edd1f99448d42Tyler Gunn private static final String NOTIFICATION_TAG = MissedCallNotifierImpl.class.getSimpleName(); 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; 1317c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu private final DefaultDialerCache mDefaultDialerCache; 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 1397c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu public MissedCallNotifierImpl(Context context, PhoneAccountRegistrar phoneAccountRegistrar, 1407c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu DefaultDialerCache defaultDialerCache) { 1417c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu this(context, phoneAccountRegistrar, defaultDialerCache, 1427c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu new DefaultNotificationBuilderFactory()); 143a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu } 144a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu 145a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu public MissedCallNotifierImpl(Context context, 146a993094840386163e9c2aa65a05e14b49d122318Tony Mak PhoneAccountRegistrar phoneAccountRegistrar, 1477c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu DefaultDialerCache defaultDialerCache, 148a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu NotificationBuilderFactory notificationBuilderFactory) { 1498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mContext = context; 150a993094840386163e9c2aa65a05e14b49d122318Tony Mak mPhoneAccountRegistrar = phoneAccountRegistrar; 1518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mNotificationManager = 1528de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 1537c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu mDefaultDialerCache = defaultDialerCache; 15441045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 155a33c44b34eaed1ec2dd5c87e00e2c0865971b7d1Hall Liu mNotificationBuilderFactory = notificationBuilderFactory; 156a993094840386163e9c2aa65a05e14b49d122318Tony Mak mMissedCallCounts = new ConcurrentHashMap<>(); 1578de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 1588de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1598de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** Clears missed call notification and marks the call log's missed calls as read. */ 160226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee @Override 16139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal public void clearMissedCalls(UserHandle userHandle) { 16239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal // If the default dialer is showing the missed call notification then it will modify the 16339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal // call log and we don't have to do anything here. 16439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (!shouldManageNotificationThroughDefaultDialer(userHandle)) { 16539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal markMissedCallsAsRead(userHandle); 16639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 16739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal cancelMissedCallNotification(userHandle); 16839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 16939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 17039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private void markMissedCallsAsRead(final UserHandle userHandle) { 171f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger AsyncTask.execute(new Runnable("MCNI.mMCAR", null /*lock*/) { 1728de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad @Override 173e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger public void loggedRun() { 1748de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Clear the list of new missed calls from the call log. 1758de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad ContentValues values = new ContentValues(); 1768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad values.put(Calls.NEW, 0); 1778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad values.put(Calls.IS_READ, 1); 1788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad StringBuilder where = new StringBuilder(); 1798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(Calls.NEW); 1808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(" = 1 AND "); 1818de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(Calls.TYPE); 1828de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad where.append(" = ?"); 1830f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh try { 184a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri callsUri = ContentProvider 185a993094840386163e9c2aa65a05e14b49d122318Tony Mak .maybeAddUserId(Calls.CONTENT_URI, userHandle.getIdentifier()); 186a993094840386163e9c2aa65a05e14b49d122318Tony Mak mContext.getContentResolver().update(callsUri, values, 1870f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh where.toString(), new String[]{ Integer.toString(Calls. 1880f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh MISSED_TYPE) }); 1890f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh } catch (IllegalArgumentException e) { 1900f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh Log.w(this, "ContactsProvider update command failed", e); 1910f39c5571184dbd941a40781e6204630ec4f89ebShriram Ganesh } 1928de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 193e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger }.prepare()); 1948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 1958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 1968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 1973037ac6f171b6a3627494bb10042ab7adb34366aHall Liu * Returns the missed-call notification intent to send to the default dialer for the given user. 1983037ac6f171b6a3627494bb10042ab7adb34366aHall Liu * Note, the passed in userHandle is always the non-managed user for SIM calls (multi-user 19939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * calls). In this case we return the default dialer for the logged in user. This is never the 20039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * managed (work profile) dialer. 20139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * 20239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * For non-multi-user calls (3rd party phone accounts), the passed in userHandle is the user 20339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * handle of the phone account. This could be a managed user. In that case we return the default 20439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal * dialer for the given user which could be a managed (work profile) dialer. 20539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal */ 20639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private Intent getShowMissedCallIntentForDefaultDialer(UserHandle userHandle) { 2077c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu String dialerPackage = mDefaultDialerCache.getDefaultDialerApplication( 2087c9283261ad4fdbc5ebbb74257671388f9c758c7Hall Liu userHandle.getIdentifier()); 20939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (TextUtils.isEmpty(dialerPackage)) { 21039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return null; 21139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 21239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return new Intent(TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION) 21339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .setPackage(dialerPackage); 21439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 21539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 21639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal private boolean shouldManageNotificationThroughDefaultDialer(UserHandle userHandle) { 21739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Intent intent = getShowMissedCallIntentForDefaultDialer(userHandle); 21839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (intent == null) { 21939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return false; 22039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 22139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 2224d34c5bc9ba32cb03c34fdb4186e084e85af79cfSailesh Nepal List<ResolveInfo> receivers = mContext.getPackageManager() 2234d34c5bc9ba32cb03c34fdb4186e084e85af79cfSailesh Nepal .queryBroadcastReceiversAsUser(intent, 0, userHandle.getIdentifier()); 22439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return receivers.size() > 0; 22539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 22639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 2273037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private void sendNotificationThroughDefaultDialer(CallInfo callInfo, UserHandle userHandle) { 22839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal int count = mMissedCallCounts.get(userHandle).get(); 22939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Intent intent = getShowMissedCallIntentForDefaultDialer(userHandle) 23039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .setFlags(Intent.FLAG_RECEIVER_FOREGROUND) 2313d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu .putExtra(TelecomManager.EXTRA_CLEAR_MISSED_CALLS_INTENT, 2323d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu createClearMissedCallsPendingIntent(userHandle)) 23339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .putExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, count) 23439245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal .putExtra(TelecomManager.EXTRA_NOTIFICATION_PHONE_NUMBER, 2353037ac6f171b6a3627494bb10042ab7adb34366aHall Liu callInfo == null ? null : callInfo.getPhoneNumber()); 23639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 2373d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu if (count == 1 && callInfo != null) { 2383d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu final Uri handleUri = callInfo.getHandle(); 2393d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu String handle = handleUri == null ? null : handleUri.getSchemeSpecificPart(); 2403d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu 2413d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu if (!TextUtils.isEmpty(handle) && !TextUtils.equals(handle, 2423d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu mContext.getString(R.string.handle_restricted))) { 2433d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu intent.putExtra(TelecomManager.EXTRA_CALL_BACK_INTENT, 2443d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu createCallBackPendingIntent(handleUri, userHandle)); 2453d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu } 2463d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu } 2473d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu 2483d59c4bdd4f1c8c7a260280d1adfca0504b35841Wei Liu 24939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal Log.w(this, "Showing missed calls through default dialer."); 25039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal mContext.sendBroadcastAsUser(intent, userHandle, READ_PHONE_STATE); 25139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 25239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 25339245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal /** 2548de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Create a system notification for the missed call. 2558de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 2568de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param call The missed call. 2578de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 258226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee @Override 2593037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void showMissedCallNotification(@NonNull CallInfo callInfo) { 2603037ac6f171b6a3627494bb10042ab7adb34366aHall Liu final PhoneAccountHandle phoneAccountHandle = callInfo.getPhoneAccountHandle(); 261a993094840386163e9c2aa65a05e14b49d122318Tony Mak final PhoneAccount phoneAccount = 262a993094840386163e9c2aa65a05e14b49d122318Tony Mak mPhoneAccountRegistrar.getPhoneAccountUnchecked(phoneAccountHandle); 263a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle; 264a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (phoneAccount != null && 265a993094840386163e9c2aa65a05e14b49d122318Tony Mak phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) { 266a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle = mCurrentUserHandle; 267a993094840386163e9c2aa65a05e14b49d122318Tony Mak } else { 268a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle = phoneAccountHandle.getUserHandle(); 269a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 2703037ac6f171b6a3627494bb10042ab7adb34366aHall Liu showMissedCallNotification(callInfo, userHandle); 271a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 2728de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 2733037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private void showMissedCallNotification(@NonNull CallInfo callInfo, UserHandle userHandle) { 2743037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.i(this, "showMissedCallNotification()"); 2753cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0)); 2763cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak int missCallCounts = mMissedCallCounts.get(userHandle).incrementAndGet(); 277a993094840386163e9c2aa65a05e14b49d122318Tony Mak 27839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (shouldManageNotificationThroughDefaultDialer(userHandle)) { 2793037ac6f171b6a3627494bb10042ab7adb34366aHall Liu sendNotificationThroughDefaultDialer(callInfo, userHandle); 28039245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return; 28139245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 28239245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 2838de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final int titleResId; 2848de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final String expandedText; // The text in the notification's line 1 and 2. 2858de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 2868de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Display the first line of the notification: 2878de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // 1 missed call: <caller name || handle> 2888de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // More than 1 missed call: <number of calls> + "missed calls" 289a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (missCallCounts == 1) { 2903037ac6f171b6a3627494bb10042ab7adb34366aHall Liu expandedText = getNameForMissedCallNotification(callInfo); 2919e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang 2923037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallerInfo ci = callInfo.getCallerInfo(); 2939e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang if (ci != null && ci.userType == CallerInfo.USER_TYPE_WORK) { 2949e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang titleResId = R.string.notification_missedWorkCallTitle; 2959e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang } else { 2969e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang titleResId = R.string.notification_missedCallTitle; 2979e7f98ac892c6b88905e8971dfd7228c604c2f52Victor Chang } 2988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 2998de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad titleResId = R.string.notification_missedCallsTitle; 3008de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad expandedText = 301a993094840386163e9c2aa65a05e14b49d122318Tony Mak mContext.getString(R.string.notification_missedCallsMsg, missCallCounts); 3028de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3038de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3048fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Create a public viewable version of the notification, suitable for display when sensitive 3058fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // notification content is hidden. 306a993094840386163e9c2aa65a05e14b49d122318Tony Mak // We use user's context here to make sure notification is badged if it is a managed user. 307a993094840386163e9c2aa65a05e14b49d122318Tony Mak Context contextForUser = getContextForUser(userHandle); 308a993094840386163e9c2aa65a05e14b49d122318Tony Mak Notification.Builder publicBuilder = mNotificationBuilderFactory.getBuilder(contextForUser); 3098fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn publicBuilder.setSmallIcon(android.R.drawable.stat_notify_missed_call) 3108fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setColor(mContext.getResources().getColor(R.color.theme_color)) 3113037ac6f171b6a3627494bb10042ab7adb34366aHall Liu .setWhen(callInfo.getCreationTimeMillis()) 3122879d0b874c6ae7660da387750d4349b3053a595liheng.x.zhang .setShowWhen(true) 3138fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Show "Phone" for notification title. 3148fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setContentTitle(mContext.getText(R.string.userCallActivityLabel)) 3158fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Notification details shows that there are missed call(s), but does not reveal 3168fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // the missed caller information. 3178fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setContentText(mContext.getText(titleResId)) 318a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setContentIntent(createCallLogPendingIntent(userHandle)) 3198fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn .setAutoCancel(true) 320a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setDeleteIntent(createClearMissedCallsPendingIntent(userHandle)); 3218fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn 3228fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Create the notification suitable for display when sensitive information is showing. 323a993094840386163e9c2aa65a05e14b49d122318Tony Mak Notification.Builder builder = mNotificationBuilderFactory.getBuilder(contextForUser); 3248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setSmallIcon(android.R.drawable.stat_notify_missed_call) 3258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setColor(mContext.getResources().getColor(R.color.theme_color)) 3263037ac6f171b6a3627494bb10042ab7adb34366aHall Liu .setWhen(callInfo.getCreationTimeMillis()) 3272879d0b874c6ae7660da387750d4349b3053a595liheng.x.zhang .setShowWhen(true) 3288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setContentTitle(mContext.getText(titleResId)) 3298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setContentText(expandedText) 330a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setContentIntent(createCallLogPendingIntent(userHandle)) 3318de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad .setAutoCancel(true) 332a993094840386163e9c2aa65a05e14b49d122318Tony Mak .setDeleteIntent(createClearMissedCallsPendingIntent(userHandle)) 3338fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // Include a public version of the notification to be shown when the missed call 3348fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // notification is shown on the user's lock screen and they have chosen to hide 3358fd6d31d9faf4e5b0fd2397442cee1c505939f91Tyler Gunn // sensitive notification information. 336acc09c44870b58e3350086a78add37bbedccfce8Tyler Gunn .setPublicVersion(publicBuilder.build()) 3375f1672b92d70fd68f0e514185c0d2787c3a1b73dJulia Reynolds .setChannelId(NotificationChannelManager.CHANNEL_ID_MISSED_CALLS); 3388de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3393037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Uri handleUri = callInfo.getHandle(); 3403037ac6f171b6a3627494bb10042ab7adb34366aHall Liu String handle = callInfo.getHandleSchemeSpecificPart(); 3418de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3428de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Add additional actions when there is only 1 missed call, like call-back and SMS. 343a993094840386163e9c2aa65a05e14b49d122318Tony Mak if (missCallCounts == 1) { 3448de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(this, "Add actions with number %s.", Log.piiHandle(handle)); 3458de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (!TextUtils.isEmpty(handle) 3478de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad && !TextUtils.equals(handle, mContext.getString(R.string.handle_restricted))) { 348bbdd44c57736b256ce118ce230ec95a1d42f30a7Andrew Lee builder.addAction(R.drawable.ic_phone_24dp, 3498de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad mContext.getString(R.string.notification_missedCall_call_back), 350a993094840386163e9c2aa65a05e14b49d122318Tony Mak createCallBackPendingIntent(handleUri, userHandle)); 3518de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3523037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (canRespondViaSms(callInfo)) { 35335ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon builder.addAction(R.drawable.ic_message_24dp, 35435ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon mContext.getString(R.string.notification_missedCall_message), 355a993094840386163e9c2aa65a05e14b49d122318Tony Mak createSendSmsFromNotificationPendingIntent(handleUri, userHandle)); 35635ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon } 3578de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3588de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3593037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Bitmap photoIcon = callInfo.getCallerInfo() == null ? 3603037ac6f171b6a3627494bb10042ab7adb34366aHall Liu null : callInfo.getCallerInfo().cachedPhotoIcon; 3618de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (photoIcon != null) { 3628de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setLargeIcon(photoIcon); 3638de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 3643037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Drawable photo = callInfo.getCallerInfo() == null ? 3653037ac6f171b6a3627494bb10042ab7adb34366aHall Liu null : callInfo.getCallerInfo().cachedPhoto; 3668de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (photo != null && photo instanceof BitmapDrawable) { 3678de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad builder.setLargeIcon(((BitmapDrawable) photo).getBitmap()); 3688de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3698de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3708de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 3718de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(this, "Suppress actions. handle: %s, missedCalls: %d.", Log.piiHandle(handle), 372a993094840386163e9c2aa65a05e14b49d122318Tony Mak missCallCounts); 3738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3748de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3758de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Notification notification = builder.build(); 3768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad configureLedOnNotification(notification); 3778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 3783037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.i(this, "Adding missed call notification for %s.", Log.pii(callInfo.getHandle())); 379761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee long token = Binder.clearCallingIdentity(); 380761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee try { 381761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee mNotificationManager.notifyAsUser( 382ca766d28471cc41d9ef33682a41edd1f99448d42Tyler Gunn NOTIFICATION_TAG, MISSED_CALL_NOTIFICATION_ID, notification, userHandle); 383761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } finally { 384761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee Binder.restoreCallingIdentity(token); 385761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } 3868de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 3878de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 388a993094840386163e9c2aa65a05e14b49d122318Tony Mak 3898de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** Cancels the "missed call" notification. */ 390a993094840386163e9c2aa65a05e14b49d122318Tony Mak private void cancelMissedCallNotification(UserHandle userHandle) { 3918de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Reset the number of missed calls to 0. 3923cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.putIfAbsent(userHandle, new AtomicInteger(0)); 3933cf8d22b74e8bbcf953223e8c1259af1bffbc7cbTony Mak mMissedCallCounts.get(userHandle).set(0); 39441045b499a47c00459986c96bbbb28ffee2cbefcBryce Lee 39539245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal if (shouldManageNotificationThroughDefaultDialer(userHandle)) { 39639245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal sendNotificationThroughDefaultDialer(null, userHandle); 39739245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal return; 39839245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal } 39939245e75b0c5c9a4d9d95254e918ce7408df025eSailesh Nepal 400761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee long token = Binder.clearCallingIdentity(); 401761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee try { 402ca766d28471cc41d9ef33682a41edd1f99448d42Tyler Gunn mNotificationManager.cancelAsUser(NOTIFICATION_TAG, MISSED_CALL_NOTIFICATION_ID, 403ca766d28471cc41d9ef33682a41edd1f99448d42Tyler Gunn userHandle); 404761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } finally { 405761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee Binder.restoreCallingIdentity(token); 406761a63fe47526bd48d1649da33f7ef213fbb6207Anthony Lee } 4078de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 4108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Returns the name to use in the missed call notification. 4118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 4123037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private String getNameForMissedCallNotification(@NonNull CallInfo callInfo) { 4133037ac6f171b6a3627494bb10042ab7adb34366aHall Liu String handle = callInfo.getHandleSchemeSpecificPart(); 4143037ac6f171b6a3627494bb10042ab7adb34366aHall Liu String name = callInfo.getName(); 4158de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 416c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (!TextUtils.isEmpty(handle)) { 417c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn String formattedNumber = PhoneNumberUtils.formatNumber(handle, 418c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn getCurrentCountryIso(mContext)); 419c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 420c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // The formatted number will be null if there was a problem formatting it, but we can 421c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // default to using the unformatted number instead (e.g. a SIP URI may not be able to 422c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // be formatted. 423c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (!TextUtils.isEmpty(formattedNumber)) { 424c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn handle = formattedNumber; 425c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 426c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 427c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 4288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (!TextUtils.isEmpty(name) && TextUtils.isGraphic(name)) { 4298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return name; 4308de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else if (!TextUtils.isEmpty(handle)) { 4318de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // A handle should always be displayed LTR using {@link BidiFormatter} regardless of the 4328de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // content of the rest of the notification. 4338de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // TODO: Does this apply to SIP addresses? 4348de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad BidiFormatter bidiFormatter = BidiFormatter.getInstance(); 4358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return bidiFormatter.unicodeWrap(handle, TextDirectionHeuristics.LTR); 4368de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 4378de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Use "unknown" if the call is unidentifiable. 4388de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return mContext.getString(R.string.unknown); 4398de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4408de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4418de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4428de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 443c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * @return The ISO 3166-1 two letters country code of the country the user is in based on the 444c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * network location. If the network location does not exist, fall back to the locale 445c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn * setting. 446c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn */ 447c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn private String getCurrentCountryIso(Context context) { 448c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // Without framework function calls, this seems to be the most accurate location service 449c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn // we can rely on. 450c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn final TelephonyManager telephonyManager = 451c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 452c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn String countryIso = telephonyManager.getNetworkCountryIso().toUpperCase(); 453c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 454c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn if (countryIso == null) { 455c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn countryIso = Locale.getDefault().getCountry(); 456c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn Log.w(this, "No CountryDetector; falling back to countryIso based on locale: " 457c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn + countryIso); 458c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 459c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn return countryIso; 460c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn } 461c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn 462c8e528b8d5d630f65c841e37c2a23c7458386ad3Tyler Gunn /** 4638de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates a new pending intent that sends the user to the call log. 4648de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 4658de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @return The pending intent. 4668de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 467a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createCallLogPendingIntent(UserHandle userHandle) { 4688de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Intent intent = new Intent(Intent.ACTION_VIEW, null); 4698de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad intent.setType(Calls.CONTENT_TYPE); 4708de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4718de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(mContext); 4728de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad taskStackBuilder.addNextIntent(intent); 4738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 474a993094840386163e9c2aa65a05e14b49d122318Tony Mak return taskStackBuilder.getPendingIntent(0, 0, null, userHandle); 4758de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 4788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the missed call notification is cleared. 4798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 480a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createClearMissedCallsPendingIntent(UserHandle userHandle) { 4818de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 482a993094840386163e9c2aa65a05e14b49d122318Tony Mak TelecomBroadcastIntentProcessor.ACTION_CLEAR_MISSED_CALLS, null, userHandle); 4838de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4848de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4858de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 4868de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the user opts to "call back" from the missed call 4878de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * notification. 4888de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 4898de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param handle The handle to call back. 4908de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 491a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createCallBackPendingIntent(Uri handle, UserHandle userHandle) { 4928de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 493a993094840386163e9c2aa65a05e14b49d122318Tony Mak TelecomBroadcastIntentProcessor.ACTION_CALL_BACK_FROM_NOTIFICATION, handle, 494a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle); 4958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 4968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 4978de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 4988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates an intent to be invoked when the user opts to "send sms" from the missed call 4998de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * notification. 5008de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 501a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createSendSmsFromNotificationPendingIntent(Uri handle, 502a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle) { 5038de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad return createTelecomPendingIntent( 5048de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad TelecomBroadcastIntentProcessor.ACTION_SEND_SMS_FROM_NOTIFICATION, 505a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri.fromParts(Constants.SCHEME_SMSTO, handle.getSchemeSpecificPart(), null), 506a993094840386163e9c2aa65a05e14b49d122318Tony Mak userHandle); 5078de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5088de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Creates generic pending intent from the specified parameters to be received by 5118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * {@link TelecomBroadcastIntentProcessor}. 5128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * 5138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param action The intent action. 5148de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * @param data The intent data. 5158de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 516a993094840386163e9c2aa65a05e14b49d122318Tony Mak private PendingIntent createTelecomPendingIntent(String action, Uri data, 517a993094840386163e9c2aa65a05e14b49d122318Tony Mak UserHandle userHandle) { 518226ae567a63a3ae8dd5292b127d59abf107417f4Yorke Lee Intent intent = new Intent(action, data, mContext, TelecomBroadcastReceiver.class); 519a993094840386163e9c2aa65a05e14b49d122318Tony Mak intent.putExtra(TelecomBroadcastIntentProcessor.EXTRA_USERHANDLE, userHandle); 520e8b11f8edc4a684cab2d11426cfe465e66bdf18aHonggang Luo return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 5218de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5228de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5238de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Configures a notification to emit the blinky notification light. 5258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 5268de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad private void configureLedOnNotification(Notification notification) { 5278de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad notification.flags |= Notification.FLAG_SHOW_LIGHTS; 5288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad notification.defaults |= Notification.DEFAULT_LIGHTS; 5298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5308de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5313037ac6f171b6a3627494bb10042ab7adb34366aHall Liu private boolean canRespondViaSms(@NonNull CallInfo callInfo) { 53235ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon // Only allow respond-via-sms for "tel:" calls. 5333037ac6f171b6a3627494bb10042ab7adb34366aHall Liu return callInfo.getHandle() != null && 5343037ac6f171b6a3627494bb10042ab7adb34366aHall Liu PhoneAccount.SCHEME_TEL.equals(callInfo.getHandle().getScheme()); 53535ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon } 53635ed79788af4173ff1c86e16623c1bdf777b0f31Santos Cordon 5373037ac6f171b6a3627494bb10042ab7adb34366aHall Liu @Override 5383037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void reloadAfterBootComplete(final CallerInfoLookupHelper callerInfoLookupHelper, 5393037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallInfoFactory callInfoFactory) { 5403037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (userToLoadAfterBootComplete != null) { 5413037ac6f171b6a3627494bb10042ab7adb34366aHall Liu reloadFromDatabase(callerInfoLookupHelper, 5423037ac6f171b6a3627494bb10042ab7adb34366aHall Liu callInfoFactory, userToLoadAfterBootComplete); 5433037ac6f171b6a3627494bb10042ab7adb34366aHall Liu userToLoadAfterBootComplete = null; 5443037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 5453037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 5468de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad /** 5478de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad * Adds the missed call notification on startup if there are unread missed calls. 5488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad */ 5498d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad @Override 5503037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void reloadFromDatabase(final CallerInfoLookupHelper callerInfoLookupHelper, 5513037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallInfoFactory callInfoFactory, final UserHandle userHandle) { 552a993094840386163e9c2aa65a05e14b49d122318Tony Mak Log.d(this, "reloadFromDatabase()..."); 5533037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (TelecomSystem.getInstance() == null || !TelecomSystem.getInstance().isBootComplete()) { 5543037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.i(this, "Boot not yet complete -- call log db may not be available. Deferring " + 5553037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "loading until boot complete."); 5563037ac6f171b6a3627494bb10042ab7adb34366aHall Liu userToLoadAfterBootComplete = userHandle; 5573037ac6f171b6a3627494bb10042ab7adb34366aHall Liu return; 5583037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 5598de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5608de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // instantiate query handler 5618de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad AsyncQueryHandler queryHandler = new AsyncQueryHandler(mContext.getContentResolver()) { 5628de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad @Override 5638de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 5648de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.d(MissedCallNotifierImpl.this, "onQueryComplete()..."); 5658de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (cursor != null) { 5668de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad try { 567a993094840386163e9c2aa65a05e14b49d122318Tony Mak mMissedCallCounts.remove(userHandle); 5688de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad while (cursor.moveToNext()) { 5698de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // Get data about the missed call from the cursor 5708de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final String handleString = cursor.getString(CALL_LOG_COLUMN_NUMBER); 5718de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final int presentation = 5728de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad cursor.getInt(CALL_LOG_COLUMN_NUMBER_PRESENTATION); 5738de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final long date = cursor.getLong(CALL_LOG_COLUMN_DATE); 5748de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5758de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad final Uri handle; 5768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad if (presentation != Calls.PRESENTATION_ALLOWED 5778de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad || TextUtils.isEmpty(handleString)) { 5788de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handle = null; 5798de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } else { 5808de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(handleString) ? 5818de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, 5828de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad handleString, null); 5838de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 5848de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 5853037ac6f171b6a3627494bb10042ab7adb34366aHall Liu callerInfoLookupHelper.startLookup(handle, 5863037ac6f171b6a3627494bb10042ab7adb34366aHall Liu new CallerInfoLookupHelper.OnQueryCompleteListener() { 5873037ac6f171b6a3627494bb10042ab7adb34366aHall Liu @Override 5883037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void onCallerInfoQueryComplete(Uri queryHandle, 5893037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallerInfo info) { 5903037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (!Objects.equals(queryHandle, handle)) { 5913037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.w(MissedCallNotifierImpl.this, 5923037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "CallerInfo query returned with " + 5933037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "different handle."); 5943037ac6f171b6a3627494bb10042ab7adb34366aHall Liu return; 5953037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 596270f1237e4d3fff509e514225627517832699f58Hall Liu if (info == null || 597270f1237e4d3fff509e514225627517832699f58Hall Liu info.contactDisplayPhotoUri == null) { 598270f1237e4d3fff509e514225627517832699f58Hall Liu // If there is no photo or if the caller info is 599270f1237e4d3fff509e514225627517832699f58Hall Liu // null, just show the notification. 6003037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallInfo callInfo = callInfoFactory.makeCallInfo( 6013037ac6f171b6a3627494bb10042ab7adb34366aHall Liu info, null, handle, date); 6023037ac6f171b6a3627494bb10042ab7adb34366aHall Liu showMissedCallNotification(callInfo, userHandle); 6033037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6043037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6053037ac6f171b6a3627494bb10042ab7adb34366aHall Liu 6063037ac6f171b6a3627494bb10042ab7adb34366aHall Liu @Override 6073037ac6f171b6a3627494bb10042ab7adb34366aHall Liu public void onContactPhotoQueryComplete(Uri queryHandle, 6083037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallerInfo info) { 6093037ac6f171b6a3627494bb10042ab7adb34366aHall Liu if (!Objects.equals(queryHandle, handle)) { 6103037ac6f171b6a3627494bb10042ab7adb34366aHall Liu Log.w(MissedCallNotifierImpl.this, 6113037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "CallerInfo query for photo returned " + 6123037ac6f171b6a3627494bb10042ab7adb34366aHall Liu "with different handle."); 6133037ac6f171b6a3627494bb10042ab7adb34366aHall Liu return; 6143037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6153037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CallInfo callInfo = callInfoFactory.makeCallInfo( 6163037ac6f171b6a3627494bb10042ab7adb34366aHall Liu info, null, handle, date); 6173037ac6f171b6a3627494bb10042ab7adb34366aHall Liu showMissedCallNotification(callInfo, userHandle); 6183037ac6f171b6a3627494bb10042ab7adb34366aHall Liu } 6198d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad } 6203037ac6f171b6a3627494bb10042ab7adb34366aHall Liu ); 6218de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6228de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } finally { 6238de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad cursor.close(); 6248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6258de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6268de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 6278de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad }; 6288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad 6298de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // setup query spec, look for all Missed calls that are new. 630a993094840386163e9c2aa65a05e14b49d122318Tony Mak Uri callsUri = 631a993094840386163e9c2aa65a05e14b49d122318Tony Mak ContentProvider.maybeAddUserId(Calls.CONTENT_URI, userHandle.getIdentifier()); 6328de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad // start the query 633a993094840386163e9c2aa65a05e14b49d122318Tony Mak queryHandler.startQuery(0, null, callsUri, CALL_LOG_PROJECTION, 6343037ac6f171b6a3627494bb10042ab7adb34366aHall Liu CALL_LOG_WHERE_CLAUSE, null, Calls.DEFAULT_SORT_ORDER); 6358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad } 636a993094840386163e9c2aa65a05e14b49d122318Tony Mak 637a993094840386163e9c2aa65a05e14b49d122318Tony Mak @Override 638a993094840386163e9c2aa65a05e14b49d122318Tony Mak public void setCurrentUserHandle(UserHandle currentUserHandle) { 639a993094840386163e9c2aa65a05e14b49d122318Tony Mak mCurrentUserHandle = currentUserHandle; 640a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 641a993094840386163e9c2aa65a05e14b49d122318Tony Mak 642a993094840386163e9c2aa65a05e14b49d122318Tony Mak private Context getContextForUser(UserHandle user) { 643a993094840386163e9c2aa65a05e14b49d122318Tony Mak try { 644a993094840386163e9c2aa65a05e14b49d122318Tony Mak return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user); 645a993094840386163e9c2aa65a05e14b49d122318Tony Mak } catch (NameNotFoundException e) { 646a993094840386163e9c2aa65a05e14b49d122318Tony Mak // Default to mContext, not finding the package system is running as is unlikely. 647a993094840386163e9c2aa65a05e14b49d122318Tony Mak return mContext; 648a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 649a993094840386163e9c2aa65a05e14b49d122318Tony Mak } 6508de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad} 651