CallLogProvider.java revision 9978b26dd17bb2b20b91101f1e4682604336b5f6
1e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov/* 2e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * Copyright (C) 2009 The Android Open Source Project 3e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * 4e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 5e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * you may not use this file except in compliance with the License. 6e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * You may obtain a copy of the License at 7e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * 8e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 9e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * 10e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 11e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 12e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * See the License for the specific language governing permissions and 14e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * limitations under the License 15e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov */ 16e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 17e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovpackage com.android.providers.contacts; 18e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 1900e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjeeimport static com.android.providers.contacts.util.DbQueryUtils.checkForSupportedColumns; 20aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjeeimport static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause; 21aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjeeimport static com.android.providers.contacts.util.DbQueryUtils.getInequalityClause; 2200e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee 23b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikovimport com.android.providers.contacts.ContactsDatabaseHelper.Tables; 24aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjeeimport com.android.providers.contacts.util.SelectionBuilder; 25aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerdaimport com.google.common.annotations.VisibleForTesting; 26e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 27e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.content.ContentProvider; 28e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.content.ContentUris; 29e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.content.ContentValues; 30e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.content.Context; 31e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.content.UriMatcher; 32e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.database.Cursor; 33e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.database.DatabaseUtils; 34e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.database.sqlite.SQLiteDatabase; 35e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.database.sqlite.SQLiteQueryBuilder; 36e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.net.Uri; 37e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.CallLog; 38e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport android.provider.CallLog.Calls; 39663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onukiimport android.util.Log; 40e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 41e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovimport java.util.HashMap; 42e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 43e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov/** 44e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov * Call log content provider. 45e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov */ 46e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikovpublic class CallLogProvider extends ContentProvider { 47aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee /** Selection clause to use to exclude voicemail records. */ 48aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private static final String EXCLUDE_VOICEMAIL_SELECTION = getInequalityClause( 499978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda Calls.TYPE, Calls.VOICEMAIL_TYPE); 50aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 51e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private static final int CALLS = 1; 52e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 53e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private static final int CALLS_ID = 2; 54e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 55e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private static final int CALLS_FILTER = 3; 56e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 57e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); 58e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov static { 59e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sURIMatcher.addURI(CallLog.AUTHORITY, "calls", CALLS); 60e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sURIMatcher.addURI(CallLog.AUTHORITY, "calls/#", CALLS_ID); 61e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sURIMatcher.addURI(CallLog.AUTHORITY, "calls/filter/*", CALLS_FILTER); 62e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 63e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 64e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private static final HashMap<String, String> sCallsProjectionMap; 65e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov static { 66e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 67e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov // Calls projection map 68e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap = new HashMap<String, String>(); 69e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls._ID, Calls._ID); 70e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls.NUMBER, Calls.NUMBER); 71e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls.DATE, Calls.DATE); 72e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls.DURATION, Calls.DURATION); 73e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls.TYPE, Calls.TYPE); 74e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls.NEW, Calls.NEW); 7559f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee sCallsProjectionMap.put(Calls.VOICEMAIL_URI, Calls.VOICEMAIL_URI); 76b2197b235e3d96e7f70c24d548b7dac52dab88d8Flavio Lerda sCallsProjectionMap.put(Calls.IS_READ, Calls.IS_READ); 77e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls.CACHED_NAME, Calls.CACHED_NAME); 78e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls.CACHED_NUMBER_TYPE, Calls.CACHED_NUMBER_TYPE); 79e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov sCallsProjectionMap.put(Calls.CACHED_NUMBER_LABEL, Calls.CACHED_NUMBER_LABEL); 802530512f639c4979fd7371c7dd25dd67e8118124Bai Tao sCallsProjectionMap.put(Calls.COUNTRY_ISO, Calls.COUNTRY_ISO); 81aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda sCallsProjectionMap.put(Calls.GEOCODED_LOCATION, Calls.GEOCODED_LOCATION); 827a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda sCallsProjectionMap.put(Calls.CACHED_LOOKUP_URI, Calls.CACHED_LOOKUP_URI); 837a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda sCallsProjectionMap.put(Calls.CACHED_MATCHED_NUMBER, Calls.CACHED_MATCHED_NUMBER); 847a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda sCallsProjectionMap.put(Calls.CACHED_NORMALIZED_NUMBER, Calls.CACHED_NORMALIZED_NUMBER); 857a24e1c1476b57a6268de8d57e5ef4a2d5f46794Flavio Lerda sCallsProjectionMap.put(Calls.CACHED_PHOTO_ID, Calls.CACHED_PHOTO_ID); 8613ed28505ed1af4f0b4a6297c4c6840d91f10c8cFlavio Lerda sCallsProjectionMap.put(Calls.CACHED_FORMATTED_NUMBER, Calls.CACHED_FORMATTED_NUMBER); 87e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 88e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 89b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov private ContactsDatabaseHelper mDbHelper; 90e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov private DatabaseUtils.InsertHelper mCallsInserter; 913a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa private boolean mUseStrictPhoneNumberComparation; 92aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private VoicemailPermissions mVoicemailPermissions; 93aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda private CallLogInsertionHelper mCallLogInsertionHelper; 94e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 95e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 96e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public boolean onCreate() { 97663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 98663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "CallLogProvider.onCreate start"); 99663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 100e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov final Context context = getContext(); 101b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov mDbHelper = getDatabaseHelper(context); 1023a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa mUseStrictPhoneNumberComparation = 1033a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa context.getResources().getBoolean( 1043a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa com.android.internal.R.bool.config_use_strict_phone_number_comparation); 105aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee mVoicemailPermissions = new VoicemailPermissions(context); 106aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda mCallLogInsertionHelper = createCallLogInsertionHelper(context); 107663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) { 108663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki Log.d(Constants.PERFORMANCE_TAG, "CallLogProvider.onCreate finish"); 109663b8b8ce7a29fb2796dc6431f2cd5992934f315Makoto Onuki } 110e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return true; 111e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 112e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 113aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda @VisibleForTesting 114aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda protected CallLogInsertionHelper createCallLogInsertionHelper(final Context context) { 115c4144727cd740079f47e74ae5078d1613874f72aMakoto Onuki return DefaultCallLogInsertionHelper.getInstance(context); 116aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda } 117aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda 118aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda @VisibleForTesting 119b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov protected ContactsDatabaseHelper getDatabaseHelper(final Context context) { 120b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov return ContactsDatabaseHelper.getInstance(context); 121e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 122e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 123e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 124e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 125e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov String sortOrder) { 126e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 12759f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee qb.setTables(Tables.CALLS); 12859f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee qb.setProjectionMap(sCallsProjectionMap); 12959f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee qb.setStrict(true); 13059f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee 131aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 132aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee checkVoicemailPermissionAndAddRestriction(uri, selectionBuilder); 133aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 134e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov int match = sURIMatcher.match(uri); 135e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov switch (match) { 13659f6477e10203617f504857f7e9aee2fda393f4fDebashish Chatterjee case CALLS: 137e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov break; 138e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 139e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov case CALLS_ID: { 140aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee selectionBuilder.addClause(getEqualityClause(Calls._ID, 141aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee parseCallIdFromUri(uri))); 142e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov break; 143e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 144e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 145e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov case CALLS_FILTER: { 146e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov String phoneNumber = uri.getPathSegments().get(2); 147e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov qb.appendWhere("PHONE_NUMBERS_EQUAL(number, "); 148e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov qb.appendWhereEscapeString(phoneNumber); 1493a6a49cfb06272e3e25f3c390a9cf4002da6e34dDaisuke Miyakawa qb.appendWhere(mUseStrictPhoneNumberComparation ? ", 1)" : ", 0)"); 150e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov break; 151e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 152e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 153e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov default: 154e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov throw new IllegalArgumentException("Unknown URL " + uri); 155e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 156e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 157b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getReadableDatabase(); 158aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee Cursor c = qb.query(db, projection, selectionBuilder.build(), selectionArgs, null, null, 159aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee sortOrder, null); 160e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov if (c != null) { 161e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov c.setNotificationUri(getContext().getContentResolver(), CallLog.CONTENT_URI); 162e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 163e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return c; 164e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 165e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 166e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 167e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public String getType(Uri uri) { 168e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov int match = sURIMatcher.match(uri); 169e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov switch (match) { 170e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov case CALLS: 171e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return Calls.CONTENT_TYPE; 172e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov case CALLS_ID: 173e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return Calls.CONTENT_ITEM_TYPE; 174e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov case CALLS_FILTER: 175e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return Calls.CONTENT_TYPE; 176e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov default: 177e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov throw new IllegalArgumentException("Unknown URI: " + uri); 178e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 179e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 180e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 181e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 182e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public Uri insert(Uri uri, ContentValues values) { 18300e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee checkForSupportedColumns(sCallsProjectionMap, values); 184aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee // Inserting a voicemail record through call_log requires the voicemail 185aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee // permission and also requires the additional voicemail param set. 186aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (hasVoicemailValue(values)) { 187aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee checkIsAllowVoicemailRequest(uri); 188aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee mVoicemailPermissions.checkCallerHasFullAccess(); 189aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 19037c85b89cc989308749ea22b1ce29c59a47158acDmitri Plotnikov if (mCallsInserter == null) { 19137c85b89cc989308749ea22b1ce29c59a47158acDmitri Plotnikov SQLiteDatabase db = mDbHelper.getWritableDatabase(); 19237c85b89cc989308749ea22b1ce29c59a47158acDmitri Plotnikov mCallsInserter = new DatabaseUtils.InsertHelper(db, Tables.CALLS); 19337c85b89cc989308749ea22b1ce29c59a47158acDmitri Plotnikov } 194f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda 195f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda ContentValues copiedValues = new ContentValues(values); 196f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda 197f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda // Add the computed fields to the copied values. 198f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda mCallLogInsertionHelper.addComputedValues(copiedValues); 199f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda 200f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda long rowId = getDatabaseModifier(mCallsInserter).insert(copiedValues); 201e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov if (rowId > 0) { 202e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return ContentUris.withAppendedId(uri, rowId); 203e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 204e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov return null; 205e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 206e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 207e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 208aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 20900e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee checkForSupportedColumns(sCallsProjectionMap, values); 210aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee // Request that involves changing record type to voicemail requires the 211aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee // voicemail param set in the uri. 212aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (hasVoicemailValue(values)) { 213aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee checkIsAllowVoicemailRequest(uri); 214aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 215aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 216aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 217aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee checkVoicemailPermissionAndAddRestriction(uri, selectionBuilder); 218aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 219b38ed2c5ffeb20efc677b4a9229db4a00603aa8dDmitri Plotnikov final SQLiteDatabase db = mDbHelper.getWritableDatabase(); 220aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee final int matchedUriId = sURIMatcher.match(uri); 221e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov switch (matchedUriId) { 222e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov case CALLS: 223e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov break; 224e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 225e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov case CALLS_ID: 226aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee selectionBuilder.addClause(getEqualityClause(Calls._ID, parseCallIdFromUri(uri))); 227e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov break; 228e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 229e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov default: 230aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee throw new UnsupportedOperationException("Cannot update URL: " + uri); 231e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 232e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 2332e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee return getDatabaseModifier(db).update(Tables.CALLS, values, selectionBuilder.build(), 2342e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee selectionArgs); 235e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 236e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 237e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov @Override 238e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov public int delete(Uri uri, String selection, String[] selectionArgs) { 239aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee SelectionBuilder selectionBuilder = new SelectionBuilder(selection); 240aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee checkVoicemailPermissionAndAddRestriction(uri, selectionBuilder); 241e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov 242aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee final SQLiteDatabase db = mDbHelper.getWritableDatabase(); 243e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov final int matchedUriId = sURIMatcher.match(uri); 244e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov switch (matchedUriId) { 245e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov case CALLS: 2462e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee return getDatabaseModifier(db).delete(Tables.CALLS, 247929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee selectionBuilder.build(), selectionArgs); 248e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov default: 249e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov throw new UnsupportedOperationException("Cannot delete that URL: " + uri); 250e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 251e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov } 2526f157d1cfb219f80d375c1357bfbdc5bf599d91aDmitri Plotnikov 253929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee // Work around to let the test code override the context. getContext() is final so cannot be 254929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee // overridden. 255929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee protected Context context() { 256929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return getContext(); 257929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 258929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 2592e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee /** 2602e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee * Returns a {@link DatabaseModifier} that takes care of sending necessary notifications 2612e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee * after the operation is performed. 2622e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee */ 263929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private DatabaseModifier getDatabaseModifier(SQLiteDatabase db) { 2642e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee return new DbModifierWithNotification(Tables.CALLS, db, context()); 265929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 266929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 2672e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee /** 2682e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee * Same as {@link #getDatabaseModifier(SQLiteDatabase)} but used for insert helper operations 2692e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee * only. 2702e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee */ 271929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private DatabaseModifier getDatabaseModifier(DatabaseUtils.InsertHelper insertHelper) { 2722e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee return new DbModifierWithNotification(Tables.CALLS, insertHelper, context()); 273929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 274929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 275aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private boolean hasVoicemailValue(ContentValues values) { 276aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee return values.containsKey(Calls.TYPE) && 277aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee values.getAsInteger(Calls.TYPE).equals(Calls.VOICEMAIL_TYPE); 278aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 279aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 280aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee /** 281aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * Checks if the supplied uri requests to include voicemails and take appropriate 282aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * action. 283aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * <p> If voicemail is requested, then check for voicemail permissions. Otherwise 284aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * modify the selection to restrict to non-voicemail entries only. 285aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee */ 286aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private void checkVoicemailPermissionAndAddRestriction(Uri uri, 287aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee SelectionBuilder selectionBuilder) { 288aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (isAllowVoicemailRequest(uri)) { 289aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee mVoicemailPermissions.checkCallerHasFullAccess(); 290aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } else { 291aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee selectionBuilder.addClause(EXCLUDE_VOICEMAIL_SELECTION); 292aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 293aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 294aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 295aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee /** 296aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * Determines if the supplied uri has the request to allow voicemails to be 297aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * included. 298aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee */ 299aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private boolean isAllowVoicemailRequest(Uri uri) { 30092d97071e56110e0df7f25e6ebc92ff4ebf74a88Flavio Lerda return uri.getBooleanQueryParameter(Calls.ALLOW_VOICEMAILS_PARAM_KEY, false); 301aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 302aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 303aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee /** 304aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * Checks to ensure that the given uri has allow_voicemail set. Used by 305aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * insert and update operations to check that ContentValues with voicemail 306aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * call type must use the voicemail uri. 307aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * @throws IllegalArgumentException if allow_voicemail is not set. 308aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee */ 309aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private void checkIsAllowVoicemailRequest(Uri uri) { 310aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee if (!isAllowVoicemailRequest(uri)) { 311aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee throw new IllegalArgumentException( 312aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee String.format("Uri %s cannot be used for voicemail record." + 31392d97071e56110e0df7f25e6ebc92ff4ebf74a88Flavio Lerda " Please set '%s=true' in the uri.", uri, 31492d97071e56110e0df7f25e6ebc92ff4ebf74a88Flavio Lerda Calls.ALLOW_VOICEMAILS_PARAM_KEY)); 315aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 316aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 317aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 318aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee /** 319aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * Parses the call Id from the given uri, assuming that this is a uri that 320aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * matches CALLS_ID. For other uri types the behaviour is undefined. 321aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee * @throws IllegalArgumentException if the id included in the Uri is not a valid long value. 322aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee */ 3239978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda private long parseCallIdFromUri(Uri uri) { 324aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee try { 3259978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda return Long.parseLong(uri.getPathSegments().get(1)); 326aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } catch (NumberFormatException e) { 327aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee throw new IllegalArgumentException("Invalid call id in uri: " + uri, e); 328aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 329aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 330e99988b266dd1263162583e81e2b408e7329b1c8Dmitri Plotnikov} 331