1 /* 2 * Copyright (C) 2017 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.voicemail.impl.transcribe; 17 18 import android.annotation.TargetApi; 19 import android.content.ContentResolver; 20 import android.content.ContentUris; 21 import android.content.ContentValues; 22 import android.content.Context; 23 import android.database.Cursor; 24 import android.net.Uri; 25 import android.os.Build; 26 import android.provider.VoicemailContract.Voicemails; 27 import android.support.annotation.VisibleForTesting; 28 import android.support.annotation.WorkerThread; 29 import android.util.Pair; 30 import com.android.dialer.common.Assert; 31 import com.android.dialer.common.LogUtil; 32 import com.android.dialer.compat.android.provider.VoicemailCompat; 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** Helper class for reading and writing transcription data in the database */ 37 @TargetApi(Build.VERSION_CODES.O) 38 public class TranscriptionDbHelper { 39 @VisibleForTesting 40 static final String[] PROJECTION = 41 new String[] { 42 Voicemails._ID, // 0 43 Voicemails.TRANSCRIPTION, // 1 44 VoicemailCompat.TRANSCRIPTION_STATE // 2 45 }; 46 47 static final int ID = 0; 48 static final int TRANSCRIPTION = 1; 49 static final int TRANSCRIPTION_STATE = 2; 50 51 private final ContentResolver contentResolver; 52 private final Uri uri; 53 TranscriptionDbHelper(Context context, Uri uri)54 TranscriptionDbHelper(Context context, Uri uri) { 55 Assert.isNotNull(uri); 56 this.contentResolver = context.getContentResolver(); 57 this.uri = uri; 58 } 59 TranscriptionDbHelper(Context context)60 TranscriptionDbHelper(Context context) { 61 this(context, Voicemails.buildSourceUri(context.getPackageName())); 62 } 63 64 @WorkerThread getTranscriptionAndState()65 Pair<String, Integer> getTranscriptionAndState() { 66 Assert.checkState(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O); 67 Assert.isWorkerThread(); 68 try (Cursor cursor = contentResolver.query(uri, PROJECTION, null, null, null)) { 69 if (cursor == null) { 70 LogUtil.e("TranscriptionDbHelper.getTranscriptionAndState", "query failed."); 71 return null; 72 } 73 74 if (cursor.moveToFirst()) { 75 String transcription = cursor.getString(TRANSCRIPTION); 76 int transcriptionState = cursor.getInt(TRANSCRIPTION_STATE); 77 return new Pair<>(transcription, transcriptionState); 78 } 79 } 80 LogUtil.i("TranscriptionDbHelper.getTranscriptionAndState", "query returned no results"); 81 return null; 82 } 83 84 @WorkerThread getUntranscribedVoicemails()85 List<Uri> getUntranscribedVoicemails() { 86 Assert.checkState(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O); 87 Assert.isWorkerThread(); 88 List<Uri> untranscribed = new ArrayList<>(); 89 String whereClause = 90 "(" 91 + Voicemails.TRANSCRIPTION 92 + " is NULL OR " 93 + Voicemails.TRANSCRIPTION 94 + " = '')" 95 + " AND " 96 + VoicemailCompat.TRANSCRIPTION_STATE 97 + "=?"; 98 String[] whereArgs = {String.valueOf(VoicemailCompat.TRANSCRIPTION_NOT_STARTED)}; 99 try (Cursor cursor = contentResolver.query(uri, PROJECTION, whereClause, whereArgs, null)) { 100 if (cursor == null) { 101 LogUtil.e("TranscriptionDbHelper.getUntranscribedVoicemails", "query failed."); 102 } else { 103 while (cursor.moveToNext()) { 104 untranscribed.add(ContentUris.withAppendedId(uri, cursor.getLong(ID))); 105 } 106 } 107 } 108 return untranscribed; 109 } 110 111 @WorkerThread getTranscribingVoicemails()112 List<Uri> getTranscribingVoicemails() { 113 Assert.checkState(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O); 114 Assert.isWorkerThread(); 115 List<Uri> inProgress = new ArrayList<>(); 116 String whereClause = VoicemailCompat.TRANSCRIPTION_STATE + "=?"; 117 String[] whereArgs = {String.valueOf(VoicemailCompat.TRANSCRIPTION_IN_PROGRESS)}; 118 try (Cursor cursor = contentResolver.query(uri, PROJECTION, whereClause, whereArgs, null)) { 119 if (cursor == null) { 120 LogUtil.e("TranscriptionDbHelper.getTranscribingVoicemails", "query failed."); 121 } else { 122 while (cursor.moveToNext()) { 123 inProgress.add(ContentUris.withAppendedId(uri, cursor.getLong(ID))); 124 } 125 } 126 } 127 return inProgress; 128 } 129 130 @WorkerThread setTranscriptionState(int transcriptionState)131 void setTranscriptionState(int transcriptionState) { 132 Assert.isWorkerThread(); 133 LogUtil.i( 134 "TranscriptionDbHelper.setTranscriptionState", 135 "uri: " + uri + ", state: " + transcriptionState); 136 ContentValues values = new ContentValues(); 137 values.put(VoicemailCompat.TRANSCRIPTION_STATE, transcriptionState); 138 updateDatabase(values); 139 } 140 141 @WorkerThread setTranscriptionAndState(String transcription, int transcriptionState)142 void setTranscriptionAndState(String transcription, int transcriptionState) { 143 Assert.isWorkerThread(); 144 LogUtil.i( 145 "TranscriptionDbHelper.setTranscriptionAndState", 146 "uri: " + uri + ", state: " + transcriptionState); 147 ContentValues values = new ContentValues(); 148 values.put(Voicemails.TRANSCRIPTION, transcription); 149 values.put(VoicemailCompat.TRANSCRIPTION_STATE, transcriptionState); 150 updateDatabase(values); 151 } 152 updateDatabase(ContentValues values)153 private void updateDatabase(ContentValues values) { 154 int updatedCount = contentResolver.update(uri, values, null, null); 155 if (updatedCount != 1) { 156 LogUtil.e( 157 "TranscriptionDbHelper.updateDatabase", 158 "Wrong row count, should have updated 1 row, was: " + updatedCount); 159 } 160 } 161 } 162