14b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee/* 24b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * Copyright (C) 2011 The Android Open Source Project 34b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * 44b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * Licensed under the Apache License, Version 2.0 (the "License"); 54b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * you may not use this file except in compliance with the License. 64b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * You may obtain a copy of the License at 74b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * 84b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * http://www.apache.org/licenses/LICENSE-2.0 94b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * 104b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * Unless required by applicable law or agreed to in writing, software 114b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * distributed under the License is distributed on an "AS IS" BASIS, 124b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * See the License for the specific language governing permissions and 144b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * limitations under the License 154b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee */ 164b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeepackage com.android.providers.contacts; 174b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 184b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport static com.android.providers.contacts.util.DbQueryUtils.checkForSupportedColumns; 194b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses; 204b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause; 214b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 224b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.content.ContentUris; 234b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.content.ContentValues; 244b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.content.Context; 254b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.database.Cursor; 261e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudsonimport android.database.DatabaseUtils; 274b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.database.sqlite.SQLiteDatabase; 284b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.database.sqlite.SQLiteOpenHelper; 294b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.database.sqlite.SQLiteQueryBuilder; 304b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.net.Uri; 314b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.os.ParcelFileDescriptor; 324b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.provider.CallLog.Calls; 331e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudsonimport android.provider.OpenableColumns; 344b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.provider.VoicemailContract.Voicemails; 354b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport android.util.Log; 364b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 37ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Chengimport com.google.common.collect.ImmutableSet; 38ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng 3938210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.common.content.ProjectionMap; 4038210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.providers.contacts.VoicemailContentProvider.UriData; 4138210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.providers.contacts.util.CloseUtils; 42284f71646d1953f2d78b53e2cdb42cb93e1d9d6fChiao Chengimport com.google.common.collect.ImmutableSet; 4338210445730ee04c351c7cc1b3800cfe23e34325Makoto Onuki 444b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport java.io.File; 459cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjeeimport java.io.FileNotFoundException; 464b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeeimport java.io.IOException; 474b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 484b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee/** 494b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee * Implementation of {@link VoicemailTable.Delegate} for the voicemail content table. 504b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee */ 514b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjeepublic class VoicemailContentTable implements VoicemailTable.Delegate { 524b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private static final String TAG = "VoicemailContentProvider"; 531e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson private final ProjectionMap mVoicemailProjectionMap; 544b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 554b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** The private directory in which to store the data associated with the voicemail. */ 564b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private static final String DATA_DIRECTORY = "voicemail-data"; 574b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 584b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private static final String[] FILENAME_ONLY_PROJECTION = new String[] { Voicemails._DATA }; 594b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 60ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng private static final ImmutableSet<String> ALLOWED_COLUMNS = new ImmutableSet.Builder<String>() 61ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails._ID) 62ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.NUMBER) 63ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.DATE) 64ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.DURATION) 65ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.IS_READ) 66d372af60001602a8c6cccf6258b514360c69b513Yorke Lee .add(Voicemails.TRANSCRIPTION) 67ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.STATE) 68ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.SOURCE_DATA) 69ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.SOURCE_PACKAGE) 70ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.HAS_CONTENT) 71dca8f302db8e661f13f3585bc67c53a5adf36617Nancy Chen .add(Voicemails.PHONE_ACCOUNT_COMPONENT_NAME) 72dca8f302db8e661f13f3585bc67c53a5adf36617Nancy Chen .add(Voicemails.PHONE_ACCOUNT_ID) 73ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(Voicemails.MIME_TYPE) 740f74e8600ad744f2e4ba9c6a4cdadf5da5a20e83Nancy Chen .add(Voicemails.DIRTY) 750f74e8600ad744f2e4ba9c6a4cdadf5da5a20e83Nancy Chen .add(Voicemails.DELETED) 76ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(OpenableColumns.DISPLAY_NAME) 77ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .add(OpenableColumns.SIZE) 78ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng .build(); 79ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng 804b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final String mTableName; 814b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final SQLiteOpenHelper mDbHelper; 824b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final Context mContext; 834b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private final VoicemailTable.DelegateHelper mDelegateHelper; 84aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda private final CallLogInsertionHelper mCallLogInsertionHelper; 854b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 864b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public VoicemailContentTable(String tableName, Context context, SQLiteOpenHelper dbHelper, 87aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda VoicemailTable.DelegateHelper contentProviderHelper, 88aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda CallLogInsertionHelper callLogInsertionHelper) { 894b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mTableName = tableName; 904b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mContext = context; 914b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mDbHelper = dbHelper; 924b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mDelegateHelper = contentProviderHelper; 931e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson mVoicemailProjectionMap = new ProjectionMap.Builder() 941e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails._ID) 951e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.NUMBER) 961e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.DATE) 971e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.DURATION) 981e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.IS_READ) 99d372af60001602a8c6cccf6258b514360c69b513Yorke Lee .add(Voicemails.TRANSCRIPTION) 1001e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.STATE) 1011e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.SOURCE_DATA) 1021e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.SOURCE_PACKAGE) 1031e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.HAS_CONTENT) 1041e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails.MIME_TYPE) 1051e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(Voicemails._DATA) 106dca8f302db8e661f13f3585bc67c53a5adf36617Nancy Chen .add(Voicemails.PHONE_ACCOUNT_COMPONENT_NAME) 107dca8f302db8e661f13f3585bc67c53a5adf36617Nancy Chen .add(Voicemails.PHONE_ACCOUNT_ID) 1080f74e8600ad744f2e4ba9c6a4cdadf5da5a20e83Nancy Chen .add(Voicemails.DIRTY) 1090f74e8600ad744f2e4ba9c6a4cdadf5da5a20e83Nancy Chen .add(Voicemails.DELETED) 1101e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(OpenableColumns.DISPLAY_NAME, createDisplayName(context)) 1111e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .add(OpenableColumns.SIZE, "NULL") 1121e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson .build(); 113aeaba441ddb05dede8bd86291ca78f42d670d54cFlavio Lerda mCallLogInsertionHelper = callLogInsertionHelper; 1141e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson } 1151e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson 1161e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson /** 1171e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson * Calculate a suitable value for the display name column. 1181e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson * <p> 1191e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson * This is a bit of a hack, it uses a suitably localized string and uses SQL to combine this 1201e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson * with the number column. 1211e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson */ 1221e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson private static String createDisplayName(Context context) { 1231e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson String prefix = context.getString(R.string.voicemail_from_column); 1241e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson return DatabaseUtils.sqlEscapeString(prefix) + " || " + Voicemails.NUMBER; 1254b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 1264b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 1274b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 1284b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public Uri insert(UriData uriData, ContentValues values) { 1291e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson checkForSupportedColumns(mVoicemailProjectionMap, values); 1304b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee ContentValues copiedValues = new ContentValues(values); 1314b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee checkInsertSupported(uriData); 1324b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee mDelegateHelper.checkAndAddSourcePackageIntoValues(uriData, copiedValues); 1334b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 134f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda // Add the computed fields to the copied values. 135f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda mCallLogInsertionHelper.addComputedValues(copiedValues); 136f402aaf776fee29d8044d97979b16695f24086ddFlavio Lerda 1374b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // "_data" column is used by base ContentProvider's openFileHelper() to determine filename 1384b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // when Input/Output stream is requested to be opened. 1394b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee copiedValues.put(Voicemails._DATA, generateDataFile()); 1404b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 1414b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // call type is always voicemail. 1424b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee copiedValues.put(Calls.TYPE, Calls.VOICEMAIL_TYPE); 1435638e7fa091fa925b539a54bbf63abf94ea4c257Nancy Chen // A voicemail is marked as new unless it is marked as read or explicitly overridden. 1445638e7fa091fa925b539a54bbf63abf94ea4c257Nancy Chen boolean isRead = values.containsKey(Calls.IS_READ) ? 1455c466282ff1ebecb37c93dcb6d6ccfc845330e65Nancy Chen values.getAsBoolean(Calls.IS_READ) : false; 146eaa7d851000e368a18be24bc816046ad9cf49d6eDebashish Chatterjee if (!values.containsKey(Calls.NEW)) { 1475638e7fa091fa925b539a54bbf63abf94ea4c257Nancy Chen copiedValues.put(Calls.NEW, !isRead); 148eaa7d851000e368a18be24bc816046ad9cf49d6eDebashish Chatterjee } 1494b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 1504b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SQLiteDatabase db = mDbHelper.getWritableDatabase(); 151929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee long rowId = getDatabaseModifier(db).insert(mTableName, null, copiedValues); 1524b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (rowId > 0) { 1534b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Uri newUri = ContentUris.withAppendedId(uriData.getUri(), rowId); 1544b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // Populate the 'voicemail_uri' field to be used by the call_log provider. 1554b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee updateVoicemailUri(db, newUri); 1564b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return newUri; 1574b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 1584b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return null; 1594b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 1604b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 1614b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private void checkInsertSupported(UriData uriData) { 1624b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (uriData.hasId()) { 1634b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new UnsupportedOperationException(String.format( 1644b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee "Cannot insert URI: %s. Inserted URIs should not contain an id.", 1654b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee uriData.getUri())); 1664b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 1674b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 1684b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 1694b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Generates a random file for storing audio data. */ 1704b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private String generateDataFile() { 1714b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee try { 1724b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee File dataDirectory = mContext.getDir(DATA_DIRECTORY, Context.MODE_PRIVATE); 1734b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee File voicemailFile = File.createTempFile("voicemail", "", dataDirectory); 1744b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return voicemailFile.getAbsolutePath(); 1754b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } catch (IOException e) { 1764b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // If we are unable to create a temporary file, something went horribly wrong. 1774b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new RuntimeException("unable to create temp file", e); 1784b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 1794b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 1804b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private void updateVoicemailUri(SQLiteDatabase db, Uri newUri) { 1814b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee ContentValues values = new ContentValues(); 1824b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee values.put(Calls.VOICEMAIL_URI, newUri.toString()); 1834b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // Directly update the db because we cannot update voicemail_uri through external 1844b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // update() due to projectionMap check. This also avoids unnecessary permission 1854b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // checks that are already done as part of insert request. 1869cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee db.update(mTableName, values, UriData.createUriData(newUri).getWhereClause(), null); 1874b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 1884b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 1894b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 1904b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public int delete(UriData uriData, String selection, String[] selectionArgs) { 1914b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee final SQLiteDatabase db = mDbHelper.getWritableDatabase(); 1929cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee String combinedClause = concatenateClauses(selection, uriData.getWhereClause(), 1934b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee getCallTypeClause()); 1944b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 1954b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // Delete all the files associated with this query. Once we've deleted the rows, there will 1964b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // be no way left to get hold of the files. 1974b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Cursor cursor = null; 1984b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee try { 1994b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee cursor = query(uriData, FILENAME_ONLY_PROJECTION, selection, selectionArgs, null); 2004b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee while (cursor.moveToNext()) { 2011c8e5fcdd6199f5959aaa6eab47e806b401efdd9Hugo Hudson String filename = cursor.getString(0); 2021c8e5fcdd6199f5959aaa6eab47e806b401efdd9Hugo Hudson if (filename == null) { 2031c8e5fcdd6199f5959aaa6eab47e806b401efdd9Hugo Hudson Log.w(TAG, "No filename for uri " + uriData.getUri() + ", cannot delete file"); 2041c8e5fcdd6199f5959aaa6eab47e806b401efdd9Hugo Hudson continue; 2051c8e5fcdd6199f5959aaa6eab47e806b401efdd9Hugo Hudson } 2061c8e5fcdd6199f5959aaa6eab47e806b401efdd9Hugo Hudson File file = new File(filename); 2074b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (file.exists()) { 2084b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee boolean success = file.delete(); 2094b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (!success) { 2104b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Log.e(TAG, "Failed to delete file: " + file.getAbsolutePath()); 2114b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2124b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2134b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2144b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } finally { 2154b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee CloseUtils.closeQuietly(cursor); 2164b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2174b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 2184b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // Now delete the rows themselves. 219929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return getDatabaseModifier(db).delete(mTableName, combinedClause, 220929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee selectionArgs); 2214b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2224b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 2234b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 2244b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public Cursor query(UriData uriData, String[] projection, String selection, 2254b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String[] selectionArgs, String sortOrder) { 2264b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 2274b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee qb.setTables(mTableName); 2281e6310fcc55c8549c98018fc427b54e1619320a4Hugo Hudson qb.setProjectionMap(mVoicemailProjectionMap); 2294b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee qb.setStrict(true); 2304b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 2319cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee String combinedClause = concatenateClauses(selection, uriData.getWhereClause(), 2324b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee getCallTypeClause()); 2334b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee SQLiteDatabase db = mDbHelper.getReadableDatabase(); 2344b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee Cursor c = qb.query(db, projection, combinedClause, selectionArgs, null, null, sortOrder); 2354b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (c != null) { 2364b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee c.setNotificationUri(mContext.getContentResolver(), Voicemails.CONTENT_URI); 2374b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2384b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee return c; 2394b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2404b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 2414b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 2424b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public int update(UriData uriData, ContentValues values, String selection, 2434b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee String[] selectionArgs) { 244ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng 245ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng checkForSupportedColumns(ALLOWED_COLUMNS, values, "Updates are not allowed."); 2464b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee checkUpdateSupported(uriData); 247ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng 2484b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee final SQLiteDatabase db = mDbHelper.getWritableDatabase(); 2494b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // TODO: This implementation does not allow bulk update because it only accepts 2504b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee // URI that include message Id. I think we do want to support bulk update. 2519cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee String combinedClause = concatenateClauses(selection, uriData.getWhereClause(), 2524b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee getCallTypeClause()); 253929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee return getDatabaseModifier(db).update(mTableName, values, combinedClause, 254929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee selectionArgs); 2554b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2564b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 2574b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private void checkUpdateSupported(UriData uriData) { 2584b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (!uriData.hasId()) { 2594b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee throw new UnsupportedOperationException(String.format( 2604b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee "Cannot update URI: %s. Bulk update not supported", uriData.getUri())); 2614b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2624b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2634b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 2644b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 2654b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee public String getType(UriData uriData) { 2664b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee if (uriData.hasId()) { 267d558ccc921460ac382850a8e6e2e668f3a2b9b26Debashish Chatterjee return Voicemails.ITEM_TYPE; 268d558ccc921460ac382850a8e6e2e668f3a2b9b26Debashish Chatterjee } else { 269d558ccc921460ac382850a8e6e2e668f3a2b9b26Debashish Chatterjee return Voicemails.DIR_TYPE; 2704b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2714b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2724b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 2734b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee @Override 2749cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee public ParcelFileDescriptor openFile(UriData uriData, String mode) 2759cf06e7bcb0be759f1c930412fd2e41eba4f5f03Debashish Chatterjee throws FileNotFoundException { 2763ae32e20bc3f7a278471475efa300b6544b1112eDebashish Chatterjee return mDelegateHelper.openDataFile(uriData, mode); 2774b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 2784b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee 2794b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee /** Creates a clause to restrict the selection to only voicemail call type.*/ 2804b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee private String getCallTypeClause() { 2819978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda return getEqualityClause(Calls.TYPE, Calls.VOICEMAIL_TYPE); 2824b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee } 283929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee 284929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee private DatabaseModifier getDatabaseModifier(SQLiteDatabase db) { 2852e757d904e62dbf5bc0b028626fa9319ccc38c45Debashish Chatterjee return new DbModifierWithNotification(mTableName, db, mContext); 286929a04e2830e30718930d96335dfb0a729b6ab91Debashish Chatterjee } 2874b571ba0de4fac4ff9d2a4277032b8c6548fdbfaDebashish Chatterjee} 288