Home | History | Annotate | Download | only in database
      1 /*
      2  * Copyright (C) 2016 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.database;
     18 
     19 import android.content.ContentProvider;
     20 import android.content.ContentUris;
     21 import android.content.ContentValues;
     22 import android.content.Context;
     23 import android.content.UriMatcher;
     24 import android.database.Cursor;
     25 import android.database.sqlite.SQLiteDatabase;
     26 import android.database.sqlite.SQLiteQueryBuilder;
     27 import android.net.Uri;
     28 import android.os.ParcelFileDescriptor;
     29 import android.support.annotation.Nullable;
     30 import android.text.TextUtils;
     31 import android.webkit.MimeTypeMap;
     32 
     33 import com.android.dialerbind.DatabaseHelperManager;
     34 import com.google.common.annotations.VisibleForTesting;
     35 
     36 import java.io.File;
     37 import java.io.FileNotFoundException;
     38 
     39 /**
     40  * An implementation of the Voicemail Archive content provider. This class performs
     41  * all database level operations on the voicemail_archive_table.
     42  */
     43 public class VoicemailArchiveProvider extends ContentProvider {
     44     private static final String TAG = "VMArchiveProvider";
     45     private static final int VOICEMAIL_ARCHIVE_TABLE = 1;
     46     private static final int VOICEMAIL_ARCHIVE_TABLE_ID = 2;
     47     private static final String VOICEMAIL_FOLDER = "voicemails";
     48 
     49     private DialerDatabaseHelper mDialerDatabaseHelper;
     50     private final UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
     51 
     52     @Override
     53     public boolean onCreate() {
     54          mDialerDatabaseHelper = getDatabaseHelper(getContext());
     55          if (mDialerDatabaseHelper == null) {
     56              return false;
     57          }
     58         mUriMatcher.addURI(VoicemailArchiveContract.AUTHORITY,
     59                  VoicemailArchiveContract.VoicemailArchive.VOICEMAIL_ARCHIVE_TABLE,
     60                  VOICEMAIL_ARCHIVE_TABLE);
     61         mUriMatcher.addURI(VoicemailArchiveContract.AUTHORITY,
     62                  VoicemailArchiveContract.VoicemailArchive.VOICEMAIL_ARCHIVE_TABLE + "/#",
     63                  VOICEMAIL_ARCHIVE_TABLE_ID);
     64          return true;
     65     }
     66 
     67     @VisibleForTesting
     68     protected DialerDatabaseHelper getDatabaseHelper(Context context) {
     69         return DatabaseHelperManager.getDatabaseHelper(context);
     70     }
     71 
     72     /**
     73      * Used by the test class because it extends {@link android.test.ProviderTestCase2} in which the
     74      * {@link android.test.IsolatedContext} returns /dev/null when getFilesDir() is called.
     75      *
     76      * @see android.test.IsolatedContext#getFilesDir
     77      */
     78     @VisibleForTesting
     79     protected File getFilesDir() {
     80         return getContext().getFilesDir();
     81     }
     82 
     83     @Nullable
     84     @Override
     85     public Cursor query(Uri uri,
     86                         @Nullable String[] projection,
     87                         @Nullable String selection,
     88                         @Nullable String[] selectionArgs,
     89                         @Nullable String sortOrder) {
     90         SQLiteDatabase db = mDialerDatabaseHelper.getReadableDatabase();
     91         SQLiteQueryBuilder queryBuilder = getQueryBuilder(uri);
     92         Cursor cursor = queryBuilder
     93                 .query(db, projection, selection, selectionArgs, null, null, sortOrder);
     94         if (cursor != null) {
     95             cursor.setNotificationUri(getContext().getContentResolver(),
     96                     VoicemailArchiveContract.VoicemailArchive.CONTENT_URI);
     97         }
     98         return cursor;
     99     }
    100 
    101     @Override
    102     public String getType(Uri uri) {
    103         return VoicemailArchiveContract.VoicemailArchive.CONTENT_ITEM_TYPE;
    104     }
    105 
    106     @Nullable
    107     @Override
    108     public Uri insert(Uri uri, ContentValues values) {
    109         SQLiteDatabase db = mDialerDatabaseHelper.getWritableDatabase();
    110         long id = db.insert(DialerDatabaseHelper.Tables.VOICEMAIL_ARCHIVE_TABLE,
    111                 null, values);
    112         if (id < 0) {
    113             return null;
    114         }
    115         notifyChange(uri);
    116         // Create the directory for archived voicemails if it doesn't already exist
    117         File directory = new File(getFilesDir(), VOICEMAIL_FOLDER);
    118         directory.mkdirs();
    119         Uri newUri = ContentUris.withAppendedId(uri, id);
    120 
    121         // Create new file only if path is not provided to one
    122         if (!values.containsKey(VoicemailArchiveContract.VoicemailArchive._DATA)) {
    123             String fileExtension = MimeTypeMap.getSingleton().getExtensionFromMimeType(
    124                     values.getAsString(VoicemailArchiveContract.VoicemailArchive.MIME_TYPE));
    125             File voicemailFile = new File(directory,
    126                     TextUtils.isEmpty(fileExtension) ? Long.toString(id) :
    127                             id + "." + fileExtension);
    128             values.put(VoicemailArchiveContract.VoicemailArchive._DATA, voicemailFile.getPath());
    129         }
    130         update(newUri, values, null, null);
    131         return newUri;
    132     }
    133 
    134 
    135     @Override
    136     public int delete(Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
    137         SQLiteDatabase db = mDialerDatabaseHelper.getWritableDatabase();
    138         SQLiteQueryBuilder queryBuilder = getQueryBuilder(uri);
    139         Cursor cursor = queryBuilder.query(db, null, selection, selectionArgs, null, null, null);
    140 
    141         // Delete all the voicemail files related to the selected rows
    142         while (cursor.moveToNext()) {
    143             deleteFile(cursor.getString(cursor.getColumnIndex(
    144                     VoicemailArchiveContract.VoicemailArchive._DATA)));
    145         }
    146 
    147         int rows = db.delete(DialerDatabaseHelper.Tables.VOICEMAIL_ARCHIVE_TABLE,
    148                 getSelectionWithId(selection, uri),
    149                 selectionArgs);
    150         if (rows > 0) {
    151             notifyChange(uri);
    152         }
    153         return rows;
    154     }
    155 
    156     @Override
    157     public int update(Uri uri,
    158                       ContentValues values,
    159                       @Nullable String selection,
    160                       @Nullable String[] selectionArgs) {
    161         SQLiteDatabase db = mDialerDatabaseHelper.getWritableDatabase();
    162         selection = getSelectionWithId(selection, uri);
    163         int rows = db.update(DialerDatabaseHelper.Tables.VOICEMAIL_ARCHIVE_TABLE,
    164                 values,
    165                 selection,
    166                 selectionArgs);
    167         if (rows > 0) {
    168             notifyChange(uri);
    169         }
    170         return rows;
    171     }
    172 
    173     @Override
    174     public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    175         if (mUriMatcher.match(uri) != VOICEMAIL_ARCHIVE_TABLE_ID) {
    176             throw new IllegalArgumentException("URI Invalid.");
    177         }
    178         return openFileHelper(uri, mode);
    179     }
    180 
    181     private void deleteFile(@Nullable String path) {
    182         if (TextUtils.isEmpty(path)) {
    183             return;
    184         }
    185         File file = new File(path);
    186         if (file.exists()) {
    187             file.delete();
    188         }
    189     }
    190 
    191     private SQLiteQueryBuilder getQueryBuilder(Uri uri) {
    192         SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    193         queryBuilder.setTables(DialerDatabaseHelper.Tables.VOICEMAIL_ARCHIVE_TABLE);
    194         String selectionWithId = getSelectionWithId(null, uri);
    195         if (!TextUtils.isEmpty(selectionWithId)) {
    196             queryBuilder.appendWhere(selectionWithId);
    197         }
    198         return queryBuilder;
    199     }
    200 
    201     private String getSelectionWithId(String selection, Uri uri) {
    202         int match = mUriMatcher.match(uri);
    203         switch (match) {
    204             case VOICEMAIL_ARCHIVE_TABLE:
    205                 return selection;
    206             case VOICEMAIL_ARCHIVE_TABLE_ID:
    207                 String idStr = VoicemailArchiveContract.VoicemailArchive._ID + "=" +
    208                         ContentUris.parseId(uri);
    209                 return TextUtils.isEmpty(selection) ? idStr : selection + " AND " + idStr;
    210             default:
    211                 throw new IllegalArgumentException("Unknown uri: " + uri);
    212         }
    213     }
    214 
    215     private void notifyChange(Uri uri) {
    216         getContext().getContentResolver().notifyChange(uri, null);
    217     }
    218 }
    219