• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
onCreate()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
getDatabaseHelper(Context context)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
getFilesDir()79     protected File getFilesDir() {
80         return getContext().getFilesDir();
81     }
82 
83     @Nullable
84     @Override
query(Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder)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
getType(Uri uri)102     public String getType(Uri uri) {
103         return VoicemailArchiveContract.VoicemailArchive.CONTENT_ITEM_TYPE;
104     }
105 
106     @Nullable
107     @Override
insert(Uri uri, ContentValues values)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
delete(Uri uri, @Nullable String selection, @Nullable String[] selectionArgs)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
update(Uri uri, ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs)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
openFile(Uri uri, String mode)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 
deleteFile(@ullable String path)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 
getQueryBuilder(Uri uri)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 
getSelectionWithId(String selection, Uri uri)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 
notifyChange(Uri uri)215     private void notifyChange(Uri uri) {
216         getContext().getContentResolver().notifyChange(uri, null);
217     }
218 }
219