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