From ec1a970dec22d68773f8ae9dbde6f17df6154e03 Mon Sep 17 00:00:00 2001 From: mdooley Date: Fri, 27 Oct 2017 16:20:32 -0700 Subject: internal change Bug: 62423454 Test: manual and updated unit test PiperOrigin-RevId: 173731907 Change-Id: Ic73600197b1c4fa6ac0937a8c38b048cd8faded8 --- java/com/android/voicemail/VoicemailClient.java | 10 ++++++ .../voicemail/impl/VoicemailClientImpl.java | 25 ++++++++++++++ .../impl/fetch/VoicemailFetchedCallback.java | 3 +- .../android/voicemail/impl/res/values/strings.xml | 17 ++++++++++ .../voicemail/impl/res/xml/voicemail_settings.xml | 6 ++++ .../impl/settings/VisualVoicemailSettingsUtil.java | 21 ++++++++++++ .../impl/settings/VoicemailSettingsFragment.java | 38 ++++++++++++++++++++++ .../transcribe/TranscriptionBackfillService.java | 2 +- .../transcribe/TranscriptionConfigProvider.java | 5 +++ .../impl/transcribe/TranscriptionService.java | 22 ++++++++++--- .../impl/transcribe/TranscriptionTask.java | 22 ++++++++++--- .../impl/transcribe/TranscriptionTaskAsync.java | 13 +++++++- .../voicemail/stub/StubVoicemailClient.java | 10 ++++++ 13 files changed, 183 insertions(+), 11 deletions(-) diff --git a/java/com/android/voicemail/VoicemailClient.java b/java/com/android/voicemail/VoicemailClient.java index d52a67a8e..717362e18 100644 --- a/java/com/android/voicemail/VoicemailClient.java +++ b/java/com/android/voicemail/VoicemailClient.java @@ -124,6 +124,16 @@ public interface VoicemailClient { void setVoicemailArchiveEnabled( Context context, PhoneAccountHandle phoneAccountHandle, boolean value); + /** + * @return if the voicemail transcription feature is available on the current device. This depends + * on whether the server side flag is turned on for the feature, and if the OS meets the + * requirement for this feature. + */ + boolean isVoicemailTranscriptionAvailable(Context context); + + /** @return if the voicemail donation setting has been enabled by the user. */ + boolean isVoicemailDonationEnabled(Context context, PhoneAccountHandle account); + /** * @return an intent that will launch the activity to change the voicemail PIN. The PIN is used * when calling into the mailbox. diff --git a/java/com/android/voicemail/impl/VoicemailClientImpl.java b/java/com/android/voicemail/impl/VoicemailClientImpl.java index 9bb14f2dc..ff1a18d32 100644 --- a/java/com/android/voicemail/impl/VoicemailClientImpl.java +++ b/java/com/android/voicemail/impl/VoicemailClientImpl.java @@ -37,6 +37,7 @@ import com.android.voicemail.impl.settings.VoicemailChangePinActivity; import com.android.voicemail.impl.settings.VoicemailSettingsFragment; import com.android.voicemail.impl.sync.VvmAccountManager; import com.android.voicemail.impl.transcribe.TranscriptionBackfillService; +import com.android.voicemail.impl.transcribe.TranscriptionConfigProvider; import java.util.List; import javax.inject.Inject; @@ -119,6 +120,30 @@ public class VoicemailClientImpl implements VoicemailClient { VisualVoicemailSettingsUtil.setArchiveEnabled(context, phoneAccountHandle, value); } + @Override + public boolean isVoicemailTranscriptionAvailable(Context context) { + if (!BuildCompat.isAtLeastO()) { + LogUtil.i( + "VoicemailClientImpl.isVoicemailTranscriptionAvailable", "not running on O or later"); + return false; + } + + TranscriptionConfigProvider provider = new TranscriptionConfigProvider(context); + if (!provider.isVoicemailTranscriptionEnabled()) { + LogUtil.i( + "VoicemailClientImpl.isVoicemailTranscriptionAvailable", "feature disabled by config"); + return false; + } + + return true; + } + + @Override + public boolean isVoicemailDonationEnabled(Context context, PhoneAccountHandle account) { + return isVoicemailTranscriptionAvailable(context) + && VisualVoicemailSettingsUtil.isVoicemailDonationEnabled(context, account); + } + @Override public Intent getSetPinIntent(Context context, PhoneAccountHandle phoneAccountHandle) { Intent intent = new Intent(context, VoicemailChangePinActivity.class); diff --git a/java/com/android/voicemail/impl/fetch/VoicemailFetchedCallback.java b/java/com/android/voicemail/impl/fetch/VoicemailFetchedCallback.java index 3e825407b..e8e14bedb 100644 --- a/java/com/android/voicemail/impl/fetch/VoicemailFetchedCallback.java +++ b/java/com/android/voicemail/impl/fetch/VoicemailFetchedCallback.java @@ -97,7 +97,8 @@ public class VoicemailFetchedCallback { if (updateVoicemail(values)) { ThreadUtil.postOnUiThread( () -> { - if (!TranscriptionService.scheduleNewVoicemailTranscriptionJob(mContext, mUri, true)) { + if (!TranscriptionService.scheduleNewVoicemailTranscriptionJob( + mContext, mUri, mPhoneAccountHandle, true)) { VvmLog.w(TAG, String.format("Failed to schedule transcription for %s", mUri)); } }); diff --git a/java/com/android/voicemail/impl/res/values/strings.xml b/java/com/android/voicemail/impl/res/values/strings.xml index 66c0e62b0..c70306d0d 100644 --- a/java/com/android/voicemail/impl/res/values/strings.xml +++ b/java/com/android/voicemail/impl/res/values/strings.xml @@ -42,6 +42,9 @@ archive_is_enabled + + donate_voicemails + voicemail_change_pin_key @@ -53,6 +56,20 @@ Extra backup and storage + + + Voicemail transcription analysis + + + Visual voicemail must be enabled to donate voicemails + + Visual voicemail is not activated yet, please try again later + + Let Google review your voicemail messages to improve transcription quality + Set PIN diff --git a/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml b/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml index 50510905c..9b0391ad4 100644 --- a/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml +++ b/java/com/android/voicemail/impl/res/xml/voicemail_settings.xml @@ -29,6 +29,12 @@ android:key="@string/voicemail_visual_voicemail_archive_key" android:dependency="@string/voicemail_visual_voicemail_key" android:title="@string/voicemail_visual_voicemail_auto_archive_switch_title"/>" + + " + diff --git a/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java b/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java index ae526d168..6694a5db8 100644 --- a/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java +++ b/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java @@ -57,6 +57,18 @@ public class VisualVoicemailSettingsUtil { .apply(); } + public static void setVoicemailDonationEnabled( + Context context, PhoneAccountHandle phoneAccount, boolean isEnabled) { + Assert.checkArgument( + VoicemailComponent.get(context) + .getVoicemailClient() + .isVoicemailTranscriptionAvailable(context)); + new VisualVoicemailPreferences(context, phoneAccount) + .edit() + .putBoolean(context.getString(R.string.voicemail_visual_voicemail_donation_key), isEnabled) + .apply(); + } + public static boolean isEnabled(Context context, PhoneAccountHandle phoneAccount) { if (phoneAccount == null) { return false; @@ -79,6 +91,15 @@ public class VisualVoicemailSettingsUtil { context.getString(R.string.voicemail_visual_voicemail_archive_key), false); } + public static boolean isVoicemailDonationEnabled( + Context context, PhoneAccountHandle phoneAccount) { + Assert.isNotNull(phoneAccount); + + VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount); + return prefs.getBoolean( + context.getString(R.string.voicemail_visual_voicemail_donation_key), false); + } + /** * Whether the client enabled status is explicitly set by user or by default(Whether carrier VVM * app is installed). This is used to determine whether to disable the client when the carrier VVM diff --git a/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java b/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java index e2ea72569..465223811 100644 --- a/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java +++ b/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java @@ -53,6 +53,7 @@ public class VoicemailSettingsFragment extends PreferenceFragment private Preference voicemailNotificationPreference; private SwitchPreference voicemailVisualVoicemail; private SwitchPreference autoArchiveSwitchPreference; + private SwitchPreference donateVoicemailSwitchPreference; private Preference voicemailChangePinPreference; private PreferenceScreen advancedSettings; @@ -102,12 +103,22 @@ public class VoicemailSettingsFragment extends PreferenceFragment (SwitchPreference) findPreference(getString(R.string.voicemail_visual_voicemail_archive_key)); + donateVoicemailSwitchPreference = + (SwitchPreference) + findPreference(getString(R.string.voicemail_visual_voicemail_donation_key)); + if (!VoicemailComponent.get(getContext()) .getVoicemailClient() .isVoicemailArchiveAvailable(getContext())) { getPreferenceScreen().removePreference(autoArchiveSwitchPreference); } + if (!VoicemailComponent.get(getContext()) + .getVoicemailClient() + .isVoicemailDonationEnabled(getContext(), phoneAccountHandle)) { + getPreferenceScreen().removePreference(donateVoicemailSwitchPreference); + } + voicemailChangePinPreference = findPreference(getString(R.string.voicemail_change_pin_key)); if (omtpVvmCarrierConfigHelper.isValid()) { @@ -141,9 +152,15 @@ public class VoicemailSettingsFragment extends PreferenceFragment autoArchiveSwitchPreference.setOnPreferenceChangeListener(this); autoArchiveSwitchPreference.setChecked( VisualVoicemailSettingsUtil.isArchiveEnabled(getContext(), phoneAccountHandle)); + + donateVoicemailSwitchPreference.setOnPreferenceChangeListener(this); + donateVoicemailSwitchPreference.setChecked( + VisualVoicemailSettingsUtil.isVoicemailDonationEnabled(getContext(), phoneAccountHandle)); + updateDonateVoicemail(); } else { prefSet.removePreference(voicemailVisualVoicemail); prefSet.removePreference(autoArchiveSwitchPreference); + prefSet.removePreference(donateVoicemailSwitchPreference); prefSet.removePreference(voicemailChangePinPreference); } @@ -192,10 +209,15 @@ public class VoicemailSettingsFragment extends PreferenceFragment } updateChangePin(); + updateDonateVoicemail(); } else if (preference.getKey().equals(autoArchiveSwitchPreference.getKey())) { logArchiveToggle((boolean) objValue); VisualVoicemailSettingsUtil.setArchiveEnabled( getContext(), phoneAccountHandle, (boolean) objValue); + } else if (preference.getKey().equals(donateVoicemailSwitchPreference.getKey())) { + logArchiveToggle((boolean) objValue); + VisualVoicemailSettingsUtil.setVoicemailDonationEnabled( + getContext(), phoneAccountHandle, (boolean) objValue); } // Always let the preference setting proceed. @@ -217,6 +239,21 @@ public class VoicemailSettingsFragment extends PreferenceFragment } } + private void updateDonateVoicemail() { + if (!VisualVoicemailSettingsUtil.isEnabled(getContext(), phoneAccountHandle)) { + donateVoicemailSwitchPreference.setSummary( + R.string.voicemail_donate_preference_summary_disable); + donateVoicemailSwitchPreference.setEnabled(false); + } else if (!VvmAccountManager.isAccountActivated(getContext(), phoneAccountHandle)) { + donateVoicemailSwitchPreference.setSummary( + R.string.voicemail_donate_preference_summary_not_activated); + donateVoicemailSwitchPreference.setEnabled(false); + } else { + donateVoicemailSwitchPreference.setSummary(R.string.voicemail_donate_preference_summary_info); + donateVoicemailSwitchPreference.setEnabled(true); + } + } + private void logArchiveToggle(boolean userTurnedOn) { if (userTurnedOn) { Logger.get(getContext()) @@ -231,6 +268,7 @@ public class VoicemailSettingsFragment extends PreferenceFragment public void onActivationStateChanged(PhoneAccountHandle phoneAccountHandle, boolean isActivated) { if (this.phoneAccountHandle.equals(phoneAccountHandle)) { updateChangePin(); + updateDonateVoicemail(); } } diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java b/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java index f3c6e64f4..f7f643932 100644 --- a/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java @@ -72,7 +72,7 @@ public class TranscriptionBackfillService extends JobIntentService { for (Uri uri : untranscribed) { ThreadUtil.postOnUiThread( () -> { - TranscriptionService.scheduleNewVoicemailTranscriptionJob(this, uri, false); + TranscriptionService.scheduleNewVoicemailTranscriptionJob(this, uri, null, false); }); } } diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionConfigProvider.java b/java/com/android/voicemail/impl/transcribe/TranscriptionConfigProvider.java index 4bb9a261b..5da450312 100644 --- a/java/com/android/voicemail/impl/transcribe/TranscriptionConfigProvider.java +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionConfigProvider.java @@ -75,6 +75,11 @@ public class TranscriptionConfigProvider { .getLong("voicemail_transcription_get_transcript_poll_interval_millis", 1000L); } + public boolean isVoicemailDonationEnabled() { + return ConfigProviderBindings.get(context) + .getBoolean("voicemail_transcription_donation_enabled", false); + } + @Override public String toString() { return String.format( diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionService.java b/java/com/android/voicemail/impl/transcribe/TranscriptionService.java index b733928d7..79e1a017c 100644 --- a/java/com/android/voicemail/impl/transcribe/TranscriptionService.java +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionService.java @@ -25,8 +25,10 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; import android.support.annotation.MainThread; +import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.v4.os.BuildCompat; +import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; @@ -44,6 +46,7 @@ import java.util.concurrent.Executors; */ public class TranscriptionService extends JobService { @VisibleForTesting static final String EXTRA_VOICEMAIL_URI = "extra_voicemail_uri"; + @VisibleForTesting static final String EXTRA_ACCOUNT_HANDLE = "extra_account_handle"; private ExecutorService executorService; private JobParameters jobParameters; @@ -58,10 +61,14 @@ public class TranscriptionService extends JobService { } // Schedule a task to transcribe the indicated voicemail, return true if transcription task was - // scheduled. + // scheduled. If the PhoneAccountHandle is null then the voicemail will not be considered for + // donation. @MainThread public static boolean scheduleNewVoicemailTranscriptionJob( - Context context, Uri voicemailUri, boolean highPriority) { + Context context, + Uri voicemailUri, + @Nullable PhoneAccountHandle account, + boolean highPriority) { Assert.isMainThread(); if (BuildCompat.isAtLeastO()) { LogUtil.i( @@ -80,7 +87,7 @@ public class TranscriptionService extends JobService { builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); } JobScheduler scheduler = context.getSystemService(JobScheduler.class); - JobWorkItem workItem = makeWorkItem(voicemailUri); + JobWorkItem workItem = makeWorkItem(voicemailUri, account); return scheduler.enqueue(builder.build(), workItem) == JobScheduler.RESULT_SUCCESS; } else { LogUtil.i("TranscriptionService.scheduleNewVoicemailTranscriptionJob", "not supported"); @@ -193,6 +200,10 @@ public class TranscriptionService extends JobService { return workItem.getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI); } + static PhoneAccountHandle getPhoneAccountHandle(JobWorkItem workItem) { + return workItem.getIntent().getParcelableExtra(EXTRA_ACCOUNT_HANDLE); + } + private ExecutorService getExecutorService() { if (executorService == null) { // The common use case is transcribing a single voicemail so just use a single thread executor @@ -219,9 +230,12 @@ public class TranscriptionService extends JobService { } } - private static JobWorkItem makeWorkItem(Uri voicemailUri) { + private static JobWorkItem makeWorkItem(Uri voicemailUri, PhoneAccountHandle account) { Intent intent = new Intent(); intent.putExtra(EXTRA_VOICEMAIL_URI, voicemailUri); + if (account != null) { + intent.putExtra(EXTRA_ACCOUNT_HANDLE, account); + } return new JobWorkItem(intent); } diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionTask.java b/java/com/android/voicemail/impl/transcribe/TranscriptionTask.java index a93c65151..f3b1d587f 100644 --- a/java/com/android/voicemail/impl/transcribe/TranscriptionTask.java +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionTask.java @@ -20,6 +20,8 @@ import android.app.job.JobWorkItem; import android.content.Context; import android.net.Uri; import android.support.annotation.MainThread; +import android.support.annotation.VisibleForTesting; +import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import android.util.Pair; import com.android.dialer.common.Assert; @@ -62,6 +64,7 @@ public abstract class TranscriptionTask implements Runnable { private final JobWorkItem workItem; private final TranscriptionClientFactory clientFactory; private final Uri voicemailUri; + protected final PhoneAccountHandle phoneAccountHandle; private final TranscriptionDbHelper databaseHelper; protected final TranscriptionConfigProvider configProvider; protected ByteString audioData; @@ -86,6 +89,7 @@ public abstract class TranscriptionTask implements Runnable { this.workItem = workItem; this.clientFactory = clientFactory; this.voicemailUri = TranscriptionService.getVoicemailUri(workItem); + this.phoneAccountHandle = TranscriptionService.getPhoneAccountHandle(workItem); this.configProvider = configProvider; databaseHelper = new TranscriptionDbHelper(context, voicemailUri); } @@ -240,14 +244,24 @@ public abstract class TranscriptionTask implements Runnable { return false; } - if (audioData.startsWith(ByteString.copyFromUtf8(AMR_PREFIX))) { - encoding = AudioFormat.AMR_NB_8KHZ; - } else { + encoding = getAudioFormat(audioData); + if (encoding == AudioFormat.AUDIO_FORMAT_UNSPECIFIED) { VvmLog.i(TAG, "Transcriber.readAndValidateAudioFile, unknown encoding"); - encoding = AudioFormat.AUDIO_FORMAT_UNSPECIFIED; return false; } return true; } + + private static AudioFormat getAudioFormat(ByteString audioData) { + return audioData != null && audioData.startsWith(ByteString.copyFromUtf8(AMR_PREFIX)) + ? AudioFormat.AMR_NB_8KHZ + : AudioFormat.AUDIO_FORMAT_UNSPECIFIED; + } + + @VisibleForTesting + void setAudioDataForTesting(ByteString audioData) { + this.audioData = audioData; + encoding = getAudioFormat(audioData); + } } diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java b/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java index e75728014..f946607b5 100644 --- a/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java @@ -21,11 +21,13 @@ import android.util.Pair; import com.android.dialer.common.Assert; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; +import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.transcribe.TranscriptionService.JobCallback; import com.android.voicemail.impl.transcribe.grpc.GetTranscriptResponseAsync; import com.android.voicemail.impl.transcribe.grpc.TranscriptionClientFactory; import com.android.voicemail.impl.transcribe.grpc.TranscriptionResponseAsync; +import com.google.internal.communications.voicemailtranscription.v1.DonationPreference; import com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest; import com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest; import com.google.internal.communications.voicemailtranscription.v1.TranscriptionStatus; @@ -119,13 +121,22 @@ public class TranscriptionTaskAsync extends TranscriptionTask { return new Pair<>(null, TranscriptionStatus.FAILED_NO_RETRY); } - private TranscribeVoicemailAsyncRequest getUploadRequest() { + TranscribeVoicemailAsyncRequest getUploadRequest() { return TranscribeVoicemailAsyncRequest.newBuilder() .setVoicemailData(audioData) .setAudioFormat(encoding) + .setDonationPreference( + isDonationEnabled() ? DonationPreference.DONATE : DonationPreference.DO_NOT_DONATE) .build(); } + private boolean isDonationEnabled() { + return phoneAccountHandle != null + && VoicemailComponent.get(context) + .getVoicemailClient() + .isVoicemailDonationEnabled(context, phoneAccountHandle); + } + private GetTranscriptRequest getGetTranscriptRequest(TranscriptionResponseAsync uploadResponse) { Assert.checkArgument(uploadResponse.getTranscriptionId() != null); return GetTranscriptRequest.newBuilder() diff --git a/java/com/android/voicemail/stub/StubVoicemailClient.java b/java/com/android/voicemail/stub/StubVoicemailClient.java index c2c7a6d38..4b8ed9ab8 100644 --- a/java/com/android/voicemail/stub/StubVoicemailClient.java +++ b/java/com/android/voicemail/stub/StubVoicemailClient.java @@ -75,6 +75,16 @@ public final class StubVoicemailClient implements VoicemailClient { public void setVoicemailArchiveEnabled( Context context, PhoneAccountHandle phoneAccountHandle, boolean value) {} + @Override + public boolean isVoicemailTranscriptionAvailable(Context context) { + return false; + } + + @Override + public boolean isVoicemailDonationEnabled(Context context, PhoneAccountHandle account) { + return false; + } + @Override public Intent getSetPinIntent(Context context, PhoneAccountHandle phoneAccountHandle) { Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL); -- cgit v1.2.3