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