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