1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dialer.interactions;
18 
19 import static android.Manifest.permission.READ_CONTACTS;
20 import static android.Manifest.permission.WRITE_CONTACTS;
21 
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.database.Cursor;
26 import android.net.Uri;
27 import android.provider.ContactsContract.PhoneLookup;
28 import android.provider.ContactsContract.PinnedPositions;
29 import android.text.TextUtils;
30 import com.android.dialer.util.PermissionsUtil;
31 
32 /**
33  * This broadcast receiver is used to listen to outgoing calls and undemote formerly demoted
34  * contacts if a phone call is made to a phone number belonging to that contact.
35  *
36  * <p>NOTE This doesn't work for corp contacts.
37  */
38 public class UndemoteOutgoingCallReceiver extends BroadcastReceiver {
39 
40   private static final long NO_CONTACT_FOUND = -1;
41 
42   @Override
onReceive(final Context context, Intent intent)43   public void onReceive(final Context context, Intent intent) {
44     if (!PermissionsUtil.hasPermission(context, READ_CONTACTS)
45         || !PermissionsUtil.hasPermission(context, WRITE_CONTACTS)) {
46       return;
47     }
48     if (intent != null && Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) {
49       final String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
50       if (TextUtils.isEmpty(number)) {
51         return;
52       }
53       new Thread() {
54         @Override
55         public void run() {
56           final long id = getContactIdFromPhoneNumber(context, number);
57           if (id != NO_CONTACT_FOUND) {
58             undemoteContactWithId(context, id);
59           }
60         }
61       }.start();
62     }
63   }
64 
undemoteContactWithId(Context context, long id)65   private void undemoteContactWithId(Context context, long id) {
66     // If the contact is not demoted, this will not do anything. Otherwise, it will
67     // restore it to an unpinned position. If it was a frequently called contact, it will
68     // show up once again show up on the favorites screen.
69     if (PermissionsUtil.hasPermission(context, WRITE_CONTACTS)) {
70       try {
71         PinnedPositions.undemote(context.getContentResolver(), id);
72       } catch (SecurityException e) {
73         // Just in case
74       }
75     }
76   }
77 
getContactIdFromPhoneNumber(Context context, String number)78   private long getContactIdFromPhoneNumber(Context context, String number) {
79     if (!PermissionsUtil.hasPermission(context, READ_CONTACTS)) {
80       return NO_CONTACT_FOUND;
81     }
82     final Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
83     final Cursor cursor;
84     try {
85       cursor =
86           context
87               .getContentResolver()
88               .query(contactUri, new String[] {PhoneLookup._ID}, null, null, null);
89     } catch (SecurityException e) {
90       // Just in case
91       return NO_CONTACT_FOUND;
92     }
93     if (cursor == null) {
94       return NO_CONTACT_FOUND;
95     }
96     try {
97       if (cursor.moveToFirst()) {
98         final long id = cursor.getLong(0);
99         return id;
100       } else {
101         return NO_CONTACT_FOUND;
102       }
103     } finally {
104       cursor.close();
105     }
106   }
107 }
108