1 /* 2 * Copyright (C) 2006 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 android.provider; 18 19 import com.android.internal.telephony.CallerInfo; 20 import com.android.internal.telephony.Connection; 21 22 import android.content.ContentResolver; 23 import android.content.ContentValues; 24 import android.content.Context; 25 import android.database.Cursor; 26 import android.net.Uri; 27 import android.text.TextUtils; 28 29 /** 30 * The CallLog provider contains information about placed and received calls. 31 */ 32 public class CallLog { 33 public static final String AUTHORITY = "call_log"; 34 35 /** 36 * The content:// style URL for this provider 37 */ 38 public static final Uri CONTENT_URI = 39 Uri.parse("content://" + AUTHORITY); 40 41 /** 42 * Contains the recent calls. 43 */ 44 public static class Calls implements BaseColumns { 45 /** 46 * The content:// style URL for this table 47 */ 48 public static final Uri CONTENT_URI = 49 Uri.parse("content://call_log/calls"); 50 51 /** 52 * The content:// style URL for filtering this table on phone numbers 53 */ 54 public static final Uri CONTENT_FILTER_URI = 55 Uri.parse("content://call_log/calls/filter"); 56 57 /** 58 * The default sort order for this table 59 */ 60 public static final String DEFAULT_SORT_ORDER = "date DESC"; 61 62 /** 63 * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI} 64 * providing a directory of calls. 65 */ 66 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls"; 67 68 /** 69 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single 70 * call. 71 */ 72 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls"; 73 74 /** 75 * The type of the call (incoming, outgoing or missed). 76 * <P>Type: INTEGER (int)</P> 77 */ 78 public static final String TYPE = "type"; 79 80 public static final int INCOMING_TYPE = 1; 81 public static final int OUTGOING_TYPE = 2; 82 public static final int MISSED_TYPE = 3; 83 84 /** 85 * The phone number as the user entered it. 86 * <P>Type: TEXT</P> 87 */ 88 public static final String NUMBER = "number"; 89 90 /** 91 * The date the call occured, in milliseconds since the epoch 92 * <P>Type: INTEGER (long)</P> 93 */ 94 public static final String DATE = "date"; 95 96 /** 97 * The duration of the call in seconds 98 * <P>Type: INTEGER (long)</P> 99 */ 100 public static final String DURATION = "duration"; 101 102 /** 103 * Whether or not the call has been acknowledged 104 * <P>Type: INTEGER (boolean)</P> 105 */ 106 public static final String NEW = "new"; 107 108 /** 109 * The cached name associated with the phone number, if it exists. 110 * This value is not guaranteed to be current, if the contact information 111 * associated with this number has changed. 112 * <P>Type: TEXT</P> 113 */ 114 public static final String CACHED_NAME = "name"; 115 116 /** 117 * The cached number type (Home, Work, etc) associated with the 118 * phone number, if it exists. 119 * This value is not guaranteed to be current, if the contact information 120 * associated with this number has changed. 121 * <P>Type: INTEGER</P> 122 */ 123 public static final String CACHED_NUMBER_TYPE = "numbertype"; 124 125 /** 126 * The cached number label, for a custom number type, associated with the 127 * phone number, if it exists. 128 * This value is not guaranteed to be current, if the contact information 129 * associated with this number has changed. 130 * <P>Type: TEXT</P> 131 */ 132 public static final String CACHED_NUMBER_LABEL = "numberlabel"; 133 134 /** 135 * Adds a call to the call log. 136 * 137 * @param ci the CallerInfo object to get the target contact from. Can be null 138 * if the contact is unknown. 139 * @param context the context used to get the ContentResolver 140 * @param number the phone number to be added to the calls db 141 * @param presentation the number presenting rules set by the network for 142 * "allowed", "payphone", "restricted" or "unknown" 143 * @param callType enumerated values for "incoming", "outgoing", or "missed" 144 * @param start time stamp for the call in milliseconds 145 * @param duration call duration in seconds 146 * 147 * {@hide} 148 */ addCall(CallerInfo ci, Context context, String number, int presentation, int callType, long start, int duration)149 public static Uri addCall(CallerInfo ci, Context context, String number, 150 int presentation, int callType, long start, int duration) { 151 final ContentResolver resolver = context.getContentResolver(); 152 153 // If this is a private number then set the number to Private, otherwise check 154 // if the number field is empty and set the number to Unavailable 155 if (presentation == Connection.PRESENTATION_RESTRICTED) { 156 number = CallerInfo.PRIVATE_NUMBER; 157 if (ci != null) ci.name = ""; 158 } else if (presentation == Connection.PRESENTATION_PAYPHONE) { 159 number = CallerInfo.PAYPHONE_NUMBER; 160 if (ci != null) ci.name = ""; 161 } else if (TextUtils.isEmpty(number) 162 || presentation == Connection.PRESENTATION_UNKNOWN) { 163 number = CallerInfo.UNKNOWN_NUMBER; 164 if (ci != null) ci.name = ""; 165 } 166 167 ContentValues values = new ContentValues(5); 168 169 values.put(NUMBER, number); 170 values.put(TYPE, Integer.valueOf(callType)); 171 values.put(DATE, Long.valueOf(start)); 172 values.put(DURATION, Long.valueOf(duration)); 173 values.put(NEW, Integer.valueOf(1)); 174 if (ci != null) { 175 values.put(CACHED_NAME, ci.name); 176 values.put(CACHED_NUMBER_TYPE, ci.numberType); 177 values.put(CACHED_NUMBER_LABEL, ci.numberLabel); 178 } 179 180 if ((ci != null) && (ci.person_id > 0)) { 181 ContactsContract.Contacts.markAsContacted(resolver, ci.person_id); 182 } 183 184 Uri result = resolver.insert(CONTENT_URI, values); 185 186 removeExpiredEntries(context); 187 188 return result; 189 } 190 191 /** 192 * Query the call log database for the last dialed number. 193 * @param context Used to get the content resolver. 194 * @return The last phone number dialed (outgoing) or an empty 195 * string if none exist yet. 196 */ getLastOutgoingCall(Context context)197 public static String getLastOutgoingCall(Context context) { 198 final ContentResolver resolver = context.getContentResolver(); 199 Cursor c = null; 200 try { 201 c = resolver.query( 202 CONTENT_URI, 203 new String[] {NUMBER}, 204 TYPE + " = " + OUTGOING_TYPE, 205 null, 206 DEFAULT_SORT_ORDER + " LIMIT 1"); 207 if (c == null || !c.moveToFirst()) { 208 return ""; 209 } 210 return c.getString(0); 211 } finally { 212 if (c != null) c.close(); 213 } 214 } 215 removeExpiredEntries(Context context)216 private static void removeExpiredEntries(Context context) { 217 final ContentResolver resolver = context.getContentResolver(); 218 resolver.delete(CONTENT_URI, "_id IN " + 219 "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER 220 + " LIMIT -1 OFFSET 500)", null); 221 } 222 } 223 } 224