• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.voicedialer;
18 
19 import android.app.Activity;
20 import android.database.Cursor;
21 import android.database.DatabaseUtils;
22 import android.provider.ContactsContract.CommonDataKinds.Phone;
23 import android.provider.CallLog;
24 import android.util.Config;
25 import android.util.Log;
26 import java.io.BufferedReader;
27 import java.io.File;
28 import java.io.FileReader;
29 import java.io.IOException;
30 import java.util.ArrayList;
31 import java.util.List;
32 
33 
34 /**
35  * This class represents a person who may be called via the VoiceDialer app.
36  * The person has a name and a list of phones (home, mobile, work, other).
37  */
38 public class VoiceContact {
39     private static final String TAG = "VoiceContact";
40 
41     /**
42      * Corresponding row doesn't exist.
43      */
44     public static final long ID_UNDEFINED = -1;
45 
46     public final String mName;
47     public final long mContactId;
48     public final long mPrimaryId;
49     public final long mHomeId;
50     public final long mMobileId;
51     public final long mWorkId;
52     public final long mOtherId;
53 
54     /**
55      * Constructor.
56      *
57      * @param name person's name.
58      * @param contactId ID in person table.
59      * @param primaryId primary ID in phone table.
60      * @param homeId home ID in phone table.
61      * @param mobileId mobile ID in phone table.
62      * @param workId work ID in phone table.
63      * @param otherId other ID in phone table.
64      */
VoiceContact(String name, long contactId, long primaryId, long homeId, long mobileId, long workId,long otherId)65     private VoiceContact(String name, long contactId, long primaryId,
66             long homeId, long mobileId, long workId,long otherId) {
67         mName = name;
68         mContactId = contactId;
69         mPrimaryId = primaryId;
70         mHomeId = homeId;
71         mMobileId = mobileId;
72         mWorkId = workId;
73         mOtherId = otherId;
74     }
75 
76     @Override
hashCode()77     public int hashCode() {
78         final int LARGE_PRIME = 1610612741;
79         int hash = 0;
80         hash = LARGE_PRIME * (hash + (int)mContactId);
81         hash = LARGE_PRIME * (hash + (int)mPrimaryId);
82         hash = LARGE_PRIME * (hash + (int)mHomeId);
83         hash = LARGE_PRIME * (hash + (int)mMobileId);
84         hash = LARGE_PRIME * (hash + (int)mWorkId);
85         hash = LARGE_PRIME * (hash + (int)mOtherId);
86         return mName.hashCode() + hash;
87     }
88 
89     @Override
toString()90     public String toString() {
91         return "mName=" + mName
92                 + " mPersonId=" + mContactId
93                 + " mPrimaryId=" + mPrimaryId
94                 + " mHomeId=" + mHomeId
95                 + " mMobileId=" + mMobileId
96                 + " mWorkId=" + mWorkId
97                 + " mOtherId=" + mOtherId;
98     }
99 
100     /**
101      * @param activity The VoiceDialerActivity instance.
102      * @return List of {@link VoiceContact} from
103      * the contact list content provider.
104      */
getVoiceContacts(Activity activity)105     public static List<VoiceContact> getVoiceContacts(Activity activity) {
106         if (Config.LOGD) Log.d(TAG, "VoiceContact.getVoiceContacts");
107 
108         List<VoiceContact> contacts = new ArrayList<VoiceContact>();
109 
110         String[] phonesProjection = new String[] {
111             Phone._ID,
112             Phone.TYPE,
113             Phone.IS_PRIMARY,
114             // TODO: handle type != 0,1,2, and use LABEL
115             Phone.LABEL,
116             Phone.DISPLAY_NAME,
117             Phone.CONTACT_ID,
118         };
119 
120         // Table is sorted by number of times contacted and name. If we cannot fit all contacts
121         // in the recognizer, we will at least have the commonly used ones.
122         Cursor cursor = activity.getContentResolver().query(
123                 Phone.CONTENT_URI, phonesProjection,
124                 Phone.NUMBER + " NOT NULL", null,
125                 Phone.LAST_TIME_CONTACTED + " DESC, " + Phone.DISPLAY_NAME + " ASC");
126 
127         final int phoneIdColumn = cursor.getColumnIndexOrThrow(Phone._ID);
128         final int typeColumn = cursor.getColumnIndexOrThrow(Phone.TYPE);
129         final int isPrimaryColumn = cursor.getColumnIndexOrThrow(Phone.IS_PRIMARY);
130         final int labelColumn = cursor.getColumnIndexOrThrow(Phone.LABEL);
131         final int nameColumn = cursor.getColumnIndexOrThrow(Phone.DISPLAY_NAME);
132         final int personIdColumn = cursor.getColumnIndexOrThrow(Phone.CONTACT_ID);
133 
134         // pieces of next VoiceContact
135         String name = null;
136         long personId = ID_UNDEFINED;
137         long primaryId = ID_UNDEFINED;
138         long homeId = ID_UNDEFINED;
139         long mobileId = ID_UNDEFINED;
140         long workId = ID_UNDEFINED;
141         long otherId = ID_UNDEFINED;
142 
143         // loop over phone table
144         for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
145             long phoneIdAtCursor = cursor.getLong(phoneIdColumn);
146             int typeAtCursor = cursor.getInt(typeColumn);
147             long isPrimaryAtCursor = cursor.getLong(isPrimaryColumn);
148             String labelAtCursor = cursor.getString(labelColumn);
149             String nameAtCursor = cursor.getString(nameColumn);
150             long personIdAtCursor = cursor.getLong(personIdColumn);
151 
152             /*
153             if (Config.LOGD) {
154                 Log.d(TAG, "phoneId=" + phoneIdAtCursor
155                         + " type=" + typeAtCursor
156                         + " isPrimary=" + isPrimaryAtCursor
157                         + " label=" + labelAtCursor
158                         + " name=" + nameAtCursor
159                         + " personId=" + personIdAtCursor
160                         );
161             }
162             */
163 
164             // encountered a new name, so generate current VoiceContact
165             if (name != null && !name.equals(nameAtCursor)) {
166                 contacts.add(new VoiceContact(name, personId, primaryId,
167                         homeId, mobileId, workId, otherId));
168                 name = null;
169             }
170 
171             // start accumulating pieces for a new VoiceContact
172             if (name == null) {
173                 name = nameAtCursor;
174                 personId = personIdAtCursor;
175                 primaryId = ID_UNDEFINED;
176                 homeId = ID_UNDEFINED;
177                 mobileId = ID_UNDEFINED;
178                 workId = ID_UNDEFINED;
179                 otherId = ID_UNDEFINED;
180             }
181 
182             // if labeled, then patch to HOME/MOBILE/WORK/OTHER
183             if (typeAtCursor == Phone.TYPE_CUSTOM &&
184                     labelAtCursor != null) {
185                 String label = labelAtCursor.toLowerCase();
186                 if (label.contains("home") || label.contains("house")) {
187                     typeAtCursor = Phone.TYPE_HOME;
188                 }
189                 else if (label.contains("mobile") || label.contains("cell")) {
190                     typeAtCursor = Phone.TYPE_MOBILE;
191                 }
192                 else if (label.contains("work") || label.contains("office")) {
193                     typeAtCursor = Phone.TYPE_WORK;
194                 }
195                 else if (label.contains("other")) {
196                     typeAtCursor = Phone.TYPE_OTHER;
197                 }
198             }
199 
200             // save the home, mobile, or work phone id
201             switch (typeAtCursor) {
202                 case Phone.TYPE_HOME:
203                     homeId = phoneIdAtCursor;
204                     if (isPrimaryAtCursor != 0) {
205                         primaryId = phoneIdAtCursor;
206                     }
207                     break;
208                 case Phone.TYPE_MOBILE:
209                     mobileId = phoneIdAtCursor;
210                     if (isPrimaryAtCursor != 0) {
211                         primaryId = phoneIdAtCursor;
212                     }
213                     break;
214                 case Phone.TYPE_WORK:
215                     workId = phoneIdAtCursor;
216                     if (isPrimaryAtCursor != 0) {
217                         primaryId = phoneIdAtCursor;
218                     }
219                     break;
220                 case Phone.TYPE_OTHER:
221                     otherId = phoneIdAtCursor;
222                     if (isPrimaryAtCursor != 0) {
223                         primaryId = phoneIdAtCursor;
224                     }
225                     break;
226             }
227         }
228 
229         // generate the last VoiceContact
230         if (name != null) {
231             contacts.add(new VoiceContact(name, personId, primaryId,
232                             homeId, mobileId, workId, otherId));
233         }
234 
235         // clean up cursor
236         cursor.close();
237 
238         if (Config.LOGD) Log.d(TAG, "VoiceContact.getVoiceContacts " + contacts.size());
239 
240         return contacts;
241     }
242 
243     /**
244      * @param contactsFile File containing a list of names,
245      * one per line.
246      * @return a List of {@link VoiceContact} in a File.
247      */
getVoiceContactsFromFile(File contactsFile)248     public static List<VoiceContact> getVoiceContactsFromFile(File contactsFile) {
249         if (Config.LOGD) Log.d(TAG, "getVoiceContactsFromFile " + contactsFile);
250 
251         List<VoiceContact> contacts = new ArrayList<VoiceContact>();
252 
253         // read from a file
254         BufferedReader br = null;
255         try {
256             br = new BufferedReader(new FileReader(contactsFile), 8192);
257             String name;
258             for (int id = 1; (name = br.readLine()) != null; id++) {
259                 contacts.add(new VoiceContact(name, id, ID_UNDEFINED,
260                         ID_UNDEFINED, ID_UNDEFINED, ID_UNDEFINED, ID_UNDEFINED));
261             }
262         }
263         catch (IOException e) {
264             if (Config.LOGD) Log.d(TAG, "getVoiceContactsFromFile failed " + e);
265         }
266         finally {
267             try {
268                 br.close();
269             } catch (IOException e) {
270                 if (Config.LOGD) Log.d(TAG, "getVoiceContactsFromFile failed during close " + e);
271             }
272         }
273 
274         if (Config.LOGD) Log.d(TAG, "getVoiceContactsFromFile " + contacts.size());
275 
276         return contacts;
277     }
278 
279     /**
280      * @param activity The VoiceDialerActivity instance.
281      * @return String of last number dialed.
282      */
redialNumber(Activity activity)283     public static String redialNumber(Activity activity) {
284         Cursor cursor = activity.getContentResolver().query(
285                 CallLog.Calls.CONTENT_URI,
286                 new String[] { CallLog.Calls.NUMBER },
287                 CallLog.Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE,
288                 null,
289                 CallLog.Calls.DEFAULT_SORT_ORDER + " LIMIT 1");
290         String number = null;
291         if (cursor.getCount() >= 1) {
292             cursor.moveToNext();
293             int column = cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER);
294             number = cursor.getString(column);
295         }
296         cursor.close();
297 
298         if (Config.LOGD) Log.d(TAG, "redialNumber " + number);
299 
300         return number;
301     }
302 
303 }
304