Home | History | Annotate | Download | only in sync
      1 /*
      2  * Copyright (C) 2015 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 package com.android.phone.vvm.omtp.sync;
     17 
     18 import android.content.ContentResolver;
     19 import android.content.ContentUris;
     20 import android.content.ContentValues;
     21 import android.content.Context;
     22 import android.database.Cursor;
     23 import android.net.Uri;
     24 import android.provider.VoicemailContract;
     25 import android.provider.VoicemailContract.Voicemails;
     26 import android.telecom.PhoneAccountHandle;
     27 import android.telecom.Voicemail;
     28 import java.util.ArrayList;
     29 import java.util.List;
     30 
     31 /**
     32  * Construct queries to interact with the voicemails table.
     33  */
     34 public class VoicemailsQueryHelper {
     35     final static String[] PROJECTION = new String[] {
     36             Voicemails._ID,              // 0
     37             Voicemails.SOURCE_DATA,      // 1
     38             Voicemails.IS_READ,          // 2
     39             Voicemails.DELETED,          // 3
     40             Voicemails.TRANSCRIPTION     // 4
     41     };
     42 
     43     public static final int _ID = 0;
     44     public static final int SOURCE_DATA = 1;
     45     public static final int IS_READ = 2;
     46     public static final int DELETED = 3;
     47     public static final int TRANSCRIPTION = 4;
     48 
     49     final static String READ_SELECTION = Voicemails.DIRTY + "=1 AND "
     50                 + Voicemails.DELETED + "!=1 AND " + Voicemails.IS_READ + "=1";
     51     final static String DELETED_SELECTION = Voicemails.DELETED + "=1";
     52 
     53     private Context mContext;
     54     private ContentResolver mContentResolver;
     55     private Uri mSourceUri;
     56 
     57     public VoicemailsQueryHelper(Context context) {
     58         mContext = context;
     59         mContentResolver = context.getContentResolver();
     60         mSourceUri = VoicemailContract.Voicemails.buildSourceUri(mContext.getPackageName());
     61     }
     62 
     63     /**
     64      * Get all the local read voicemails that have not been synced to the server.
     65      *
     66      * @return A list of read voicemails.
     67      */
     68     public List<Voicemail> getReadVoicemails() {
     69         return getLocalVoicemails(READ_SELECTION);
     70     }
     71 
     72     /**
     73      * Get all the locally deleted voicemails that have not been synced to the server.
     74      *
     75      * @return A list of deleted voicemails.
     76      */
     77     public List<Voicemail> getDeletedVoicemails() {
     78         return getLocalVoicemails(DELETED_SELECTION);
     79     }
     80 
     81     /**
     82      * Get all voicemails locally stored.
     83      *
     84      * @return A list of all locally stored voicemails.
     85      */
     86     public List<Voicemail> getAllVoicemails() {
     87         return getLocalVoicemails(null);
     88     }
     89 
     90     /**
     91      * Utility method to make queries to the voicemail database.
     92      *
     93      * @param selection A filter declaring which rows to return. {@code null} returns all rows.
     94      * @return A list of voicemails according to the selection statement.
     95      */
     96     private List<Voicemail> getLocalVoicemails(String selection) {
     97         Cursor cursor = mContentResolver.query(mSourceUri, PROJECTION, selection, null, null);
     98         if (cursor == null) {
     99             return null;
    100         }
    101         try {
    102             List<Voicemail> voicemails = new ArrayList<Voicemail>();
    103             while (cursor.moveToNext()) {
    104                 final long id = cursor.getLong(_ID);
    105                 final String sourceData = cursor.getString(SOURCE_DATA);
    106                 final boolean isRead = cursor.getInt(IS_READ) == 1;
    107                 final String transcription = cursor.getString(TRANSCRIPTION);
    108                 Voicemail voicemail = Voicemail
    109                         .createForUpdate(id, sourceData)
    110                         .setIsRead(isRead)
    111                         .setTranscription(transcription).build();
    112                 voicemails.add(voicemail);
    113             }
    114             return voicemails;
    115         } finally {
    116             cursor.close();
    117         }
    118     }
    119 
    120     /**
    121      * Deletes a list of voicemails from the voicemail content provider.
    122      *
    123      * @param voicemails The list of voicemails to delete
    124      * @return The number of voicemails deleted
    125      */
    126     public int deleteFromDatabase(List<Voicemail> voicemails) {
    127         int count = voicemails.size();
    128         if (count == 0) {
    129             return 0;
    130         }
    131 
    132         StringBuilder sb = new StringBuilder();
    133         for (int i = 0; i < count; i++) {
    134             if (i > 0) {
    135                 sb.append(",");
    136             }
    137             sb.append(voicemails.get(i).getId());
    138         }
    139 
    140         String selectionStatement = String.format(Voicemails._ID + " IN (%s)", sb.toString());
    141         return mContentResolver.delete(Voicemails.CONTENT_URI, selectionStatement, null);
    142     }
    143 
    144     /**
    145      * Utility method to delete a single voicemail.
    146      */
    147     public void deleteFromDatabase(Voicemail voicemail) {
    148         mContentResolver.delete(Voicemails.CONTENT_URI, Voicemails._ID + "=?",
    149                 new String[] { Long.toString(voicemail.getId()) });
    150     }
    151 
    152     public int markReadInDatabase(List<Voicemail> voicemails) {
    153         int count = voicemails.size();
    154         for (int i = 0; i < count; i++) {
    155             markReadInDatabase(voicemails.get(i));
    156         }
    157         return count;
    158     }
    159 
    160     /**
    161      * Utility method to mark single message as read.
    162      */
    163     public void markReadInDatabase(Voicemail voicemail) {
    164         Uri uri = ContentUris.withAppendedId(mSourceUri, voicemail.getId());
    165         ContentValues contentValues = new ContentValues();
    166         contentValues.put(Voicemails.IS_READ, "1");
    167         mContentResolver.update(uri, contentValues, null, null);
    168     }
    169 
    170     /**
    171      * Sends an update command to the voicemail content provider for a list of voicemails. From the
    172      * view of the provider, since the updater is the owner of the entry, a blank "update" means
    173      * that the voicemail source is indicating that the server has up-to-date information on the
    174      * voicemail. This flips the "dirty" bit to "0".
    175      *
    176      * @param voicemails The list of voicemails to update
    177      * @return The number of voicemails updated
    178      */
    179     public int markCleanInDatabase(List<Voicemail> voicemails) {
    180         int count = voicemails.size();
    181         for (int i = 0; i < count; i++) {
    182             markCleanInDatabase(voicemails.get(i));
    183         }
    184         return count;
    185     }
    186 
    187     /**
    188      * Utility method to mark single message as clean.
    189      */
    190     public void markCleanInDatabase(Voicemail voicemail) {
    191         Uri uri = ContentUris.withAppendedId(mSourceUri, voicemail.getId());
    192         ContentValues contentValues = new ContentValues();
    193         mContentResolver.update(uri, contentValues, null, null);
    194     }
    195 
    196     /**
    197      * Utility method to add a transcription to the voicemail.
    198      */
    199     public void updateWithTranscription(Voicemail voicemail, String transcription) {
    200         Uri uri = ContentUris.withAppendedId(mSourceUri, voicemail.getId());
    201         ContentValues contentValues = new ContentValues();
    202         contentValues.put(Voicemails.TRANSCRIPTION, transcription);
    203         mContentResolver.update(uri, contentValues, null, null);
    204     }
    205 
    206     /**
    207      * Voicemail is unique if the tuple of (phone account component name, phone account id, source
    208      * data) is unique. If the phone account is missing, we also consider this unique since it's
    209      * simply an "unknown" account.
    210      * @param voicemail The voicemail to check if it is unique.
    211      * @return {@code true} if the voicemail is unique, {@code false} otherwise.
    212      */
    213     public boolean isVoicemailUnique(Voicemail voicemail) {
    214         Cursor cursor = null;
    215         PhoneAccountHandle phoneAccount = voicemail.getPhoneAccount();
    216         if (phoneAccount != null) {
    217             String phoneAccountComponentName = phoneAccount.getComponentName().flattenToString();
    218             String phoneAccountId = phoneAccount.getId();
    219             String sourceData = voicemail.getSourceData();
    220             if (phoneAccountComponentName == null || phoneAccountId == null || sourceData == null) {
    221                 return true;
    222             }
    223             try {
    224                 String whereClause =
    225                         Voicemails.PHONE_ACCOUNT_COMPONENT_NAME + "=? AND " +
    226                         Voicemails.PHONE_ACCOUNT_ID + "=? AND " + Voicemails.SOURCE_DATA + "=?";
    227                 String[] whereArgs = { phoneAccountComponentName, phoneAccountId, sourceData };
    228                 cursor = mContentResolver.query(
    229                         mSourceUri, PROJECTION, whereClause, whereArgs, null);
    230                 if (cursor.getCount() == 0) {
    231                     return true;
    232                 } else {
    233                     return false;
    234                 }
    235             }
    236             finally {
    237                 if (cursor != null) {
    238                     cursor.close();
    239                 }
    240             }
    241         }
    242         return true;
    243     }
    244 }
    245