summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2018-01-14 19:26:10 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-01-14 19:26:10 +0000
commit0123d0030fd6dcbb33020240217a40e641d60c5e (patch)
treee50dd75250358ee2cf1a86eecbbbef2e40daab79
parent25f24a79a24334e23706c2a8d69903820c622edb (diff)
parent9fbb81d83f24d6f7ad9832bc16c3a41065eb9337 (diff)
Merge "Make sure that voicemail transcriptions are processed serially"
-rw-r--r--java/com/android/voicemail/impl/AndroidManifest.xml4
-rw-r--r--java/com/android/voicemail/impl/transcribe/GetTranscriptReceiver.java83
-rw-r--r--java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java30
-rw-r--r--java/com/android/voicemail/impl/transcribe/TranscriptionService.java3
-rw-r--r--java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java22
5 files changed, 124 insertions, 18 deletions
diff --git a/java/com/android/voicemail/impl/AndroidManifest.xml b/java/com/android/voicemail/impl/AndroidManifest.xml
index e7ab5818e..1998d35f6 100644
--- a/java/com/android/voicemail/impl/AndroidManifest.xml
+++ b/java/com/android/voicemail/impl/AndroidManifest.xml
@@ -141,6 +141,10 @@
<receiver android:name="com.android.voicemail.impl.transcribe.GetTranscriptReceiver"
android:exported="false">
+ <intent-filter>
+ <action
+ android:name="com.android.voicemail.impl.transcribe.GetTranscriptReceiver.POLL_ALARM" />
+ </intent-filter>
</receiver>
</application>
</manifest>
diff --git a/java/com/android/voicemail/impl/transcribe/GetTranscriptReceiver.java b/java/com/android/voicemail/impl/transcribe/GetTranscriptReceiver.java
index cc204ff53..cbf165753 100644
--- a/java/com/android/voicemail/impl/transcribe/GetTranscriptReceiver.java
+++ b/java/com/android/voicemail/impl/transcribe/GetTranscriptReceiver.java
@@ -23,11 +23,13 @@ import android.content.Intent;
import android.net.Uri;
import android.os.SystemClock;
import android.support.annotation.Nullable;
+import android.telecom.PhoneAccountHandle;
import android.util.Pair;
import com.android.dialer.common.Assert;
import com.android.dialer.common.backoff.ExponentialBaseCalculator;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.voicemail.impl.VvmLog;
@@ -36,6 +38,7 @@ import com.android.voicemail.impl.transcribe.grpc.TranscriptionClient;
import com.android.voicemail.impl.transcribe.grpc.TranscriptionClientFactory;
import com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest;
import com.google.internal.communications.voicemailtranscription.v1.TranscriptionStatus;
+import java.util.List;
/**
* This class uses the AlarmManager to poll for the result of a voicemail transcription request.
@@ -50,6 +53,9 @@ public class GetTranscriptReceiver extends BroadcastReceiver {
static final String EXTRA_DELAY_MILLIS = "extra_delay_millis";
static final String EXTRA_BASE_MULTIPLIER = "extra_base_multiplier";
static final String EXTRA_REMAINING_ATTEMPTS = "extra_remaining_attempts";
+ static final String EXTRA_PHONE_ACCOUNT = "extra_phone_account";
+ static final String POLL_ALARM_ACTION =
+ "com.android.voicemail.impl.transcribe.GetTranscriptReceiver.POLL_ALARM";
// Schedule an initial alarm to begin checking for a voicemail transcription result.
static void beginPolling(
@@ -57,7 +63,9 @@ public class GetTranscriptReceiver extends BroadcastReceiver {
Uri voicemailUri,
String transcriptId,
long estimatedTranscriptionTimeMillis,
- TranscriptionConfigProvider configProvider) {
+ TranscriptionConfigProvider configProvider,
+ PhoneAccountHandle account) {
+ Assert.checkState(!hasPendingAlarm(context));
long initialDelayMillis = configProvider.getInitialGetTranscriptPollDelayMillis();
long maxBackoffMillis = configProvider.getMaxGetTranscriptPollTimeMillis();
int maxAttempts = configProvider.getMaxGetTranscriptPolls();
@@ -65,7 +73,13 @@ public class GetTranscriptReceiver extends BroadcastReceiver {
ExponentialBaseCalculator.findBase(initialDelayMillis, maxBackoffMillis, maxAttempts);
Intent intent =
makeAlarmIntent(
- context, voicemailUri, transcriptId, initialDelayMillis, baseMultiplier, maxAttempts);
+ context,
+ voicemailUri,
+ transcriptId,
+ initialDelayMillis,
+ baseMultiplier,
+ maxAttempts,
+ account);
// Add an extra to distinguish this initial estimated transcription wait from subsequent backoff
// waits
intent.putExtra(EXTRA_IS_INITIAL_ESTIMATED_WAIT, true);
@@ -77,9 +91,17 @@ public class GetTranscriptReceiver extends BroadcastReceiver {
scheduleAlarm(context, estimatedTranscriptionTimeMillis, intent);
}
+ static boolean hasPendingAlarm(Context context) {
+ Intent intent = makeBaseAlarmIntent(context);
+ return getPendingIntent(context, intent, PendingIntent.FLAG_NO_CREATE) != null;
+ }
+
// Alarm fired, poll for transcription result on a background thread
@Override
public void onReceive(Context context, Intent intent) {
+ if (intent == null || !POLL_ALARM_ACTION.equals(intent.getAction())) {
+ return;
+ }
String transcriptId = intent.getStringExtra(EXTRA_TRANSCRIPT_ID);
VvmLog.i(TAG, "onReceive, for transcript id: " + transcriptId);
DialerExecutorComponent.get(context)
@@ -101,7 +123,7 @@ public class GetTranscriptReceiver extends BroadcastReceiver {
private static void scheduleAlarm(Context context, long delayMillis, Intent intent) {
PendingIntent alarmIntent =
- PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ getPendingIntent(context, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmMgr.set(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
@@ -109,22 +131,46 @@ public class GetTranscriptReceiver extends BroadcastReceiver {
alarmIntent);
}
+ private static boolean cancelAlarm(Context context, Intent intent) {
+ PendingIntent alarmIntent = getPendingIntent(context, intent, PendingIntent.FLAG_NO_CREATE);
+ if (alarmIntent != null) {
+ AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ alarmMgr.cancel(alarmIntent);
+ alarmIntent.cancel();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
private static Intent makeAlarmIntent(
Context context,
Uri voicemailUri,
String transcriptId,
long delayMillis,
double baseMultiplier,
- int remainingAttempts) {
- Intent intent = new Intent(context, GetTranscriptReceiver.class);
+ int remainingAttempts,
+ PhoneAccountHandle account) {
+ Intent intent = makeBaseAlarmIntent(context);
intent.putExtra(EXTRA_VOICEMAIL_URI, voicemailUri);
intent.putExtra(EXTRA_TRANSCRIPT_ID, transcriptId);
intent.putExtra(EXTRA_DELAY_MILLIS, delayMillis);
intent.putExtra(EXTRA_BASE_MULTIPLIER, baseMultiplier);
intent.putExtra(EXTRA_REMAINING_ATTEMPTS, remainingAttempts);
+ intent.putExtra(EXTRA_PHONE_ACCOUNT, account);
+ return intent;
+ }
+
+ private static Intent makeBaseAlarmIntent(Context context) {
+ Intent intent = new Intent(context.getApplicationContext(), GetTranscriptReceiver.class);
+ intent.setAction(POLL_ALARM_ACTION);
return intent;
}
+ private static PendingIntent getPendingIntent(Context context, Intent intent, int flags) {
+ return PendingIntent.getBroadcast(context.getApplicationContext(), 0, intent, flags);
+ }
+
private static class PollWorker implements Worker<Intent, Void> {
private final Context context;
@@ -158,9 +204,33 @@ public class GetTranscriptReceiver extends BroadcastReceiver {
Uri voicemailUri = intent.getParcelableExtra(EXTRA_VOICEMAIL_URI);
TranscriptionDbHelper dbHelper = new TranscriptionDbHelper(context, voicemailUri);
TranscriptionTask.recordResult(context, result, dbHelper);
+
+ // Check if there are other pending transcriptions
+ PhoneAccountHandle account = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT);
+ processPendingTranscriptions(account);
return null;
}
+ private void processPendingTranscriptions(PhoneAccountHandle account) {
+ TranscriptionDbHelper dbHelper = new TranscriptionDbHelper(context);
+ List<Uri> inProgress = dbHelper.getTranscribingVoicemails();
+ if (!inProgress.isEmpty()) {
+ Uri uri = inProgress.get(0);
+ VvmLog.i(TAG, "getPendingTranscription, found pending transcription " + uri);
+ if (hasPendingAlarm(context)) {
+ // Cancel the current alarm so that the next transcription task won't be postponed
+ cancelAlarm(context, makeBaseAlarmIntent(context));
+ }
+ ThreadUtil.postOnUiThread(
+ () -> {
+ TranscriptionService.scheduleNewVoicemailTranscriptionJob(
+ context, uri, account, true);
+ });
+ } else {
+ VvmLog.i(TAG, "getPendingTranscription, no more pending transcriptions");
+ }
+ }
+
private Pair<String, TranscriptionStatus> pollForTranscription(String transcriptId) {
VvmLog.i(TAG, "pollForTranscription, transcript id: " + transcriptId);
GetTranscriptRequest request = getGetTranscriptRequest(transcriptId);
@@ -214,7 +284,8 @@ public class GetTranscriptReceiver extends BroadcastReceiver {
previous.getStringExtra(EXTRA_TRANSCRIPT_ID),
nextDelay,
baseMultiplier,
- remainingAttempts);
+ remainingAttempts,
+ previous.getParcelableExtra(EXTRA_PHONE_ACCOUNT));
}
}
diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java b/java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java
index a9a37225b..24c07cc37 100644
--- a/java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java
+++ b/java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java
@@ -22,11 +22,10 @@ import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Build.VERSION_CODES;
+import android.os.Build;
import android.provider.VoicemailContract.Voicemails;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
-import android.support.v4.os.BuildCompat;
import android.util.Pair;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
@@ -35,7 +34,7 @@ import java.util.ArrayList;
import java.util.List;
/** Helper class for reading and writing transcription data in the database */
-@TargetApi(VERSION_CODES.O)
+@TargetApi(Build.VERSION_CODES.O)
public class TranscriptionDbHelper {
@VisibleForTesting
static final String[] PROJECTION =
@@ -63,9 +62,8 @@ public class TranscriptionDbHelper {
}
@WorkerThread
- @TargetApi(VERSION_CODES.M) // used for try with resources
Pair<String, Integer> getTranscriptionAndState() {
- Assert.checkState(BuildCompat.isAtLeastO());
+ Assert.checkState(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O);
Assert.isWorkerThread();
try (Cursor cursor = contentResolver.query(uri, PROJECTION, null, null, null)) {
if (cursor == null) {
@@ -84,9 +82,8 @@ public class TranscriptionDbHelper {
}
@WorkerThread
- @TargetApi(VERSION_CODES.M) // used for try with resources
List<Uri> getUntranscribedVoicemails() {
- Assert.checkArgument(BuildCompat.isAtLeastO());
+ Assert.checkState(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O);
Assert.isWorkerThread();
List<Uri> untranscribed = new ArrayList<>();
String whereClause =
@@ -105,6 +102,25 @@ public class TranscriptionDbHelper {
}
@WorkerThread
+ List<Uri> getTranscribingVoicemails() {
+ Assert.checkState(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O);
+ Assert.isWorkerThread();
+ List<Uri> inProgress = new ArrayList<>();
+ String whereClause = VoicemailCompat.TRANSCRIPTION_STATE + "=?";
+ String[] whereArgs = {String.valueOf(VoicemailCompat.TRANSCRIPTION_IN_PROGRESS)};
+ try (Cursor cursor = contentResolver.query(uri, PROJECTION, whereClause, whereArgs, null)) {
+ if (cursor == null) {
+ LogUtil.e("TranscriptionDbHelper.getTranscribingVoicemails", "query failed.");
+ } else {
+ while (cursor.moveToNext()) {
+ inProgress.add(ContentUris.withAppendedId(uri, cursor.getLong(ID)));
+ }
+ }
+ }
+ return inProgress;
+ }
+
+ @WorkerThread
void setTranscriptionState(int transcriptionState) {
Assert.isWorkerThread();
LogUtil.i(
diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionService.java b/java/com/android/voicemail/impl/transcribe/TranscriptionService.java
index 0f5300358..c206c0818 100644
--- a/java/com/android/voicemail/impl/transcribe/TranscriptionService.java
+++ b/java/com/android/voicemail/impl/transcribe/TranscriptionService.java
@@ -63,8 +63,7 @@ public class TranscriptionService extends JobService {
}
// Schedule a task to transcribe the indicated voicemail, return true if transcription task was
- // scheduled. If the PhoneAccountHandle is null then the voicemail will not be considered for
- // donation.
+ // scheduled.
@MainThread
public static boolean scheduleNewVoicemailTranscriptionJob(
Context context, Uri voicemailUri, PhoneAccountHandle account, boolean highPriority) {
diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java b/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java
index bb7aa5f38..f6035fd2c 100644
--- a/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java
+++ b/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java
@@ -58,9 +58,24 @@ public class TranscriptionTaskAsync extends TranscriptionTask {
protected Pair<String, TranscriptionStatus> getTranscription() {
VvmLog.i(TAG, "getTranscription");
+ if (GetTranscriptReceiver.hasPendingAlarm(context)) {
+ // Don't start a transcription while another is still active
+ VvmLog.i(
+ TAG,
+ "getTranscription, pending transcription, postponing transcription of: " + voicemailUri);
+ return new Pair<>(null, null);
+ }
+
+ TranscribeVoicemailAsyncRequest uploadRequest = getUploadRequest();
+ VvmLog.i(
+ TAG,
+ "getTranscription, uploading voicemail: "
+ + voicemailUri
+ + ", id: "
+ + uploadRequest.getTranscriptionId());
TranscriptionResponseAsync uploadResponse =
(TranscriptionResponseAsync)
- sendRequest((client) -> client.sendUploadRequest(getUploadRequest()));
+ sendRequest((client) -> client.sendUploadRequest(uploadRequest));
if (cancelled) {
VvmLog.i(TAG, "getTranscription, cancelled.");
@@ -72,13 +87,14 @@ public class TranscriptionTaskAsync extends TranscriptionTask {
VvmLog.i(TAG, "getTranscription, upload error: " + uploadResponse.status);
return new Pair<>(null, TranscriptionStatus.FAILED_NO_RETRY);
} else {
- VvmLog.i(TAG, "getTranscription, begin polling for result.");
+ VvmLog.i(TAG, "getTranscription, begin polling for: " + uploadResponse.getTranscriptionId());
GetTranscriptReceiver.beginPolling(
context,
voicemailUri,
uploadResponse.getTranscriptionId(),
uploadResponse.getEstimatedWaitMillis(),
- configProvider);
+ configProvider,
+ phoneAccountHandle);
// This indicates that the result is not available yet
return new Pair<>(null, null);
}