From 2ca4318cc1ee57dda907ba2069bd61d162b1baef Mon Sep 17 00:00:00 2001 From: Eric Erfanian Date: Thu, 31 Aug 2017 06:57:16 -0700 Subject: Update Dialer source to latest internal Google revision. Previously, Android's Dialer app was developed in an internal Google source control system and only exported to public during AOSP drops. The Dialer team is now switching to a public development model similar to the telephony team. This CL represents all internal Google changes that were committed to Dialer between the public O release and today's tip of tree on internal master. This CL squashes those changes into a single commit. In subsequent changes, changes will be exported on a per-commit basis. Test: make, flash install, run Merged-In: I45270eaa8ce732d71a1bd84b08c7fa0e99af3160 Change-Id: I529aaeb88535b9533c0ae4ef4e6c1222d4e0f1c8 PiperOrigin-RevId: 167068436 --- .../com/android/voicemail/impl/ActivationTask.java | 3 +- .../com/android/voicemail/impl/AndroidManifest.xml | 25 +- .../impl/DeviceProvisionedJobService.java | 33 +- java/com/android/voicemail/impl/OmtpConstants.java | 37 +- java/com/android/voicemail/impl/OmtpReceiver.java | 105 ------ java/com/android/voicemail/impl/OmtpService.java | 52 ++- .../voicemail/impl/OmtpVvmCarrierConfigHelper.java | 56 ++- .../voicemail/impl/PackageReplacedReceiver.java | 43 +++ .../voicemail/impl/SubscriptionInfoHelper.java | 70 ---- .../voicemail/impl/TelephonyManagerStub.java | 40 --- .../voicemail/impl/TelephonyVvmConfigManager.java | 2 +- .../voicemail/impl/VoicemailBootReceiver.java | 31 -- .../voicemail/impl/VoicemailClientImpl.java | 38 +- .../voicemail/impl/VoicemailClientReceiver.java | 6 + .../android/voicemail/impl/VoicemailModule.java | 3 +- .../android/voicemail/impl/VoicemailStatus.java | 3 +- .../impl/VoicemailTranscriptionServiceGrpc.java | 390 ++++++++++++++++++++ .../voicemail/impl/VvmPackageInstallReceiver.java | 80 ----- .../voicemail/impl/VvmPhoneStateListener.java | 5 +- .../voicemail/impl/configui/AndroidManifest.xml | 25 ++ .../impl/configui/ConfigOverrideFragment.java | 178 +++++++++ .../impl/configui/VoicemailSecretCodeActivity.java | 58 +++ .../impl/configui/res/values-af/strings.xml | 19 + .../impl/configui/res/values-am/strings.xml | 19 + .../impl/configui/res/values-ar/strings.xml | 19 + .../impl/configui/res/values-az/strings.xml | 19 + .../impl/configui/res/values-b+sr+Latn/strings.xml | 19 + .../impl/configui/res/values-be/strings.xml | 19 + .../impl/configui/res/values-bg/strings.xml | 19 + .../impl/configui/res/values-bn/strings.xml | 19 + .../impl/configui/res/values-bs/strings.xml | 19 + .../impl/configui/res/values-ca/strings.xml | 19 + .../impl/configui/res/values-cs/strings.xml | 19 + .../impl/configui/res/values-da/strings.xml | 19 + .../impl/configui/res/values-de/strings.xml | 19 + .../impl/configui/res/values-el/strings.xml | 19 + .../impl/configui/res/values-en-rAU/strings.xml | 19 + .../impl/configui/res/values-en-rGB/strings.xml | 19 + .../impl/configui/res/values-en-rIN/strings.xml | 19 + .../impl/configui/res/values-es-rUS/strings.xml | 19 + .../impl/configui/res/values-es/strings.xml | 19 + .../impl/configui/res/values-et/strings.xml | 19 + .../impl/configui/res/values-eu/strings.xml | 19 + .../impl/configui/res/values-fa/strings.xml | 19 + .../impl/configui/res/values-fi/strings.xml | 19 + .../impl/configui/res/values-fr-rCA/strings.xml | 19 + .../impl/configui/res/values-fr/strings.xml | 19 + .../impl/configui/res/values-gl/strings.xml | 19 + .../impl/configui/res/values-gu/strings.xml | 19 + .../impl/configui/res/values-hi/strings.xml | 19 + .../impl/configui/res/values-hr/strings.xml | 19 + .../impl/configui/res/values-hu/strings.xml | 19 + .../impl/configui/res/values-hy/strings.xml | 19 + .../impl/configui/res/values-in/strings.xml | 19 + .../impl/configui/res/values-is/strings.xml | 19 + .../impl/configui/res/values-it/strings.xml | 19 + .../impl/configui/res/values-iw/strings.xml | 19 + .../impl/configui/res/values-ja/strings.xml | 19 + .../impl/configui/res/values-ka/strings.xml | 19 + .../impl/configui/res/values-kk/strings.xml | 19 + .../impl/configui/res/values-km/strings.xml | 19 + .../impl/configui/res/values-kn/strings.xml | 19 + .../impl/configui/res/values-ko/strings.xml | 19 + .../impl/configui/res/values-ky/strings.xml | 19 + .../impl/configui/res/values-lo/strings.xml | 19 + .../impl/configui/res/values-lt/strings.xml | 19 + .../impl/configui/res/values-lv/strings.xml | 19 + .../impl/configui/res/values-mk/strings.xml | 19 + .../impl/configui/res/values-ml/strings.xml | 19 + .../impl/configui/res/values-mn/strings.xml | 19 + .../impl/configui/res/values-mr/strings.xml | 19 + .../impl/configui/res/values-ms/strings.xml | 19 + .../impl/configui/res/values-my/strings.xml | 19 + .../impl/configui/res/values-nb/strings.xml | 19 + .../impl/configui/res/values-ne/strings.xml | 19 + .../impl/configui/res/values-nl/strings.xml | 19 + .../impl/configui/res/values-no/strings.xml | 19 + .../impl/configui/res/values-pa/strings.xml | 19 + .../impl/configui/res/values-pl/strings.xml | 19 + .../impl/configui/res/values-pt-rBR/strings.xml | 19 + .../impl/configui/res/values-pt-rPT/strings.xml | 19 + .../impl/configui/res/values-pt/strings.xml | 19 + .../impl/configui/res/values-ro/strings.xml | 19 + .../impl/configui/res/values-ru/strings.xml | 19 + .../impl/configui/res/values-si/strings.xml | 19 + .../impl/configui/res/values-sk/strings.xml | 19 + .../impl/configui/res/values-sl/strings.xml | 19 + .../impl/configui/res/values-sq/strings.xml | 19 + .../impl/configui/res/values-sr/strings.xml | 19 + .../impl/configui/res/values-sv/strings.xml | 19 + .../impl/configui/res/values-sw/strings.xml | 19 + .../impl/configui/res/values-ta/strings.xml | 19 + .../impl/configui/res/values-te/strings.xml | 19 + .../impl/configui/res/values-th/strings.xml | 19 + .../impl/configui/res/values-tl/strings.xml | 19 + .../impl/configui/res/values-tr/strings.xml | 19 + .../impl/configui/res/values-uk/strings.xml | 19 + .../impl/configui/res/values-ur/strings.xml | 19 + .../impl/configui/res/values-uz/strings.xml | 19 + .../impl/configui/res/values-vi/strings.xml | 19 + .../impl/configui/res/values-zh-rCN/strings.xml | 19 + .../impl/configui/res/values-zh-rHK/strings.xml | 19 + .../impl/configui/res/values-zh-rTW/strings.xml | 19 + .../impl/configui/res/values-zu/strings.xml | 19 + .../voicemail/impl/configui/res/values/strings.xml | 21 ++ .../impl/configui/res/xml/vvm_config_override.xml | 76 ++++ .../impl/fetch/VoicemailFetchedCallback.java | 18 +- .../android/voicemail/impl/imap/ImapHelper.java | 19 +- .../android/voicemail/impl/mail/MailTransport.java | 5 + java/com/android/voicemail/impl/mail/Message.java | 4 + .../voicemail/impl/mail/internet/MimeHeader.java | 1 + .../voicemail/impl/mail/internet/MimeMessage.java | 24 ++ .../impl/mail/store/imap/ImapConstants.java | 2 +- java/com/android/voicemail/impl/proguard.flags | 4 + .../voicemail/impl/protocol/OmtpProtocol.java | 2 +- .../voicemail/impl/protocol/Vvm3Subscriber.java | 2 +- .../voicemail/impl/res/values-af/strings.xml | 2 - .../voicemail/impl/res/values-am/strings.xml | 2 - .../voicemail/impl/res/values-ar/strings.xml | 4 +- .../voicemail/impl/res/values-az/strings.xml | 2 - .../impl/res/values-b+sr+Latn/strings.xml | 2 - .../voicemail/impl/res/values-be/strings.xml | 2 - .../voicemail/impl/res/values-bg/strings.xml | 2 - .../voicemail/impl/res/values-bn/strings.xml | 2 - .../voicemail/impl/res/values-bs/strings.xml | 2 - .../voicemail/impl/res/values-ca/strings.xml | 2 - .../voicemail/impl/res/values-cs/strings.xml | 2 - .../voicemail/impl/res/values-da/strings.xml | 2 - .../voicemail/impl/res/values-de/strings.xml | 2 - .../voicemail/impl/res/values-el/strings.xml | 2 - .../voicemail/impl/res/values-en-rAU/strings.xml | 2 - .../voicemail/impl/res/values-en-rGB/strings.xml | 2 - .../voicemail/impl/res/values-en-rIN/strings.xml | 2 - .../voicemail/impl/res/values-es-rUS/strings.xml | 2 - .../voicemail/impl/res/values-es/strings.xml | 2 - .../voicemail/impl/res/values-et/strings.xml | 2 - .../voicemail/impl/res/values-eu/strings.xml | 2 - .../voicemail/impl/res/values-fa/strings.xml | 2 - .../voicemail/impl/res/values-fi/strings.xml | 2 - .../voicemail/impl/res/values-fr-rCA/strings.xml | 2 - .../voicemail/impl/res/values-fr/strings.xml | 2 - .../voicemail/impl/res/values-gl/strings.xml | 2 - .../voicemail/impl/res/values-gu/strings.xml | 2 - .../voicemail/impl/res/values-hi/strings.xml | 2 - .../voicemail/impl/res/values-hr/strings.xml | 2 - .../voicemail/impl/res/values-hu/strings.xml | 2 - .../voicemail/impl/res/values-hy/strings.xml | 2 - .../voicemail/impl/res/values-in/strings.xml | 2 - .../voicemail/impl/res/values-is/strings.xml | 2 - .../voicemail/impl/res/values-it/strings.xml | 2 - .../voicemail/impl/res/values-iw/strings.xml | 2 - .../voicemail/impl/res/values-ja/strings.xml | 2 - .../voicemail/impl/res/values-ka/strings.xml | 2 - .../voicemail/impl/res/values-kk/strings.xml | 2 - .../voicemail/impl/res/values-km/strings.xml | 2 - .../voicemail/impl/res/values-kn/strings.xml | 2 - .../voicemail/impl/res/values-ko/strings.xml | 2 - .../voicemail/impl/res/values-ky/strings.xml | 2 - .../voicemail/impl/res/values-lo/strings.xml | 2 - .../voicemail/impl/res/values-lt/strings.xml | 2 - .../voicemail/impl/res/values-lv/strings.xml | 2 - .../voicemail/impl/res/values-mk/strings.xml | 2 - .../voicemail/impl/res/values-ml/strings.xml | 2 - .../voicemail/impl/res/values-mn/strings.xml | 2 - .../voicemail/impl/res/values-mr/strings.xml | 4 +- .../voicemail/impl/res/values-ms/strings.xml | 2 - .../voicemail/impl/res/values-my/strings.xml | 2 - .../voicemail/impl/res/values-nb/strings.xml | 2 - .../voicemail/impl/res/values-ne/strings.xml | 2 - .../voicemail/impl/res/values-nl/strings.xml | 2 - .../voicemail/impl/res/values-no/strings.xml | 2 - .../voicemail/impl/res/values-pa/strings.xml | 2 - .../voicemail/impl/res/values-pl/strings.xml | 2 - .../voicemail/impl/res/values-pt-rBR/strings.xml | 2 - .../voicemail/impl/res/values-pt-rPT/strings.xml | 2 - .../voicemail/impl/res/values-pt/strings.xml | 2 - .../voicemail/impl/res/values-ro/strings.xml | 2 - .../voicemail/impl/res/values-ru/strings.xml | 2 - .../voicemail/impl/res/values-si/strings.xml | 2 - .../voicemail/impl/res/values-sk/strings.xml | 2 - .../voicemail/impl/res/values-sl/strings.xml | 2 - .../voicemail/impl/res/values-sq/strings.xml | 2 - .../voicemail/impl/res/values-sr/strings.xml | 2 - .../voicemail/impl/res/values-sv/strings.xml | 2 - .../voicemail/impl/res/values-sw/strings.xml | 2 - .../voicemail/impl/res/values-ta/strings.xml | 2 - .../voicemail/impl/res/values-te/strings.xml | 2 - .../voicemail/impl/res/values-th/strings.xml | 2 - .../voicemail/impl/res/values-tl/strings.xml | 2 - .../voicemail/impl/res/values-tr/strings.xml | 2 - .../voicemail/impl/res/values-uk/strings.xml | 2 - .../voicemail/impl/res/values-ur/strings.xml | 2 - .../voicemail/impl/res/values-uz/strings.xml | 2 - .../voicemail/impl/res/values-vi/strings.xml | 2 - .../voicemail/impl/res/values-zh-rCN/strings.xml | 2 - .../voicemail/impl/res/values-zh-rHK/strings.xml | 2 - .../voicemail/impl/res/values-zh-rTW/strings.xml | 2 - .../voicemail/impl/res/values-zu/strings.xml | 2 - .../android/voicemail/impl/res/values/strings.xml | 9 +- .../voicemail/impl/scheduling/TaskExecutor.java | 10 +- .../impl/scheduling/TaskSchedulerJobService.java | 4 +- .../impl/scheduling/TaskSchedulerService.java | 400 --------------------- .../impl/settings/VoicemailSettingsFragment.java | 18 +- .../voicemail/impl/sms/LegacyModeSmsHandler.java | 1 + .../voicemail/impl/sms/OmtpMessageReceiver.java | 7 +- .../voicemail/impl/sms/OmtpMessageSender.java | 6 + .../voicemail/impl/sync/OmtpVvmSyncReceiver.java | 2 +- .../voicemail/impl/sync/OmtpVvmSyncService.java | 131 +++---- .../android/voicemail/impl/sync/SyncOneTask.java | 7 +- java/com/android/voicemail/impl/sync/SyncTask.java | 9 +- .../android/voicemail/impl/sync/UploadTask.java | 6 +- .../voicemail/impl/sync/VoicemailsQueryHelper.java | 11 - .../voicemail/impl/sync/VvmAccountManager.java | 61 +++- .../impl/sync/VvmNetworkRequestCallback.java | 2 +- .../transcribe/TranscriptionBackfillService.java | 85 +++++ .../transcribe/TranscriptionConfigProvider.java | 90 +++++ .../impl/transcribe/TranscriptionDbHelper.java | 137 +++++++ .../impl/transcribe/TranscriptionService.java | 223 ++++++++++++ .../impl/transcribe/TranscriptionTask.java | 225 ++++++++++++ .../impl/transcribe/TranscriptionTaskAsync.java | 123 +++++++ .../impl/transcribe/TranscriptionTaskSync.java | 69 ++++ .../voicemail/impl/transcribe/VoicemailCompat.java | 59 +++ .../grpc/GetTranscriptResponseAsync.java | 102 ++++++ .../impl/transcribe/grpc/TranscriptionClient.java | 61 ++++ .../grpc/TranscriptionClientFactory.java | 196 ++++++++++ .../transcribe/grpc/TranscriptionResponse.java | 53 +++ .../grpc/TranscriptionResponseAsync.java | 53 +++ .../transcribe/grpc/TranscriptionResponseSync.java | 43 +++ .../transcribe/grpc/voicemail_transcription.proto | 133 +++++++ 229 files changed, 4432 insertions(+), 1091 deletions(-) delete mode 100644 java/com/android/voicemail/impl/OmtpReceiver.java create mode 100644 java/com/android/voicemail/impl/PackageReplacedReceiver.java delete mode 100644 java/com/android/voicemail/impl/SubscriptionInfoHelper.java delete mode 100644 java/com/android/voicemail/impl/TelephonyManagerStub.java delete mode 100644 java/com/android/voicemail/impl/VoicemailBootReceiver.java create mode 100644 java/com/android/voicemail/impl/VoicemailTranscriptionServiceGrpc.java delete mode 100644 java/com/android/voicemail/impl/VvmPackageInstallReceiver.java create mode 100644 java/com/android/voicemail/impl/configui/AndroidManifest.xml create mode 100644 java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java create mode 100644 java/com/android/voicemail/impl/configui/VoicemailSecretCodeActivity.java create mode 100644 java/com/android/voicemail/impl/configui/res/values-af/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-am/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ar/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-az/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-b+sr+Latn/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-be/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-bg/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-bn/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-bs/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ca/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-cs/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-da/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-de/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-el/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-en-rAU/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-en-rGB/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-en-rIN/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-es-rUS/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-es/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-et/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-eu/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-fa/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-fi/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-fr-rCA/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-fr/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-gl/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-gu/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-hi/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-hr/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-hu/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-hy/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-in/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-is/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-it/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-iw/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ja/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ka/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-kk/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-km/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-kn/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ko/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ky/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-lo/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-lt/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-lv/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-mk/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ml/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-mn/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-mr/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ms/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-my/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-nb/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ne/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-nl/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-no/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-pa/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-pl/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-pt-rBR/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-pt-rPT/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-pt/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ro/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ru/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-si/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-sk/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-sl/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-sq/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-sr/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-sv/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-sw/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ta/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-te/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-th/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-tl/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-tr/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-uk/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-ur/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-uz/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-vi/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-zh-rCN/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-zh-rHK/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-zh-rTW/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values-zu/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/values/strings.xml create mode 100644 java/com/android/voicemail/impl/configui/res/xml/vvm_config_override.xml create mode 100644 java/com/android/voicemail/impl/proguard.flags delete mode 100644 java/com/android/voicemail/impl/scheduling/TaskSchedulerService.java create mode 100644 java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java create mode 100644 java/com/android/voicemail/impl/transcribe/TranscriptionConfigProvider.java create mode 100644 java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java create mode 100644 java/com/android/voicemail/impl/transcribe/TranscriptionService.java create mode 100644 java/com/android/voicemail/impl/transcribe/TranscriptionTask.java create mode 100644 java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java create mode 100644 java/com/android/voicemail/impl/transcribe/TranscriptionTaskSync.java create mode 100644 java/com/android/voicemail/impl/transcribe/VoicemailCompat.java create mode 100644 java/com/android/voicemail/impl/transcribe/grpc/GetTranscriptResponseAsync.java create mode 100644 java/com/android/voicemail/impl/transcribe/grpc/TranscriptionClient.java create mode 100644 java/com/android/voicemail/impl/transcribe/grpc/TranscriptionClientFactory.java create mode 100644 java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponse.java create mode 100644 java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponseAsync.java create mode 100644 java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponseSync.java create mode 100644 java/com/android/voicemail/impl/transcribe/grpc/voicemail_transcription.proto (limited to 'java/com/android/voicemail/impl') diff --git a/java/com/android/voicemail/impl/ActivationTask.java b/java/com/android/voicemail/impl/ActivationTask.java index 6e27b5015..320ea2aaa 100644 --- a/java/com/android/voicemail/impl/ActivationTask.java +++ b/java/com/android/voicemail/impl/ActivationTask.java @@ -36,7 +36,6 @@ import com.android.voicemail.impl.scheduling.RetryPolicy; import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; import com.android.voicemail.impl.sms.StatusMessage; import com.android.voicemail.impl.sms.StatusSmsFetcher; -import com.android.voicemail.impl.sync.OmtpVvmSyncService; import com.android.voicemail.impl.sync.SyncTask; import com.android.voicemail.impl.sync.VvmAccountManager; import com.android.voicemail.impl.utils.LoggerUtils; @@ -258,7 +257,7 @@ public class ActivationTask extends BaseTask { VoicemailStatus.edit(context, phoneAccountHandle), OmtpEvents.CONFIG_REQUEST_STATUS_SUCCESS); clearLegacyVoicemailNotification(context, phoneAccountHandle); - SyncTask.start(context, phoneAccountHandle, OmtpVvmSyncService.SYNC_FULL_SYNC); + SyncTask.start(context, phoneAccountHandle); } /** Sends a broadcast to the dialer UI to clear legacy voicemail notifications if any. */ diff --git a/java/com/android/voicemail/impl/AndroidManifest.xml b/java/com/android/voicemail/impl/AndroidManifest.xml index 95e6e8212..4cad2247c 100644 --- a/java/com/android/voicemail/impl/AndroidManifest.xml +++ b/java/com/android/voicemail/impl/AndroidManifest.xml @@ -15,15 +15,10 @@ --> + package="com.android.voicemail.impl"> - + android:supportsRtl="true"> @@ -96,6 +91,16 @@ android:permission="android.permission.BIND_JOB_SERVICE" android:exported="false"/> + + + + - + - + diff --git a/java/com/android/voicemail/impl/DeviceProvisionedJobService.java b/java/com/android/voicemail/impl/DeviceProvisionedJobService.java index a0b999d23..20993d051 100644 --- a/java/com/android/voicemail/impl/DeviceProvisionedJobService.java +++ b/java/com/android/voicemail/impl/DeviceProvisionedJobService.java @@ -29,6 +29,7 @@ import android.content.Intent; import android.os.Build.VERSION_CODES; import android.provider.Settings; import android.provider.Settings.Global; +import android.support.annotation.VisibleForTesting; import android.telecom.PhoneAccountHandle; import com.android.dialer.constants.ScheduledJobIds; @@ -39,29 +40,25 @@ import com.android.dialer.constants.ScheduledJobIds; @TargetApi(VERSION_CODES.O) public class DeviceProvisionedJobService extends JobService { - private static final String EXTRA_PHONE_ACCOUNT_HANDLE = "EXTRA_PHONE_ACCOUNT_HANDLE"; + @VisibleForTesting static final String EXTRA_PHONE_ACCOUNT_HANDLE = "EXTRA_PHONE_ACCOUNT_HANDLE"; /** Queue the phone account to be reactivated after the setup wizard has completed. */ public static void activateAfterProvisioned( Context context, PhoneAccountHandle phoneAccountHandle) { - JobInfo jobInfo = - new JobInfo.Builder( - ScheduledJobIds.VVM_DEVICE_PROVISIONED_JOB, - new ComponentName(context, DeviceProvisionedJobService.class)) - .addTriggerContentUri( - new TriggerContentUri(Global.getUriFor(Global.DEVICE_PROVISIONED), 0)) - // VVM activation must be run as soon as possible to avoid voicemail loss - .setTriggerContentMaxDelay(0) - .build(); - Intent intent = new Intent(); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); - context.getSystemService(JobScheduler.class).enqueue(jobInfo, new JobWorkItem(intent)); + context + .getSystemService(JobScheduler.class) + .enqueue(createJobInfo(context), new JobWorkItem(intent)); } @Override public boolean onStartJob(JobParameters params) { - Assert.isTrue(isDeviceProvisioned()); + if (!isDeviceProvisioned()) { + VvmLog.i("DeviceProvisionedJobService.onStartJob", "device not provisioned, rescheduling"); + getSystemService(JobScheduler.class).schedule(createJobInfo(this)); + return false; // job not running in background + } VvmLog.i("DeviceProvisionedJobService.onStartJob", "device provisioned"); for (JobWorkItem item = params.dequeueWork(); item != null; item = params.dequeueWork()) { PhoneAccountHandle phoneAccountHandle = @@ -82,4 +79,14 @@ public class DeviceProvisionedJobService extends JobService { private boolean isDeviceProvisioned() { return Settings.Global.getInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) == 1; } + + private static JobInfo createJobInfo(Context context) { + return new JobInfo.Builder( + ScheduledJobIds.VVM_DEVICE_PROVISIONED_JOB, + new ComponentName(context, DeviceProvisionedJobService.class)) + .addTriggerContentUri(new TriggerContentUri(Global.getUriFor(Global.DEVICE_PROVISIONED), 0)) + // VVM activation must be run as soon as possible to avoid voicemail loss + .setTriggerContentMaxDelay(0) + .build(); + } } diff --git a/java/com/android/voicemail/impl/OmtpConstants.java b/java/com/android/voicemail/impl/OmtpConstants.java index 599d0d5f0..97da2a8e3 100644 --- a/java/com/android/voicemail/impl/OmtpConstants.java +++ b/java/com/android/voicemail/impl/OmtpConstants.java @@ -234,6 +234,39 @@ public class OmtpConstants { public static final int CHANGE_PIN_INVALID_CHARACTER = 5; public static final int CHANGE_PIN_SYSTEM_ERROR = 6; - /** Indicates the client is Google visual voicemail version 1.0. */ - public static final String CLIENT_TYPE_GOOGLE_10 = "google.vvm.10"; + public static String getClientType() { + String manufacturer = + truncate( + android.os.Build.MANUFACTURER + .replace('=', '_') + .replace(';', '_') + .replace('.', '_') + .replace(' ', '_'), + 12); + + String version = + truncate( + android.os.Build.VERSION + .RELEASE + .replace('=', '_') + .replace(';', '_') + .replace('.', '_') + .replace(' ', '_'), + 8); + + String model = + truncate( + android.os.Build.MODEL + .replace('=', '_') + .replace(';', '_') + .replace('.', '_') + .replace(' ', '_'), + 28 - manufacturer.length() - version.length()); + + return String.format("%s.%s.%s", manufacturer, model, version); + } + + private static final String truncate(String string, int length) { + return string.substring(0, Math.min(length, string.length())); + } } diff --git a/java/com/android/voicemail/impl/OmtpReceiver.java b/java/com/android/voicemail/impl/OmtpReceiver.java deleted file mode 100644 index 9baf95415..000000000 --- a/java/com/android/voicemail/impl/OmtpReceiver.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemail.impl; - -import android.annotation.TargetApi; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.Build.VERSION_CODES; -import android.telecom.PhoneAccountHandle; -import android.telephony.VisualVoicemailSms; -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.settings.VisualVoicemailSettingsUtil; -import com.android.voicemail.impl.sync.VvmAccountManager; - -/** Listens to com.android.phone.vvm.ACTION_TEMP_VISUAL_VOICEMAIL_SERVICE_EVENT */ -@TargetApi(VERSION_CODES.O) -public class OmtpReceiver extends BroadcastReceiver { - - private static final String TAG = "VvmOmtpReceiver"; - - public static final String ACTION_SMS_RECEIVED = "com.android.vociemailomtp.sms.sms_received"; - - public static final String EXTRA_VOICEMAIL_SMS = "extra_voicemail_sms"; - - private static final String EXTRA_WHAT = "what"; - - private static final int MSG_ON_CELL_SERVICE_CONNECTED = 1; - - private static final int MSG_ON_SMS_RECEIVED = 2; - - private static final int MSG_ON_SIM_REMOVED = 3; - - private static final int MSG_TASK_STOPPED = 5; - - private static final String DATA_PHONE_ACCOUNT_HANDLE = "data_phone_account_handle"; - - private static final String DATA_SMS = "data_sms"; - - @Override - public void onReceive(Context context, Intent intent) { - // ACTION_VISUAL_VOICEMAIL_SERVICE_EVENT is not a protected broadcast pre-O. - if (!VoicemailComponent.get(context).getVoicemailClient().isVoicemailModuleEnabled()) { - VvmLog.e(TAG, "ACTION_VISUAL_VOICEMAIL_SERVICE_EVENT received when module is disabled"); - return; - } - - int what = intent.getIntExtra(EXTRA_WHAT, -1); - PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(DATA_PHONE_ACCOUNT_HANDLE); - OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle); - if (!config.isValid()) { - VvmLog.i(TAG, "VVM not supported on " + phoneAccountHandle); - return; - } - if (!VisualVoicemailSettingsUtil.isEnabled(context, phoneAccountHandle) - && !config.isLegacyModeEnabled()) { - VvmLog.i(TAG, "VVM is disabled"); - return; - } - switch (what) { - case MSG_ON_CELL_SERVICE_CONNECTED: - VvmLog.i(TAG, "onCellServiceConnected"); - Logger.get(context).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); - ActivationTask.start(context, phoneAccountHandle, null); - break; - case MSG_ON_SMS_RECEIVED: - VvmLog.i(TAG, "onSmsReceived"); - Logger.get(context).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); - VisualVoicemailSms sms = intent.getParcelableExtra(DATA_SMS); - Intent receivedIntent = new Intent(ACTION_SMS_RECEIVED); - receivedIntent.setPackage(context.getPackageName()); - receivedIntent.putExtra(EXTRA_VOICEMAIL_SMS, sms); - context.sendBroadcast(receivedIntent); - break; - case MSG_ON_SIM_REMOVED: - VvmLog.i(TAG, "onSimRemoved"); - Logger.get(context).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); - VvmAccountManager.removeAccount(context, phoneAccountHandle); - break; - case MSG_TASK_STOPPED: - VvmLog.i(TAG, "onStopped"); - Logger.get(context).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); - break; - default: - throw Assert.createIllegalStateFailException("unexpected what: " + what); - } - } -} diff --git a/java/com/android/voicemail/impl/OmtpService.java b/java/com/android/voicemail/impl/OmtpService.java index b82cc5f68..4db1aeb7e 100644 --- a/java/com/android/voicemail/impl/OmtpService.java +++ b/java/com/android/voicemail/impl/OmtpService.java @@ -17,9 +17,13 @@ package com.android.voicemail.impl; import android.annotation.TargetApi; +import android.content.Context; import android.content.Intent; import android.os.Build.VERSION_CODES; import android.os.UserManager; +import android.preference.PreferenceManager; +import android.support.annotation.MainThread; +import android.support.annotation.NonNull; import android.telecom.PhoneAccountHandle; import android.telephony.VisualVoicemailService; import android.telephony.VisualVoicemailSms; @@ -40,6 +44,8 @@ public class OmtpService extends VisualVoicemailService { public static final String EXTRA_VOICEMAIL_SMS = "extra_voicemail_sms"; + private static final String IS_SHUTTING_DOWN = "com.android.voicemail.impl.is_shutting_down"; + @Override public void onCellServiceConnected( VisualVoicemailTask task, final PhoneAccountHandle phoneAccountHandle) { @@ -50,7 +56,7 @@ public class OmtpService extends VisualVoicemailService { return; } - if (!isUserUnlocked()) { + if (!isUserUnlocked(this)) { VvmLog.i(TAG, "onCellServiceConnected: user locked"); task.finish(); return; @@ -75,7 +81,7 @@ public class OmtpService extends VisualVoicemailService { return; } - if (!isUserUnlocked()) { + if (!isUserUnlocked(this)) { LegacyModeSmsHandler.handle(this, sms); return; } @@ -105,12 +111,18 @@ public class OmtpService extends VisualVoicemailService { return; } - if (!isUserUnlocked()) { + if (!isUserUnlocked(this)) { VvmLog.i(TAG, "onSimRemoved: user locked"); task.finish(); return; } + if (isShuttingDown(this)) { + VvmLog.i(TAG, "onSimRemoved: system shutting down, ignoring"); + task.finish(); + return; + } + Logger.get(this).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); VvmAccountManager.removeAccount(this, phoneAccountHandle); task.finish(); @@ -124,7 +136,7 @@ public class OmtpService extends VisualVoicemailService { task.finish(); return; } - if (!isUserUnlocked()) { + if (!isUserUnlocked(this)) { VvmLog.i(TAG, "onStopped: user locked"); task.finish(); return; @@ -132,6 +144,22 @@ public class OmtpService extends VisualVoicemailService { Logger.get(this).logImpression(DialerImpression.Type.VVM_UNBUNDLED_EVENT_RECEIVED); } + @MainThread + static void onBoot(@NonNull Context context) { + VvmLog.i(TAG, "onBoot"); + Assert.isTrue(isUserUnlocked(context)); + Assert.isMainThread(); + setShuttingDown(context, false); + } + + @MainThread + static void onShutdown(@NonNull Context context) { + VvmLog.i(TAG, "onShutdown"); + Assert.isTrue(isUserUnlocked(context)); + Assert.isMainThread(); + setShuttingDown(context, true); + } + private boolean isModuleEnabled() { return VoicemailComponent.get(this).getVoicemailClient().isVoicemailModuleEnabled(); } @@ -150,8 +178,20 @@ public class OmtpService extends VisualVoicemailService { return true; } - private boolean isUserUnlocked() { - UserManager userManager = getSystemService(UserManager.class); + private static boolean isUserUnlocked(@NonNull Context context) { + UserManager userManager = context.getSystemService(UserManager.class); return userManager.isUserUnlocked(); } + + private static void setShuttingDown(Context context, boolean value) { + PreferenceManager.getDefaultSharedPreferences(context) + .edit() + .putBoolean(IS_SHUTTING_DOWN, value) + .apply(); + } + + private static boolean isShuttingDown(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(IS_SHUTTING_DOWN, false); + } } diff --git a/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java b/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java index 4a9e43370..700e1cbca 100644 --- a/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java +++ b/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java @@ -15,9 +15,11 @@ */ package com.android.voicemail.impl; +import android.annotation.TargetApi; import android.app.PendingIntent; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.PersistableBundle; import android.support.annotation.NonNull; @@ -30,6 +32,7 @@ import android.telephony.VisualVoicemailSmsFilterSettings; import android.text.TextUtils; import android.util.ArraySet; import com.android.dialer.common.Assert; +import com.android.voicemail.impl.configui.ConfigOverrideFragment; import com.android.voicemail.impl.protocol.VisualVoicemailProtocol; import com.android.voicemail.impl.protocol.VisualVoicemailProtocolFactory; import com.android.voicemail.impl.sms.StatusMessage; @@ -48,27 +51,28 @@ import java.util.Set; * *

The current hidden configs are: {@link #getSslPort()} {@link #getDisabledCapabilities()} */ +@TargetApi(VERSION_CODES.O) public class OmtpVvmCarrierConfigHelper { private static final String TAG = "OmtpVvmCarrierCfgHlpr"; - static final String KEY_VVM_TYPE_STRING = CarrierConfigManager.KEY_VVM_TYPE_STRING; - static final String KEY_VVM_DESTINATION_NUMBER_STRING = + public static final String KEY_VVM_TYPE_STRING = CarrierConfigManager.KEY_VVM_TYPE_STRING; + public static final String KEY_VVM_DESTINATION_NUMBER_STRING = CarrierConfigManager.KEY_VVM_DESTINATION_NUMBER_STRING; - static final String KEY_VVM_PORT_NUMBER_INT = CarrierConfigManager.KEY_VVM_PORT_NUMBER_INT; - static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = + public static final String KEY_VVM_PORT_NUMBER_INT = CarrierConfigManager.KEY_VVM_PORT_NUMBER_INT; + public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING; - static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY = + public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY = "carrier_vvm_package_name_string_array"; - static final String KEY_VVM_PREFETCH_BOOL = CarrierConfigManager.KEY_VVM_PREFETCH_BOOL; - static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL = + public static final String KEY_VVM_PREFETCH_BOOL = CarrierConfigManager.KEY_VVM_PREFETCH_BOOL; + public static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL = CarrierConfigManager.KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL; /** @see #getSslPort() */ - static final String KEY_VVM_SSL_PORT_NUMBER_INT = "vvm_ssl_port_number_int"; + public static final String KEY_VVM_SSL_PORT_NUMBER_INT = "vvm_ssl_port_number_int"; /** @see #isLegacyModeEnabled() */ - static final String KEY_VVM_LEGACY_MODE_ENABLED_BOOL = "vvm_legacy_mode_enabled_bool"; + public static final String KEY_VVM_LEGACY_MODE_ENABLED_BOOL = "vvm_legacy_mode_enabled_bool"; /** * Ban a capability reported by the server from being used. The array of string should be a subset @@ -76,10 +80,10 @@ public class OmtpVvmCarrierConfigHelper { * * @see #getDisabledCapabilities() */ - static final String KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY = + public static final String KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY = "vvm_disabled_capabilities_string_array"; - static final String KEY_VVM_CLIENT_PREFIX_STRING = "vvm_client_prefix_string"; + public static final String KEY_VVM_CLIENT_PREFIX_STRING = "vvm_client_prefix_string"; private final Context mContext; private final PersistableBundle mCarrierConfig; @@ -87,6 +91,8 @@ public class OmtpVvmCarrierConfigHelper { private final VisualVoicemailProtocol mProtocol; private final PersistableBundle mTelephonyConfig; + @Nullable private final PersistableBundle mOverrideConfig; + private PhoneAccountHandle mPhoneAccountHandle; public OmtpVvmCarrierConfigHelper(Context context, @Nullable PhoneAccountHandle handle) { @@ -100,6 +106,7 @@ public class OmtpVvmCarrierConfigHelper { VvmLog.e(TAG, "PhoneAccountHandle is invalid"); mCarrierConfig = null; mTelephonyConfig = null; + mOverrideConfig = null; mVvmType = null; mProtocol = null; return; @@ -111,6 +118,13 @@ public class OmtpVvmCarrierConfigHelper { mVvmType = getVvmType(); mProtocol = VisualVoicemailProtocolFactory.create(mContext.getResources(), mVvmType); + + if (ConfigOverrideFragment.isOverridden(context)) { + mOverrideConfig = ConfigOverrideFragment.getConfig(context); + VvmLog.w(TAG, "Config override is activated: " + mOverrideConfig); + } else { + mOverrideConfig = null; + } } @VisibleForTesting @@ -119,10 +133,23 @@ public class OmtpVvmCarrierConfigHelper { mContext = context; mCarrierConfig = carrierConfig; mTelephonyConfig = telephonyConfig; + mOverrideConfig = null; mVvmType = getVvmType(); mProtocol = VisualVoicemailProtocolFactory.create(mContext.getResources(), mVvmType); } + public PersistableBundle getConfig() { + PersistableBundle result = new PersistableBundle(); + if (mTelephonyConfig != null) { + result.putAll(mTelephonyConfig); + } + if (mCarrierConfig != null) { + result.putAll(mCarrierConfig); + } + + return result; + } + public Context getContext() { return mContext; } @@ -426,6 +453,13 @@ public class OmtpVvmCarrierConfigHelper { @Nullable private Object getValue(String key, Object defaultValue) { Object result; + if (mOverrideConfig != null) { + result = mOverrideConfig.get(key); + if (result != null) { + return result; + } + } + if (mCarrierConfig != null) { result = mCarrierConfig.get(key); if (result != null) { diff --git a/java/com/android/voicemail/impl/PackageReplacedReceiver.java b/java/com/android/voicemail/impl/PackageReplacedReceiver.java new file mode 100644 index 000000000..6a7ca4a7b --- /dev/null +++ b/java/com/android/voicemail/impl/PackageReplacedReceiver.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.voicemail.impl; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import com.android.voicemail.VoicemailComponent; + +/** Receives MY_PACKAGE_REPLACED to trigger VVM activation. */ +public class PackageReplacedReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + VvmLog.i("PackageReplacedReceiver.onReceive", "package replaced, starting activation"); + + if (!VoicemailComponent.get(context).getVoicemailClient().isVoicemailModuleEnabled()) { + VvmLog.e("PackageReplacedReceiver.onReceive", "module disabled"); + return; + } + + for (PhoneAccountHandle phoneAccountHandle : + context.getSystemService(TelecomManager.class).getCallCapablePhoneAccounts()) { + ActivationTask.start(context, phoneAccountHandle, null); + } + } +} diff --git a/java/com/android/voicemail/impl/SubscriptionInfoHelper.java b/java/com/android/voicemail/impl/SubscriptionInfoHelper.java deleted file mode 100644 index d8a8423eb..000000000 --- a/java/com/android/voicemail/impl/SubscriptionInfoHelper.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (C) 2014 The Android Open Source Project - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License - */ -package com.android.voicemail.impl; - -import android.app.ActionBar; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.text.TextUtils; - -/** - * Helper for manipulating intents or components with subscription-related information. - * - *

In settings, subscription ids and labels are passed along to indicate that settings are being - * changed for particular subscriptions. This helper provides functions for helping extract this - * info and perform common operations using this info. - */ -public class SubscriptionInfoHelper { - public static final int NO_SUB_ID = -1; - - // Extra on intent containing the id of a subscription. - public static final String SUB_ID_EXTRA = - "com.android.voicemailomtp.settings.SubscriptionInfoHelper.SubscriptionId"; - // Extra on intent containing the label of a subscription. - private static final String SUB_LABEL_EXTRA = - "com.android.voicemailomtp.settings.SubscriptionInfoHelper.SubscriptionLabel"; - - private static Context mContext; - - private static int mSubId = NO_SUB_ID; - private static String mSubLabel; - - /** Instantiates the helper, by extracting the subscription id and label from the intent. */ - public SubscriptionInfoHelper(Context context, Intent intent) { - mContext = context; - mSubId = intent.getIntExtra(SUB_ID_EXTRA, NO_SUB_ID); - mSubLabel = intent.getStringExtra(SUB_LABEL_EXTRA); - } - - /** - * Sets the action bar title to the string specified by the given resource id, formatting it with - * the subscription label. This assumes the resource string is formattable with a string-type - * specifier. - * - *

If the subscription label does not exists, leave the existing title. - */ - public void setActionBarTitle(ActionBar actionBar, Resources res, int resId) { - if (actionBar == null || TextUtils.isEmpty(mSubLabel)) { - return; - } - - String title = String.format(res.getString(resId), mSubLabel); - actionBar.setTitle(title); - } - - public int getSubId() { - return mSubId; - } -} diff --git a/java/com/android/voicemail/impl/TelephonyManagerStub.java b/java/com/android/voicemail/impl/TelephonyManagerStub.java deleted file mode 100644 index 4762e9023..000000000 --- a/java/com/android/voicemail/impl/TelephonyManagerStub.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemail.impl; - -import android.annotation.TargetApi; -import android.os.Build.VERSION_CODES; - -/** - * Temporary stub for public APIs that should be added into telephony manager. - * - *

TODO(b/32637799) remove this. - */ -@TargetApi(VERSION_CODES.O) -public class TelephonyManagerStub { - - public static void showVoicemailNotification(int voicemailCount) {} - - /** - * Dismisses the message waiting (voicemail) indicator. - * - * @param subId the subscription id we should dismiss the notification for. - */ - public static void clearMwiIndicator(int subId) {} - - public static void setShouldCheckVisualVoicemailConfigurationForMwi(int subId, boolean enabled) {} -} diff --git a/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java b/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java index b4def2fc3..046113c26 100644 --- a/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java +++ b/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java @@ -21,7 +21,7 @@ import android.os.PersistableBundle; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.util.ArrayMap; -import com.android.dialer.common.ConfigProviderBindings; +import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.voicemail.impl.utils.XmlUtils; import java.io.IOException; import java.util.ArrayList; diff --git a/java/com/android/voicemail/impl/VoicemailBootReceiver.java b/java/com/android/voicemail/impl/VoicemailBootReceiver.java deleted file mode 100644 index 0a3e61a01..000000000 --- a/java/com/android/voicemail/impl/VoicemailBootReceiver.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (C) 2017 The Android Open Source Project - * - *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License - */ -package com.android.voicemail.impl; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import com.android.voicemail.VoicemailComponent; - -/** Receives {@link Intent#ACTION_BOOT_COMPLETED} for the voicemail module. */ -public class VoicemailBootReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - if (!VoicemailComponent.get(context).getVoicemailClient().isVoicemailModuleEnabled()) { - return; - } - StatusCheckJobService.schedule(context); - } -} diff --git a/java/com/android/voicemail/impl/VoicemailClientImpl.java b/java/com/android/voicemail/impl/VoicemailClientImpl.java index 83c0523bf..9bb14f2dc 100644 --- a/java/com/android/voicemail/impl/VoicemailClientImpl.java +++ b/java/com/android/voicemail/impl/VoicemailClientImpl.java @@ -17,21 +17,26 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.os.Build.VERSION_CODES; +import android.os.PersistableBundle; import android.provider.VoicemailContract.Status; import android.provider.VoicemailContract.Voicemails; +import android.support.annotation.MainThread; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.os.BuildCompat; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; import com.android.dialer.common.Assert; -import com.android.dialer.common.ConfigProviderBindings; import com.android.dialer.common.LogUtil; +import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.voicemail.VisualVoicemailTypeExtensions; import com.android.voicemail.VoicemailClient; +import com.android.voicemail.impl.configui.VoicemailSecretCodeActivity; import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; 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 java.util.List; import javax.inject.Inject; @@ -126,6 +131,31 @@ public class VoicemailClientImpl implements VoicemailClient { return VvmAccountManager.isAccountActivated(context, phoneAccountHandle); } + @Override + public void showConfigUi(@NonNull Context context) { + Intent intent = new Intent(context, VoicemailSecretCodeActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + @Override + public PersistableBundle getConfig(Context context, PhoneAccountHandle phoneAccountHandle) { + return new OmtpVvmCarrierConfigHelper(context, phoneAccountHandle).getConfig(); + } + + @Override + @MainThread + public void onBoot(@NonNull Context context) { + OmtpService.onBoot(context); + StatusCheckJobService.schedule(context); + } + + @Override + @MainThread + public void onShutdown(@NonNull Context context) { + OmtpService.onShutdown(context); + } + @TargetApi(VERSION_CODES.O) @Override public void appendOmtpVoicemailSelectionClause( @@ -201,4 +231,10 @@ public class VoicemailClientImpl implements VoicemailClient { where.append(")"); } } + + @Override + public void onTosAccepted(Context context) { + LogUtil.i("VoicemailClientImpl.onTosAccepted", "try backfilling voicemail transcriptions"); + TranscriptionBackfillService.scheduleTask(context); + } } diff --git a/java/com/android/voicemail/impl/VoicemailClientReceiver.java b/java/com/android/voicemail/impl/VoicemailClientReceiver.java index 49a55a41b..688636e6c 100644 --- a/java/com/android/voicemail/impl/VoicemailClientReceiver.java +++ b/java/com/android/voicemail/impl/VoicemailClientReceiver.java @@ -23,6 +23,7 @@ import android.telecom.PhoneAccountHandle; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.voicemail.VoicemailClient; +import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.sync.UploadTask; import com.android.voicemail.impl.sync.VvmAccountManager; @@ -31,6 +32,11 @@ public class VoicemailClientReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + if (!VoicemailComponent.get(context).getVoicemailClient().isVoicemailModuleEnabled()) { + LogUtil.i( + "VoicemailClientReceiver.onReceive", "module disabled, ignoring " + intent.getAction()); + return; + } switch (intent.getAction()) { case VoicemailClient.ACTION_UPLOAD: doUpload(context); diff --git a/java/com/android/voicemail/impl/VoicemailModule.java b/java/com/android/voicemail/impl/VoicemailModule.java index 5a4e739f5..e689e47d2 100644 --- a/java/com/android/voicemail/impl/VoicemailModule.java +++ b/java/com/android/voicemail/impl/VoicemailModule.java @@ -18,6 +18,7 @@ package com.android.voicemail.impl; import android.content.Context; import android.support.v4.os.BuildCompat; +import com.android.dialer.inject.ApplicationContext; import com.android.voicemail.VoicemailClient; import com.android.voicemail.VoicemailPermissionHelper; import com.android.voicemail.stub.StubVoicemailClient; @@ -31,7 +32,7 @@ public final class VoicemailModule { @Provides @Singleton - static VoicemailClient provideVoicemailClient(Context context) { + static VoicemailClient provideVoicemailClient(@ApplicationContext Context context) { if (!BuildCompat.isAtLeastO()) { VvmLog.i("VoicemailModule.provideVoicemailClient", "SDK below O"); return new StubVoicemailClient(); diff --git a/java/com/android/voicemail/impl/VoicemailStatus.java b/java/com/android/voicemail/impl/VoicemailStatus.java index ec1ab4e70..5553cf5e0 100644 --- a/java/com/android/voicemail/impl/VoicemailStatus.java +++ b/java/com/android/voicemail/impl/VoicemailStatus.java @@ -24,6 +24,7 @@ import android.provider.VoicemailContract; import android.provider.VoicemailContract.Status; import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; +import com.android.dialer.strictmode.DialerStrictMode; public class VoicemailStatus { @@ -99,7 +100,7 @@ public class VoicemailStatus { ContentResolver contentResolver = mContext.getContentResolver(); Uri statusUri = VoicemailContract.Status.buildSourceUri(mContext.getPackageName()); try { - contentResolver.insert(statusUri, mValues); + DialerStrictMode.bypass(() -> contentResolver.insert(statusUri, mValues)); } catch (IllegalArgumentException iae) { VvmLog.e(TAG, "apply :: failed to insert content resolver ", iae); mValues.clear(); diff --git a/java/com/android/voicemail/impl/VoicemailTranscriptionServiceGrpc.java b/java/com/android/voicemail/impl/VoicemailTranscriptionServiceGrpc.java new file mode 100644 index 000000000..8fcbf3b97 --- /dev/null +++ b/java/com/android/voicemail/impl/VoicemailTranscriptionServiceGrpc.java @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.google.internal.communications.voicemailtranscription.v1; + +import static io.grpc.stub.ClientCalls.asyncUnaryCall; +import static io.grpc.stub.ClientCalls.asyncServerStreamingCall; +import static io.grpc.stub.ClientCalls.asyncClientStreamingCall; +import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ClientCalls.blockingUnaryCall; +import static io.grpc.stub.ClientCalls.blockingServerStreamingCall; +import static io.grpc.stub.ClientCalls.futureUnaryCall; +import static io.grpc.MethodDescriptor.generateFullMethodName; +import static io.grpc.stub.ServerCalls.asyncUnaryCall; +import static io.grpc.stub.ServerCalls.asyncServerStreamingCall; +import static io.grpc.stub.ServerCalls.asyncClientStreamingCall; +import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall; + +/** + *

+ * RPC service for transcribing voicemails.
+ * 
+ */ +@javax.annotation.Generated( + value = "by gRPC proto compiler (version 1.0.3)", + comments = "Source: voicemail_transcription.proto") +public class VoicemailTranscriptionServiceGrpc { + + private VoicemailTranscriptionServiceGrpc() {} + + public static final String SERVICE_NAME = "google.internal.communications.voicemailtranscription.v1.VoicemailTranscriptionService"; + + // Static method descriptors that strictly reflect the proto. + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901") + public static final io.grpc.MethodDescriptor METHOD_TRANSCRIBE_VOICEMAIL = + io.grpc.MethodDescriptor.create( + io.grpc.MethodDescriptor.MethodType.UNARY, + generateFullMethodName( + "google.internal.communications.voicemailtranscription.v1.VoicemailTranscriptionService", "TranscribeVoicemail"), + io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest.getDefaultInstance()), + io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailResponse.getDefaultInstance())); + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901") + public static final io.grpc.MethodDescriptor METHOD_TRANSCRIBE_VOICEMAIL_ASYNC = + io.grpc.MethodDescriptor.create( + io.grpc.MethodDescriptor.MethodType.UNARY, + generateFullMethodName( + "google.internal.communications.voicemailtranscription.v1.VoicemailTranscriptionService", "TranscribeVoicemailAsync"), + io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest.getDefaultInstance()), + io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncResponse.getDefaultInstance())); + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901") + public static final io.grpc.MethodDescriptor METHOD_GET_TRANSCRIPT = + io.grpc.MethodDescriptor.create( + io.grpc.MethodDescriptor.MethodType.UNARY, + generateFullMethodName( + "google.internal.communications.voicemailtranscription.v1.VoicemailTranscriptionService", "GetTranscript"), + io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest.getDefaultInstance()), + io.grpc.protobuf.lite.ProtoLiteUtils.marshaller(com.google.internal.communications.voicemailtranscription.v1.GetTranscriptResponse.getDefaultInstance())); + + /** + * Creates a new async stub that supports all call types for the service + */ + public static VoicemailTranscriptionServiceStub newStub(io.grpc.Channel channel) { + return new VoicemailTranscriptionServiceStub(channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static VoicemailTranscriptionServiceBlockingStub newBlockingStub( + io.grpc.Channel channel) { + return new VoicemailTranscriptionServiceBlockingStub(channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary and streaming output calls on the service + */ + public static VoicemailTranscriptionServiceFutureStub newFutureStub( + io.grpc.Channel channel) { + return new VoicemailTranscriptionServiceFutureStub(channel); + } + + /** + *
+   * RPC service for transcribing voicemails.
+   * 
+ */ + public static abstract class VoicemailTranscriptionServiceImplBase implements io.grpc.BindableService { + + /** + *
+     * Returns a transcript of the given voicemail.
+     * 
+ */ + public void transcribeVoicemail(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(METHOD_TRANSCRIBE_VOICEMAIL, responseObserver); + } + + /** + *
+     * Schedules a transcription of the given voicemail. The transcript can be
+     * retrieved using the returned ID.
+     * 
+ */ + public void transcribeVoicemailAsync(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(METHOD_TRANSCRIBE_VOICEMAIL_ASYNC, responseObserver); + } + + /** + *
+     * Returns the transcript corresponding to the given ID, which was returned
+     * by TranscribeVoicemailAsync.
+     * 
+ */ + public void getTranscript(com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(METHOD_GET_TRANSCRIPT, responseObserver); + } + + @java.lang.Override public io.grpc.ServerServiceDefinition bindService() { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + METHOD_TRANSCRIBE_VOICEMAIL, + asyncUnaryCall( + new MethodHandlers< + com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest, + com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailResponse>( + this, METHODID_TRANSCRIBE_VOICEMAIL))) + .addMethod( + METHOD_TRANSCRIBE_VOICEMAIL_ASYNC, + asyncUnaryCall( + new MethodHandlers< + com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest, + com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncResponse>( + this, METHODID_TRANSCRIBE_VOICEMAIL_ASYNC))) + .addMethod( + METHOD_GET_TRANSCRIPT, + asyncUnaryCall( + new MethodHandlers< + com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest, + com.google.internal.communications.voicemailtranscription.v1.GetTranscriptResponse>( + this, METHODID_GET_TRANSCRIPT))) + .build(); + } + } + + /** + *
+   * RPC service for transcribing voicemails.
+   * 
+ */ + public static final class VoicemailTranscriptionServiceStub extends io.grpc.stub.AbstractStub { + private VoicemailTranscriptionServiceStub(io.grpc.Channel channel) { + super(channel); + } + + private VoicemailTranscriptionServiceStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected VoicemailTranscriptionServiceStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new VoicemailTranscriptionServiceStub(channel, callOptions); + } + + /** + *
+     * Returns a transcript of the given voicemail.
+     * 
+ */ + public void transcribeVoicemail(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(METHOD_TRANSCRIBE_VOICEMAIL, getCallOptions()), request, responseObserver); + } + + /** + *
+     * Schedules a transcription of the given voicemail. The transcript can be
+     * retrieved using the returned ID.
+     * 
+ */ + public void transcribeVoicemailAsync(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(METHOD_TRANSCRIBE_VOICEMAIL_ASYNC, getCallOptions()), request, responseObserver); + } + + /** + *
+     * Returns the transcript corresponding to the given ID, which was returned
+     * by TranscribeVoicemailAsync.
+     * 
+ */ + public void getTranscript(com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(METHOD_GET_TRANSCRIPT, getCallOptions()), request, responseObserver); + } + } + + /** + *
+   * RPC service for transcribing voicemails.
+   * 
+ */ + public static final class VoicemailTranscriptionServiceBlockingStub extends io.grpc.stub.AbstractStub { + private VoicemailTranscriptionServiceBlockingStub(io.grpc.Channel channel) { + super(channel); + } + + private VoicemailTranscriptionServiceBlockingStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected VoicemailTranscriptionServiceBlockingStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new VoicemailTranscriptionServiceBlockingStub(channel, callOptions); + } + + /** + *
+     * Returns a transcript of the given voicemail.
+     * 
+ */ + public com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailResponse transcribeVoicemail(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest request) { + return blockingUnaryCall( + getChannel(), METHOD_TRANSCRIBE_VOICEMAIL, getCallOptions(), request); + } + + /** + *
+     * Schedules a transcription of the given voicemail. The transcript can be
+     * retrieved using the returned ID.
+     * 
+ */ + public com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncResponse transcribeVoicemailAsync(com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest request) { + return blockingUnaryCall( + getChannel(), METHOD_TRANSCRIBE_VOICEMAIL_ASYNC, getCallOptions(), request); + } + + /** + *
+     * Returns the transcript corresponding to the given ID, which was returned
+     * by TranscribeVoicemailAsync.
+     * 
+ */ + public com.google.internal.communications.voicemailtranscription.v1.GetTranscriptResponse getTranscript(com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest request) { + return blockingUnaryCall( + getChannel(), METHOD_GET_TRANSCRIPT, getCallOptions(), request); + } + } + + /** + *
+   * RPC service for transcribing voicemails.
+   * 
+ */ + public static final class VoicemailTranscriptionServiceFutureStub extends io.grpc.stub.AbstractStub { + private VoicemailTranscriptionServiceFutureStub(io.grpc.Channel channel) { + super(channel); + } + + private VoicemailTranscriptionServiceFutureStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected VoicemailTranscriptionServiceFutureStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new VoicemailTranscriptionServiceFutureStub(channel, callOptions); + } + + /** + *
+     * Returns a transcript of the given voicemail.
+     * 
+ */ + public com.google.common.util.concurrent.ListenableFuture transcribeVoicemail( + com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest request) { + return futureUnaryCall( + getChannel().newCall(METHOD_TRANSCRIBE_VOICEMAIL, getCallOptions()), request); + } + + /** + *
+     * Schedules a transcription of the given voicemail. The transcript can be
+     * retrieved using the returned ID.
+     * 
+ */ + public com.google.common.util.concurrent.ListenableFuture transcribeVoicemailAsync( + com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest request) { + return futureUnaryCall( + getChannel().newCall(METHOD_TRANSCRIBE_VOICEMAIL_ASYNC, getCallOptions()), request); + } + + /** + *
+     * Returns the transcript corresponding to the given ID, which was returned
+     * by TranscribeVoicemailAsync.
+     * 
+ */ + public com.google.common.util.concurrent.ListenableFuture getTranscript( + com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest request) { + return futureUnaryCall( + getChannel().newCall(METHOD_GET_TRANSCRIPT, getCallOptions()), request); + } + } + + private static final int METHODID_TRANSCRIBE_VOICEMAIL = 0; + private static final int METHODID_TRANSCRIBE_VOICEMAIL_ASYNC = 1; + private static final int METHODID_GET_TRANSCRIPT = 2; + + private static class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final VoicemailTranscriptionServiceImplBase serviceImpl; + private final int methodId; + + public MethodHandlers(VoicemailTranscriptionServiceImplBase serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_TRANSCRIBE_VOICEMAIL: + serviceImpl.transcribeVoicemail((com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_TRANSCRIBE_VOICEMAIL_ASYNC: + serviceImpl.transcribeVoicemailAsync((com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + case METHODID_GET_TRANSCRIPT: + serviceImpl.getTranscript((com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + } + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + return new io.grpc.ServiceDescriptor(SERVICE_NAME, + METHOD_TRANSCRIBE_VOICEMAIL, + METHOD_TRANSCRIBE_VOICEMAIL_ASYNC, + METHOD_GET_TRANSCRIPT); + } + +} diff --git a/java/com/android/voicemail/impl/VvmPackageInstallReceiver.java b/java/com/android/voicemail/impl/VvmPackageInstallReceiver.java deleted file mode 100644 index 1e2de6070..000000000 --- a/java/com/android/voicemail/impl/VvmPackageInstallReceiver.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ -package com.android.voicemail.impl; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.telecom.PhoneAccountHandle; -import android.telecom.TelecomManager; -import com.android.voicemail.VoicemailComponent; -import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; - -/** - * When a new package is installed, check if it matches any of the vvm carrier apps of the currently - * enabled dialer VVM sources. The dialer VVM client will be disabled upon carrier VVM app - * installation, unless it was explicitly enabled by the user. - */ -public class VvmPackageInstallReceiver extends BroadcastReceiver { - - private static final String TAG = "VvmPkgInstallReceiver"; - - @Override - public void onReceive(Context context, Intent intent) { - if (!VoicemailComponent.get(context).getVoicemailClient().isVoicemailModuleEnabled()) { - return; - } - - if (intent.getData() == null) { - return; - } - - String packageName = intent.getData().getSchemeSpecificPart(); - if (packageName == null) { - return; - } - - // This get called every time an app is installed and will be noisy. Don't log until the app - // is identified as a carrier VVM app. - for (PhoneAccountHandle phoneAccount : - context.getSystemService(TelecomManager.class).getCallCapablePhoneAccounts()) { - OmtpVvmCarrierConfigHelper carrierConfigHelper = - new OmtpVvmCarrierConfigHelper(context, phoneAccount); - if (!carrierConfigHelper.isValid()) { - continue; - } - if (carrierConfigHelper.getCarrierVvmPackageNames() == null) { - continue; - } - if (!carrierConfigHelper.getCarrierVvmPackageNames().contains(packageName)) { - continue; - } - - VvmLog.i(TAG, "Carrier app installed"); - if (VisualVoicemailSettingsUtil.isEnabledUserSet(context, phoneAccount)) { - // Skip the check if this voicemail source's setting is overridden by the user. - VvmLog.i(TAG, "VVM enabled by user, not disabling"); - continue; - } - - // Force deactivate the client. The user can re-enable it in the settings. - // There is no need to update the settings for deactivation. At this point, if the - // default value is used it should be false because a carrier package is present. - VvmLog.i(TAG, "Carrier VVM package installed, disabling system VVM client"); - VisualVoicemailSettingsUtil.setEnabled(context, phoneAccount, false); - } - } -} diff --git a/java/com/android/voicemail/impl/VvmPhoneStateListener.java b/java/com/android/voicemail/impl/VvmPhoneStateListener.java index 48b72042c..00c1358ab 100644 --- a/java/com/android/voicemail/impl/VvmPhoneStateListener.java +++ b/java/com/android/voicemail/impl/VvmPhoneStateListener.java @@ -19,7 +19,6 @@ import android.content.Context; import android.telecom.PhoneAccountHandle; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; -import com.android.voicemail.impl.sync.OmtpVvmSyncService; import com.android.voicemail.impl.sync.SyncTask; import com.android.voicemail.impl.sync.VoicemailStatusQueryHelper; import com.android.voicemail.impl.sync.VvmAccountManager; @@ -37,7 +36,7 @@ public class VvmPhoneStateListener extends PhoneStateListener { private int mPreviousState = -1; public VvmPhoneStateListener(Context context, PhoneAccountHandle accountHandle) { - // TODO: b/32637799 too much trouble to call super constructor through reflection, + // TODO(twyen): b/32637799 too much trouble to call super constructor through reflection, // just use non-phoneAccountHandle version for now. super(); mContext = context; @@ -82,7 +81,7 @@ public class VvmPhoneStateListener extends PhoneStateListener { VvmLog.v(TAG, "Signal returned: requesting resync for " + mPhoneAccount); // If the source is already registered, run a full sync in case something was missed // while signal was down. - SyncTask.start(mContext, mPhoneAccount, OmtpVvmSyncService.SYNC_FULL_SYNC); + SyncTask.start(mContext, mPhoneAccount); } else { VvmLog.v(TAG, "Signal returned: reattempting activation for " + mPhoneAccount); // Otherwise initiate an activation because this means that an OMTP source was diff --git a/java/com/android/voicemail/impl/configui/AndroidManifest.xml b/java/com/android/voicemail/impl/configui/AndroidManifest.xml new file mode 100644 index 000000000..95796f978 --- /dev/null +++ b/java/com/android/voicemail/impl/configui/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java b/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java new file mode 100644 index 000000000..1624ce579 --- /dev/null +++ b/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.voicemail.impl.configui; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.PersistableBundle; +import android.preference.EditTextPreference; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceFragment; +import android.preference.PreferenceManager; +import android.preference.PreferenceScreen; +import android.preference.SwitchPreference; +import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; +import android.telecom.PhoneAccount; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import android.text.TextUtils; +import com.android.dialer.common.Assert; +import com.android.dialer.common.concurrent.ThreadUtil; +import com.android.dialer.strictmode.DialerStrictMode; +import com.android.voicemail.VoicemailComponent; + +/** + * Fragment to edit the override values for the {@link import + * com.android.voicemail.impl.OmtpVvmCarrierConfigHelper} + */ +public class ConfigOverrideFragment extends PreferenceFragment + implements OnPreferenceChangeListener { + + /** + * Any preference with key that starts with this prefix will be written to the dialer carrier + * config. + */ + @VisibleForTesting static final String CONFIG_OVERRIDE_KEY_PREFIX = "vvm_config_override_key_"; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + PreferenceManager.setDefaultValues(getActivity(), R.xml.vvm_config_override, false); + addPreferencesFromResource(R.xml.vvm_config_override); + + // add listener so the value of a EditTextPreference will be updated to the summary. + for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) { + Preference preference = getPreferenceScreen().getPreference(i); + preference.setOnPreferenceChangeListener(this); + updatePreference(preference); + } + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + Assert.isMainThread(); + ThreadUtil.postOnUiThread(() -> updatePreference(preference)); + return true; + } + + private void updatePreference(Preference preference) { + if (preference instanceof EditTextPreference) { + EditTextPreference editTextPreference = (EditTextPreference) preference; + editTextPreference.setSummary(editTextPreference.getText()); + } + } + + @Override + public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { + if (TextUtils.equals( + preference.getKey(), getString(R.string.vvm_config_override_load_current_key))) { + loadCurrentConfig(); + } + return super.onPreferenceTreeClick(preferenceScreen, preference); + } + + /** + * Loads the config for the currently carrier into the override values, from the dialer or the + * carrier config app. This is a "reset" button to load the defaults. + */ + private void loadCurrentConfig() { + Context context = getActivity(); + PhoneAccountHandle phoneAccountHandle = + context + .getSystemService(TelecomManager.class) + .getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_VOICEMAIL); + + PersistableBundle config = + VoicemailComponent.get(context).getVoicemailClient().getConfig(context, phoneAccountHandle); + + for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) { + Preference preference = getPreferenceScreen().getPreference(i); + String key = preference.getKey(); + if (!key.startsWith(CONFIG_OVERRIDE_KEY_PREFIX)) { + continue; + } + + String configKey = key.substring(CONFIG_OVERRIDE_KEY_PREFIX.length()); + + if (configKey.endsWith("bool")) { + ((SwitchPreference) preference).setChecked(config.getBoolean(configKey)); + } else if (configKey.endsWith("int")) { + ((EditTextPreference) preference).setText(String.valueOf(config.getInt(configKey))); + } else if (configKey.endsWith("string")) { + ((EditTextPreference) preference).setText(config.getString(configKey)); + } else if (configKey.endsWith("string_array")) { + ((EditTextPreference) preference).setText(toCsv(config.getStringArray(configKey))); + } else { + throw Assert.createAssertionFailException("unknown type for key " + configKey); + } + updatePreference(preference); + } + } + + public static boolean isOverridden(Context context) { + return DialerStrictMode.bypass( + () -> + PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(context.getString(R.string.vvm_config_override_enabled_key), false)); + } + + public static PersistableBundle getConfig(Context context) { + Assert.checkState(isOverridden(context)); + PersistableBundle result = new PersistableBundle(); + + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + for (String key : preferences.getAll().keySet()) { + if (!key.startsWith(CONFIG_OVERRIDE_KEY_PREFIX)) { + continue; + } + String configKey = key.substring(CONFIG_OVERRIDE_KEY_PREFIX.length()); + if (configKey.endsWith("bool")) { + result.putBoolean(configKey, preferences.getBoolean(key, false)); + } else if (configKey.endsWith("int")) { + result.putInt(configKey, Integer.valueOf(preferences.getString(key, null))); + } else if (configKey.endsWith("string")) { + result.putString(configKey, preferences.getString(key, null)); + } else if (configKey.endsWith("string_array")) { + result.putStringArray(configKey, fromCsv(preferences.getString(key, null))); + } else { + throw Assert.createAssertionFailException("unknown type for key " + configKey); + } + } + return result; + } + + private static String toCsv(String[] array) { + if (array == null) { + return ""; + } + StringBuilder result = new StringBuilder(); + for (String element : array) { + if (result.length() != 0) { + result.append(","); + } + result.append(element); + } + return result.toString(); + }; + + private static String[] fromCsv(String csv) { + return csv.split(","); + } +} diff --git a/java/com/android/voicemail/impl/configui/VoicemailSecretCodeActivity.java b/java/com/android/voicemail/impl/configui/VoicemailSecretCodeActivity.java new file mode 100644 index 000000000..beeb9564d --- /dev/null +++ b/java/com/android/voicemail/impl/configui/VoicemailSecretCodeActivity.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.voicemail.impl.configui; + +import android.content.Intent; +import android.preference.PreferenceActivity; +import android.provider.VoicemailContract; +import java.util.List; + +/** Activity launched by simulator->voicemail, provides debug features. */ +@SuppressWarnings("FragmentInjection") // not exported +public class VoicemailSecretCodeActivity extends PreferenceActivity { + + private Header syncHeader; + + @Override + public void onBuildHeaders(List
target) { + super.onBuildHeaders(target); + syncHeader = new Header(); + syncHeader.title = "Sync"; + target.add(syncHeader); + + Header configOverride = new Header(); + configOverride.fragment = ConfigOverrideFragment.class.getName(); + configOverride.title = "VVM config override"; + target.add(configOverride); + } + + @Override + public void onHeaderClick(Header header, int position) { + if (header == syncHeader) { + Intent intent = new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL); + intent.setPackage(getPackageName()); + sendBroadcast(intent); + return; + } + super.onHeaderClick(header, position); + } + + @Override + protected boolean isValidFragment(String fragmentName) { + return true; + } +} diff --git a/java/com/android/voicemail/impl/configui/res/values-af/strings.xml b/java/com/android/voicemail/impl/configui/res/values-af/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-af/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-am/strings.xml b/java/com/android/voicemail/impl/configui/res/values-am/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-am/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ar/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ar/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ar/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-az/strings.xml b/java/com/android/voicemail/impl/configui/res/values-az/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-az/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-b+sr+Latn/strings.xml b/java/com/android/voicemail/impl/configui/res/values-b+sr+Latn/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-be/strings.xml b/java/com/android/voicemail/impl/configui/res/values-be/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-be/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-bg/strings.xml b/java/com/android/voicemail/impl/configui/res/values-bg/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-bg/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-bn/strings.xml b/java/com/android/voicemail/impl/configui/res/values-bn/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-bn/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-bs/strings.xml b/java/com/android/voicemail/impl/configui/res/values-bs/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-bs/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ca/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ca/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ca/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-cs/strings.xml b/java/com/android/voicemail/impl/configui/res/values-cs/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-cs/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-da/strings.xml b/java/com/android/voicemail/impl/configui/res/values-da/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-da/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-de/strings.xml b/java/com/android/voicemail/impl/configui/res/values-de/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-de/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-el/strings.xml b/java/com/android/voicemail/impl/configui/res/values-el/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-el/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-en-rAU/strings.xml b/java/com/android/voicemail/impl/configui/res/values-en-rAU/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-en-rAU/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-en-rGB/strings.xml b/java/com/android/voicemail/impl/configui/res/values-en-rGB/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-en-rGB/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-en-rIN/strings.xml b/java/com/android/voicemail/impl/configui/res/values-en-rIN/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-en-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-es-rUS/strings.xml b/java/com/android/voicemail/impl/configui/res/values-es-rUS/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-es-rUS/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-es/strings.xml b/java/com/android/voicemail/impl/configui/res/values-es/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-es/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-et/strings.xml b/java/com/android/voicemail/impl/configui/res/values-et/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-et/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-eu/strings.xml b/java/com/android/voicemail/impl/configui/res/values-eu/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-eu/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-fa/strings.xml b/java/com/android/voicemail/impl/configui/res/values-fa/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-fa/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-fi/strings.xml b/java/com/android/voicemail/impl/configui/res/values-fi/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-fi/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-fr-rCA/strings.xml b/java/com/android/voicemail/impl/configui/res/values-fr-rCA/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-fr-rCA/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-fr/strings.xml b/java/com/android/voicemail/impl/configui/res/values-fr/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-fr/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-gl/strings.xml b/java/com/android/voicemail/impl/configui/res/values-gl/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-gl/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-gu/strings.xml b/java/com/android/voicemail/impl/configui/res/values-gu/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-gu/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-hi/strings.xml b/java/com/android/voicemail/impl/configui/res/values-hi/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-hi/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-hr/strings.xml b/java/com/android/voicemail/impl/configui/res/values-hr/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-hr/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-hu/strings.xml b/java/com/android/voicemail/impl/configui/res/values-hu/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-hu/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-hy/strings.xml b/java/com/android/voicemail/impl/configui/res/values-hy/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-hy/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-in/strings.xml b/java/com/android/voicemail/impl/configui/res/values-in/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-in/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-is/strings.xml b/java/com/android/voicemail/impl/configui/res/values-is/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-is/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-it/strings.xml b/java/com/android/voicemail/impl/configui/res/values-it/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-it/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-iw/strings.xml b/java/com/android/voicemail/impl/configui/res/values-iw/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-iw/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ja/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ja/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ja/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ka/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ka/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ka/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-kk/strings.xml b/java/com/android/voicemail/impl/configui/res/values-kk/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-kk/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-km/strings.xml b/java/com/android/voicemail/impl/configui/res/values-km/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-km/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-kn/strings.xml b/java/com/android/voicemail/impl/configui/res/values-kn/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-kn/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ko/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ko/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ko/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ky/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ky/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ky/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-lo/strings.xml b/java/com/android/voicemail/impl/configui/res/values-lo/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-lo/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-lt/strings.xml b/java/com/android/voicemail/impl/configui/res/values-lt/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-lt/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-lv/strings.xml b/java/com/android/voicemail/impl/configui/res/values-lv/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-lv/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-mk/strings.xml b/java/com/android/voicemail/impl/configui/res/values-mk/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-mk/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ml/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ml/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ml/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-mn/strings.xml b/java/com/android/voicemail/impl/configui/res/values-mn/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-mn/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-mr/strings.xml b/java/com/android/voicemail/impl/configui/res/values-mr/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-mr/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ms/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ms/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ms/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-my/strings.xml b/java/com/android/voicemail/impl/configui/res/values-my/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-my/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-nb/strings.xml b/java/com/android/voicemail/impl/configui/res/values-nb/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-nb/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ne/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ne/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ne/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-nl/strings.xml b/java/com/android/voicemail/impl/configui/res/values-nl/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-nl/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-no/strings.xml b/java/com/android/voicemail/impl/configui/res/values-no/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-no/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-pa/strings.xml b/java/com/android/voicemail/impl/configui/res/values-pa/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-pa/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-pl/strings.xml b/java/com/android/voicemail/impl/configui/res/values-pl/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-pl/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-pt-rBR/strings.xml b/java/com/android/voicemail/impl/configui/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-pt-rBR/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-pt-rPT/strings.xml b/java/com/android/voicemail/impl/configui/res/values-pt-rPT/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-pt-rPT/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-pt/strings.xml b/java/com/android/voicemail/impl/configui/res/values-pt/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-pt/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ro/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ro/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ro/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ru/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ru/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ru/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-si/strings.xml b/java/com/android/voicemail/impl/configui/res/values-si/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-si/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-sk/strings.xml b/java/com/android/voicemail/impl/configui/res/values-sk/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-sk/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-sl/strings.xml b/java/com/android/voicemail/impl/configui/res/values-sl/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-sl/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-sq/strings.xml b/java/com/android/voicemail/impl/configui/res/values-sq/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-sq/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-sr/strings.xml b/java/com/android/voicemail/impl/configui/res/values-sr/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-sr/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-sv/strings.xml b/java/com/android/voicemail/impl/configui/res/values-sv/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-sv/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-sw/strings.xml b/java/com/android/voicemail/impl/configui/res/values-sw/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-sw/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ta/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ta/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ta/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-te/strings.xml b/java/com/android/voicemail/impl/configui/res/values-te/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-te/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-th/strings.xml b/java/com/android/voicemail/impl/configui/res/values-th/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-th/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-tl/strings.xml b/java/com/android/voicemail/impl/configui/res/values-tl/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-tl/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-tr/strings.xml b/java/com/android/voicemail/impl/configui/res/values-tr/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-tr/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-uk/strings.xml b/java/com/android/voicemail/impl/configui/res/values-uk/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-uk/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-ur/strings.xml b/java/com/android/voicemail/impl/configui/res/values-ur/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-ur/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-uz/strings.xml b/java/com/android/voicemail/impl/configui/res/values-uz/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-uz/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-vi/strings.xml b/java/com/android/voicemail/impl/configui/res/values-vi/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-vi/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-zh-rCN/strings.xml b/java/com/android/voicemail/impl/configui/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-zh-rCN/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-zh-rHK/strings.xml b/java/com/android/voicemail/impl/configui/res/values-zh-rHK/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-zh-rHK/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-zh-rTW/strings.xml b/java/com/android/voicemail/impl/configui/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-zh-rTW/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values-zu/strings.xml b/java/com/android/voicemail/impl/configui/res/values-zu/strings.xml new file mode 100644 index 000000000..826efd3cd --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values-zu/strings.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/java/com/android/voicemail/impl/configui/res/values/strings.xml b/java/com/android/voicemail/impl/configui/res/values/strings.xml new file mode 100644 index 000000000..fea76be02 --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/values/strings.xml @@ -0,0 +1,21 @@ + + + + + vvm_config_override_load_current + vvm_config_override_enabled + + diff --git a/java/com/android/voicemail/impl/configui/res/xml/vvm_config_override.xml b/java/com/android/voicemail/impl/configui/res/xml/vvm_config_override.xml new file mode 100644 index 000000000..c4a23c789 --- /dev/null +++ b/java/com/android/voicemail/impl/configui/res/xml/vvm_config_override.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/com/android/voicemail/impl/fetch/VoicemailFetchedCallback.java b/java/com/android/voicemail/impl/fetch/VoicemailFetchedCallback.java index f386fce0e..3e825407b 100644 --- a/java/com/android/voicemail/impl/fetch/VoicemailFetchedCallback.java +++ b/java/com/android/voicemail/impl/fetch/VoicemailFetchedCallback.java @@ -23,9 +23,12 @@ import android.provider.VoicemailContract.Voicemails; import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; +import com.android.dialer.common.Assert; +import com.android.dialer.common.concurrent.ThreadUtil; import com.android.voicemail.impl.R; import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.imap.VoicemailPayload; +import com.android.voicemail.impl.transcribe.TranscriptionService; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.io.IOUtils; @@ -56,6 +59,7 @@ public class VoicemailFetchedCallback { * @param voicemailPayload The object containing the content data for the voicemail */ public void setVoicemailContent(@Nullable VoicemailPayload voicemailPayload) { + Assert.isWorkerThread(); if (voicemailPayload == null) { VvmLog.i(TAG, "Payload not found, message has unsupported format"); ContentValues values = new ContentValues(); @@ -90,13 +94,23 @@ public class VoicemailFetchedCallback { ContentValues values = new ContentValues(); values.put(Voicemails.MIME_TYPE, voicemailPayload.getMimeType()); values.put(Voicemails.HAS_CONTENT, true); - updateVoicemail(values); + if (updateVoicemail(values)) { + ThreadUtil.postOnUiThread( + () -> { + if (!TranscriptionService.scheduleNewVoicemailTranscriptionJob(mContext, mUri, true)) { + VvmLog.w(TAG, String.format("Failed to schedule transcription for %s", mUri)); + } + }); + } } - private void updateVoicemail(ContentValues values) { + private boolean updateVoicemail(ContentValues values) { int updatedCount = mContentResolver.update(mUri, values, null, null); if (updatedCount != 1) { VvmLog.e(TAG, "Updating voicemail should have updated 1 row, was: " + updatedCount); + return false; + } else { + return true; } } } diff --git a/java/com/android/voicemail/impl/imap/ImapHelper.java b/java/com/android/voicemail/impl/imap/ImapHelper.java index f1bc8b221..94abe9bad 100644 --- a/java/com/android/voicemail/impl/imap/ImapHelper.java +++ b/java/com/android/voicemail/impl/imap/ImapHelper.java @@ -251,13 +251,18 @@ public class ImapHelper implements Closeable { long time = messageDetails.getSentDate().getTime(); String number = getNumber(messageDetails.getFrom()); boolean isRead = Arrays.asList(messageDetails.getFlags()).contains(Flag.SEEN); - return Voicemail.createForInsertion(time, number) - .setPhoneAccount(mPhoneAccount) - .setSourcePackage(mContext.getPackageName()) - .setSourceData(messageDetails.getUid()) - .setIsRead(isRead) - .setTranscription(listener.getVoicemailTranscription()) - .build(); + Long duration = messageDetails.getDuration(); + Voicemail.Builder builder = + Voicemail.createForInsertion(time, number) + .setPhoneAccount(mPhoneAccount) + .setSourcePackage(mContext.getPackageName()) + .setSourceData(messageDetails.getUid()) + .setIsRead(isRead) + .setTranscription(listener.getVoicemailTranscription()); + if (duration != null) { + builder.setDuration(duration); + } + return builder.build(); } /** diff --git a/java/com/android/voicemail/impl/mail/MailTransport.java b/java/com/android/voicemail/impl/mail/MailTransport.java index 3df36d544..c35e41450 100644 --- a/java/com/android/voicemail/impl/mail/MailTransport.java +++ b/java/com/android/voicemail/impl/mail/MailTransport.java @@ -17,7 +17,9 @@ package com.android.voicemail.impl.mail; import android.content.Context; import android.net.Network; +import android.net.TrafficStats; import android.support.annotation.VisibleForTesting; +import com.android.dialer.constants.TrafficStatsTags; import com.android.voicemail.impl.OmtpEvents; import com.android.voicemail.impl.imap.ImapHelper; import com.android.voicemail.impl.mail.store.ImapStore; @@ -188,10 +190,13 @@ public class MailTransport { try { LogUtils.v(TAG, "createSocket: network specified"); + TrafficStats.setThreadStatsTag(TrafficStatsTags.VISUAL_VOICEMAIL_TAG); return mNetwork.getSocketFactory().createSocket(); } catch (IOException ioe) { LogUtils.d(TAG, ioe.toString()); throw new MessagingException(MessagingException.IOERROR, ioe.toString()); + } finally { + TrafficStats.clearThreadStatsTag(); } } diff --git a/java/com/android/voicemail/impl/mail/Message.java b/java/com/android/voicemail/impl/mail/Message.java index aea5d3ead..ca65d3d73 100644 --- a/java/com/android/voicemail/impl/mail/Message.java +++ b/java/com/android/voicemail/impl/mail/Message.java @@ -15,6 +15,7 @@ */ package com.android.voicemail.impl.mail; +import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import java.util.Date; import java.util.HashSet; @@ -64,6 +65,9 @@ public abstract class Message implements Part, Body { public abstract void setSentDate(Date sentDate) throws MessagingException; + @Nullable + public abstract Long getDuration() throws MessagingException; + public abstract Address[] getRecipients(String type) throws MessagingException; public abstract void setRecipients(String type, Address[] addresses) throws MessagingException; diff --git a/java/com/android/voicemail/impl/mail/internet/MimeHeader.java b/java/com/android/voicemail/impl/mail/internet/MimeHeader.java index d41cdb3e4..8f0817650 100644 --- a/java/com/android/voicemail/impl/mail/internet/MimeHeader.java +++ b/java/com/android/voicemail/impl/mail/internet/MimeHeader.java @@ -36,6 +36,7 @@ public class MimeHeader { public static final String HEADER_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding"; public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition"; public static final String HEADER_CONTENT_ID = "Content-ID"; + public static final String HEADER_CONTENT_DURATION = "Content-Duration"; /** Fields that should be omitted when writing the header using writeTo() */ private static final String[] WRITE_OMIT_FIELDS = { diff --git a/java/com/android/voicemail/impl/mail/internet/MimeMessage.java b/java/com/android/voicemail/impl/mail/internet/MimeMessage.java index 589720660..39378a092 100644 --- a/java/com/android/voicemail/impl/mail/internet/MimeMessage.java +++ b/java/com/android/voicemail/impl/mail/internet/MimeMessage.java @@ -15,7 +15,9 @@ */ package com.android.voicemail.impl.mail.internet; +import android.support.annotation.Nullable; import android.text.TextUtils; +import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.mail.Address; import com.android.voicemail.impl.mail.Body; import com.android.voicemail.impl.mail.BodyPart; @@ -196,6 +198,28 @@ public class MimeMessage extends Message { this.mSentDate = sentDate; } + @Override + @Nullable + public Long getDuration() { + String durationHeader = null; + try { + durationHeader = getFirstHeader(MimeHeader.HEADER_CONTENT_DURATION); + } catch (MessagingException e) { + VvmLog.e("MimeMessage.getDuration", "cannot retrieve header: ", e); + return null; + } + if (durationHeader == null) { + VvmLog.w("MimeMessage.getDuration", "message missing Content-Duration header"); + return null; + } + try { + return Long.valueOf(durationHeader); + } catch (NumberFormatException e) { + VvmLog.w("MimeMessage.getDuration", "cannot parse duration " + durationHeader); + return null; + } + } + @Override public String getContentType() throws MessagingException { final String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE); diff --git a/java/com/android/voicemail/impl/mail/store/imap/ImapConstants.java b/java/com/android/voicemail/impl/mail/store/imap/ImapConstants.java index 88ec0ed90..fd56952d7 100644 --- a/java/com/android/voicemail/impl/mail/store/imap/ImapConstants.java +++ b/java/com/android/voicemail/impl/mail/store/imap/ImapConstants.java @@ -27,7 +27,7 @@ public final class ImapConstants { public static final String FETCH_FIELD_BODY_PEEK_SANE = String.format(Locale.US, "BODY.PEEK[]<0.%d>", ImapStore.FETCH_BODY_SANE_SUGGESTED_SIZE); public static final String FETCH_FIELD_HEADERS = - "BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc message-id)]"; + "BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc message-id content-duration)]"; public static final String ALERT = "ALERT"; public static final String APPEND = "APPEND"; diff --git a/java/com/android/voicemail/impl/proguard.flags b/java/com/android/voicemail/impl/proguard.flags new file mode 100644 index 000000000..9379df322 --- /dev/null +++ b/java/com/android/voicemail/impl/proguard.flags @@ -0,0 +1,4 @@ +-assumenosideeffects class com.android.voicemail.impl.VvmLog { + public static void v(...); + public static void d(...); +} diff --git a/java/com/android/voicemail/impl/protocol/OmtpProtocol.java b/java/com/android/voicemail/impl/protocol/OmtpProtocol.java index 27aab8a7c..971edcf4f 100644 --- a/java/com/android/voicemail/impl/protocol/OmtpProtocol.java +++ b/java/com/android/voicemail/impl/protocol/OmtpProtocol.java @@ -35,7 +35,7 @@ public class OmtpProtocol extends VisualVoicemailProtocol { phoneAccountHandle, applicationPort, destinationNumber, - OmtpConstants.CLIENT_TYPE_GOOGLE_10, + OmtpConstants.getClientType(), OmtpConstants.PROTOCOL_VERSION1_1, null /*clientPrefix*/); } diff --git a/java/com/android/voicemail/impl/protocol/Vvm3Subscriber.java b/java/com/android/voicemail/impl/protocol/Vvm3Subscriber.java index 1cdbbfbca..d9a06494e 100644 --- a/java/com/android/voicemail/impl/protocol/Vvm3Subscriber.java +++ b/java/com/android/voicemail/impl/protocol/Vvm3Subscriber.java @@ -31,7 +31,7 @@ import android.text.Html; import android.text.Spanned; import android.text.style.URLSpan; import android.util.ArrayMap; -import com.android.dialer.common.ConfigProviderBindings; +import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.voicemail.impl.ActivationTask; import com.android.voicemail.impl.Assert; import com.android.voicemail.impl.OmtpEvents; diff --git a/java/com/android/voicemail/impl/res/values-af/strings.xml b/java/com/android/voicemail/impl/res/values-af/strings.xml index 2e829c9b9..0ed54fa8c 100644 --- a/java/com/android/voicemail/impl/res/values-af/strings.xml +++ b/java/com/android/voicemail/impl/res/values-af/strings.xml @@ -26,8 +26,6 @@ "Verander PIN" "Visuele stemboodskap moet geaktiveer wees om PIN te verander" "Visuele stemboodskap is nog nie geaktiveer nie, probeer asseblief later weer" - "Ou PIN" - "Nuwe PIN" "Wag asseblief." "Die nuwe PIN is te kort." "Die nuwe PIN is te lank." diff --git a/java/com/android/voicemail/impl/res/values-am/strings.xml b/java/com/android/voicemail/impl/res/values-am/strings.xml index 183f7b76e..39b21b478 100644 --- a/java/com/android/voicemail/impl/res/values-am/strings.xml +++ b/java/com/android/voicemail/impl/res/values-am/strings.xml @@ -26,8 +26,6 @@ "ፒን ይቀይሩ" "ፒን ለመቀየር የእይታ የድምጽ መልዕክት መንቃት አለበት" "የእይታ የድምጽ መልዕክት ገና ገቢር አልሆነም፣ እባክዎ ቆይተው እንደገና ይሞክሩ" - "የቀድሞ ፒን" - "አዲስ ፒን" "እባክዎ ይጠብቁ።" "አዲሱ ፒን በጣም አጭር ነው።" "አዲሱ ፒን በጣም ረጅም ነው።" diff --git a/java/com/android/voicemail/impl/res/values-ar/strings.xml b/java/com/android/voicemail/impl/res/values-ar/strings.xml index 8b75b6e5b..4cdba4dfc 100644 --- a/java/com/android/voicemail/impl/res/values-ar/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ar/strings.xml @@ -25,9 +25,7 @@ "تعيين رقم التعريف الشخصي" "تغيير رقم التعريف الشخصي" "ينبغي تشغيل البريد الصوتي المرئي لتغيير رقم التعريف الشخصي" - "لم يتم تنشيط البريد الصوتي المرئي بعد، الرجاء المحاولة مرة أخرى لاحقًا" - "رقم التعريف الشخصي القديم" - "رقم التعريف الشخصي الجديد" + "لم يتم تنشيط البريد الصوتي المرئي بعد، يُرجى المحاولة مرة أخرى لاحقًا" "يُرجى الانتظار." "رقم التعريف الشخصي الجديد قصير جدًا." "رقم التعريف الشخصي الجديد طويل جدًا." diff --git a/java/com/android/voicemail/impl/res/values-az/strings.xml b/java/com/android/voicemail/impl/res/values-az/strings.xml index 978365055..f24573075 100644 --- a/java/com/android/voicemail/impl/res/values-az/strings.xml +++ b/java/com/android/voicemail/impl/res/values-az/strings.xml @@ -26,8 +26,6 @@ "PIN-i dəyişin" "PIN-i dəyişmək üçün görünən səsli e-poçt aktiv olmalıdır" "Görünən səsli e-poçt hələ aktiv edilməyib, daha sonra yenidən cəhd edin" - "Köhnə PIN" - "Yeni PIN" "Gözləyin." "Yeni PIN çox qısadır." "Yeni PIN çox uzundur." diff --git a/java/com/android/voicemail/impl/res/values-b+sr+Latn/strings.xml b/java/com/android/voicemail/impl/res/values-b+sr+Latn/strings.xml index f7c7a62dc..7c12c9e64 100644 --- a/java/com/android/voicemail/impl/res/values-b+sr+Latn/strings.xml +++ b/java/com/android/voicemail/impl/res/values-b+sr+Latn/strings.xml @@ -26,8 +26,6 @@ "Promenite PIN" "Morate da omogućite vizuelnu govornu poštu da biste promenili PIN" "Vizuelna govorna pošta još uvek nije aktivirana, probajte ponovo kasnije" - "Stari PIN" - "Novi PIN" "Sačekajte." "Novi PIN je prekratak." "Novi PIN je predugačak." diff --git a/java/com/android/voicemail/impl/res/values-be/strings.xml b/java/com/android/voicemail/impl/res/values-be/strings.xml index 6f4d1250d..c88f8ab98 100644 --- a/java/com/android/voicemail/impl/res/values-be/strings.xml +++ b/java/com/android/voicemail/impl/res/values-be/strings.xml @@ -26,8 +26,6 @@ "Змяніць PIN-код" "Трэба ўключыць візуальную галасавую пошту, каб змяніць PIN-код" "Візуальная галасавая пошта пакуль не актываваная. Паўтарыце спробу пазней" - "Стары PIN-код" - "Новы PIN-код" "Пачакайце." "Новы PIN-код занадта кароткі." "Новы PIN-код занадта доўгі." diff --git a/java/com/android/voicemail/impl/res/values-bg/strings.xml b/java/com/android/voicemail/impl/res/values-bg/strings.xml index 553c8f3ed..380efe23a 100644 --- a/java/com/android/voicemail/impl/res/values-bg/strings.xml +++ b/java/com/android/voicemail/impl/res/values-bg/strings.xml @@ -26,8 +26,6 @@ "Промяна на ПИН кода" "За промяна на ПИН кода трябва да бъде активирана визуалната гласова поща" "Визуалната гласова поща още не е активирана. Моля, опитайте отново по-късно" - "Стар ПИН" - "Нов ПИН" "Моля, изчакайте." "Новият ПИН е твърде къс." "Новият ПИН е твърде дълъг." diff --git a/java/com/android/voicemail/impl/res/values-bn/strings.xml b/java/com/android/voicemail/impl/res/values-bn/strings.xml index 362240ae6..011a74ec1 100644 --- a/java/com/android/voicemail/impl/res/values-bn/strings.xml +++ b/java/com/android/voicemail/impl/res/values-bn/strings.xml @@ -26,8 +26,6 @@ "পিন পরিবর্তন করুন" "পিন পরিবর্তন করতে ভিজ্যুয়াল ভয়েসমেল অবশ্যই সক্ষম করতে হবে" "ভিজ্যুয়াল ভয়েসমেল এখনও সক্রিয় করা হয়নি, অনুগ্রহ করে পরে আবার চেষ্টা করুন" - "পুরোনো PIN" - "নতুন PIN" "অনুগ্রহ করে অপেক্ষা করুন৷" "নতুন PIN খুবই ছোট৷" "নতুন PIN খুবই বড়৷" diff --git a/java/com/android/voicemail/impl/res/values-bs/strings.xml b/java/com/android/voicemail/impl/res/values-bs/strings.xml index f897a61e5..0a26706a5 100644 --- a/java/com/android/voicemail/impl/res/values-bs/strings.xml +++ b/java/com/android/voicemail/impl/res/values-bs/strings.xml @@ -26,8 +26,6 @@ "Promijenite PIN kôd" "Vizuelna govorna pošta mora biti omogućena za promjenu PIN kôda" "Vizuelna govorna pošta još uvijek nije aktivirana, pokušajte ponovo kasnije" - "Stari PIN kod" - "Novi PIN kod" "Pričekajte." "Novi PIN kod je prekratak." "Novi PIN kod je predug." diff --git a/java/com/android/voicemail/impl/res/values-ca/strings.xml b/java/com/android/voicemail/impl/res/values-ca/strings.xml index 51e19fb45..5c36ea716 100644 --- a/java/com/android/voicemail/impl/res/values-ca/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ca/strings.xml @@ -26,8 +26,6 @@ "Canvia el PIN" "La bústia de veu visual ha d\'estar activada per poder canviar el PIN" "La bústia de veu visual encara no està activada. Torna-ho a provar més tard." - "PIN antic" - "PIN nou" "Espera." "El PIN nou és massa curt." "El PIN nou és massa llarg." diff --git a/java/com/android/voicemail/impl/res/values-cs/strings.xml b/java/com/android/voicemail/impl/res/values-cs/strings.xml index 38ef3fe5f..ddef49171 100644 --- a/java/com/android/voicemail/impl/res/values-cs/strings.xml +++ b/java/com/android/voicemail/impl/res/values-cs/strings.xml @@ -26,8 +26,6 @@ "Změnit kód PIN" "Pokud chcete kód PIN změnit, musíte mít zapnutou vizuální hlasovou schránku" "Vizuální hlasová schránka zatím není aktivovaná, zkuste to prosím znovu později" - "Starý kód PIN" - "Nový kód PIN" "Čekejte prosím." "Nový kód PIN je příliš krátký." "Nový kód PIN je příliš dlouhý." diff --git a/java/com/android/voicemail/impl/res/values-da/strings.xml b/java/com/android/voicemail/impl/res/values-da/strings.xml index 7e471171d..64e658852 100644 --- a/java/com/android/voicemail/impl/res/values-da/strings.xml +++ b/java/com/android/voicemail/impl/res/values-da/strings.xml @@ -26,8 +26,6 @@ "Skift pinkode" "Visuel telefonsvarer skal være aktiveret, for at du kan skifte pinkode" "Visuel telefonsvarer er ikke aktiveret endnu. Prøv igen senere" - "Nuværende pinkode" - "Ny pinkode" "Vent et øjeblik." "Den nye pinkode er for kort." "Den nye pinkode er for lang." diff --git a/java/com/android/voicemail/impl/res/values-de/strings.xml b/java/com/android/voicemail/impl/res/values-de/strings.xml index 35b86f2c7..9b162759c 100644 --- a/java/com/android/voicemail/impl/res/values-de/strings.xml +++ b/java/com/android/voicemail/impl/res/values-de/strings.xml @@ -26,8 +26,6 @@ "PIN ändern" "Die visuelle Mailbox muss aktiviert sein, um die PIN zu ändern" "Die visuelle Mailbox wurde noch nicht aktiviert, bitte versuche es später noch einmal" - "Alte PIN" - "Neue PIN" "Bitte warten." "Die neue PIN ist zu kurz." "Die neue PIN ist zu lang." diff --git a/java/com/android/voicemail/impl/res/values-el/strings.xml b/java/com/android/voicemail/impl/res/values-el/strings.xml index 11711bb4a..b197b1c21 100644 --- a/java/com/android/voicemail/impl/res/values-el/strings.xml +++ b/java/com/android/voicemail/impl/res/values-el/strings.xml @@ -26,8 +26,6 @@ "Αλλαγή κωδικού PIN" "Για αλλαγή του PIN, ενεργοποιήστε τον οπτικό αυτόματο τηλεφωνητή" "Ο οπτικός αυτόματος τηλεφωνητής δεν έχει ενεργοποιηθεί ακόμα. Δοκιμάστε ξανά αργότερα." - "Παλιός αριθμός PIN" - "Νέος αριθμός PIN" "Περιμένετε." "Το νέο PIN είναι πολύ μικρό." "Το νέο PIN είναι πολύ μεγάλo." diff --git a/java/com/android/voicemail/impl/res/values-en-rAU/strings.xml b/java/com/android/voicemail/impl/res/values-en-rAU/strings.xml index be29e4736..f49f9ff12 100644 --- a/java/com/android/voicemail/impl/res/values-en-rAU/strings.xml +++ b/java/com/android/voicemail/impl/res/values-en-rAU/strings.xml @@ -26,8 +26,6 @@ "Change PIN" "Visual voicemail must be enabled to change PIN" "Visual voicemail is not activated yet. Please try again later" - "Old PIN" - "New PIN" "Please wait." "The new PIN is too short." "The new PIN is too long." diff --git a/java/com/android/voicemail/impl/res/values-en-rGB/strings.xml b/java/com/android/voicemail/impl/res/values-en-rGB/strings.xml index be29e4736..f49f9ff12 100644 --- a/java/com/android/voicemail/impl/res/values-en-rGB/strings.xml +++ b/java/com/android/voicemail/impl/res/values-en-rGB/strings.xml @@ -26,8 +26,6 @@ "Change PIN" "Visual voicemail must be enabled to change PIN" "Visual voicemail is not activated yet. Please try again later" - "Old PIN" - "New PIN" "Please wait." "The new PIN is too short." "The new PIN is too long." diff --git a/java/com/android/voicemail/impl/res/values-en-rIN/strings.xml b/java/com/android/voicemail/impl/res/values-en-rIN/strings.xml index be29e4736..f49f9ff12 100644 --- a/java/com/android/voicemail/impl/res/values-en-rIN/strings.xml +++ b/java/com/android/voicemail/impl/res/values-en-rIN/strings.xml @@ -26,8 +26,6 @@ "Change PIN" "Visual voicemail must be enabled to change PIN" "Visual voicemail is not activated yet. Please try again later" - "Old PIN" - "New PIN" "Please wait." "The new PIN is too short." "The new PIN is too long." diff --git a/java/com/android/voicemail/impl/res/values-es-rUS/strings.xml b/java/com/android/voicemail/impl/res/values-es-rUS/strings.xml index e958ecf9e..f5aeeb9f3 100644 --- a/java/com/android/voicemail/impl/res/values-es-rUS/strings.xml +++ b/java/com/android/voicemail/impl/res/values-es-rUS/strings.xml @@ -26,8 +26,6 @@ "Cambiar PIN" "El buzón de voz visual se debe activar para cambiar el PIN" "El buzón de voz visual aún no está activado. Vuelve a intentarlo más tarde." - "PIN anterior" - "PIN nuevo" "Espera." "El PIN nuevo es demasiado corto." "El PIN nuevo es demasiado largo." diff --git a/java/com/android/voicemail/impl/res/values-es/strings.xml b/java/com/android/voicemail/impl/res/values-es/strings.xml index b965ca0c5..3dc171396 100644 --- a/java/com/android/voicemail/impl/res/values-es/strings.xml +++ b/java/com/android/voicemail/impl/res/values-es/strings.xml @@ -26,8 +26,6 @@ "Cambiar PIN" "Para poder cambiar el PIN, el buzón de voz visual debe estar habilitado" "El buzón de voz visual aún no está activado; inténtalo de nuevo más tarde" - "PIN antiguo" - "PIN nuevo" "Espera..." "El PIN nuevo es muy corto." "El PIN nuevo es muy largo." diff --git a/java/com/android/voicemail/impl/res/values-et/strings.xml b/java/com/android/voicemail/impl/res/values-et/strings.xml index 28042ec10..e964dcd00 100644 --- a/java/com/android/voicemail/impl/res/values-et/strings.xml +++ b/java/com/android/voicemail/impl/res/values-et/strings.xml @@ -26,8 +26,6 @@ "PIN-koodi muutmine" "PIN-koodi muutmiseks peab olema lubatud visuaalne kõnepost" "Visuaalne kõnepost pole veel aktiveeritud, proovige hiljem uuesti" - "Vana PIN-kood" - "Uus PIN-kood" "Oodake." "Uus PIN-kood on liiga lühike." "Uus PIN-kood on liiga pikk." diff --git a/java/com/android/voicemail/impl/res/values-eu/strings.xml b/java/com/android/voicemail/impl/res/values-eu/strings.xml index ff2f34c0a..398ff2382 100644 --- a/java/com/android/voicemail/impl/res/values-eu/strings.xml +++ b/java/com/android/voicemail/impl/res/values-eu/strings.xml @@ -26,8 +26,6 @@ "Aldatu PIN kodea" "Ikusizko erantzungailuak gaituta egon behar du PIN kodea aldatu ahal izateko" "Oraindik ez dago aktibatuta ikusizko erantzungailua. Saiatu berriro geroago." - "PIN zaharra" - "PIN berria" "Itxaron, mesedez." "Laburregia da PIN kode berria." "Luzeegia da PIN kode berria." diff --git a/java/com/android/voicemail/impl/res/values-fa/strings.xml b/java/com/android/voicemail/impl/res/values-fa/strings.xml index bba6541ee..c57da2662 100644 --- a/java/com/android/voicemail/impl/res/values-fa/strings.xml +++ b/java/com/android/voicemail/impl/res/values-fa/strings.xml @@ -26,8 +26,6 @@ "تغییر پین" "برای تغییر پین، پست صوتی تصویری باید فعال شود" "پست صوتی تصویری هنوز فعال نشده است، لطفاً بعداً دوباره امتحان کنید" - "پین قدیمی" - "پین جدید" "لطفاً منتظر بمانید." "پین جدید خیلی کوتاه است." "پین جدید خیلی طولانی است." diff --git a/java/com/android/voicemail/impl/res/values-fi/strings.xml b/java/com/android/voicemail/impl/res/values-fi/strings.xml index 6886effbf..bb1d2d0ce 100644 --- a/java/com/android/voicemail/impl/res/values-fi/strings.xml +++ b/java/com/android/voicemail/impl/res/values-fi/strings.xml @@ -26,8 +26,6 @@ "Vaihda PIN-koodi" "Ota visuaalinen puhelinvastaaja käyttöön, jotta voit vaihtaa PIN-koodin." "Visuaalista puhelinvastaajaa ei ole vielä aktivoitu. Yritä myöhemmin uudelleen." - "Vanha PIN-koodi" - "Uusi PIN-koodi" "Odota." "Uusi PIN-koodi on liian lyhyt." "Uusi PIN-koodi on liian pitkä." diff --git a/java/com/android/voicemail/impl/res/values-fr-rCA/strings.xml b/java/com/android/voicemail/impl/res/values-fr-rCA/strings.xml index 3e485e0a3..92b7df6dd 100644 --- a/java/com/android/voicemail/impl/res/values-fr-rCA/strings.xml +++ b/java/com/android/voicemail/impl/res/values-fr-rCA/strings.xml @@ -26,8 +26,6 @@ "Modifier le NIP" "La messagerie vocale visuelle doit être activée pour que vous puissiez modifier votre NIP" "La messagerie vocale visuelle n\'a pas encore été activée. Veuillez réessayer plus tard" - "Ancien NIP" - "Nouveau NIP" "Veuillez patienter." "Le nouveau NIP est trop court." "Le nouveau NIP est trop long." diff --git a/java/com/android/voicemail/impl/res/values-fr/strings.xml b/java/com/android/voicemail/impl/res/values-fr/strings.xml index e540f6085..771c32436 100644 --- a/java/com/android/voicemail/impl/res/values-fr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-fr/strings.xml @@ -26,8 +26,6 @@ "Modifier le code secret" "Pour que vous puissiez modifier le code secret, la messagerie vocale visuelle doit être activée" "La messagerie vocale visuelle n\'est pas encore activée. Veuillez réessayer plus tard" - "Ancien code" - "Nouveau code" "Veuillez patienter." "Le nouveau code est trop court." "Le nouveau code est trop long." diff --git a/java/com/android/voicemail/impl/res/values-gl/strings.xml b/java/com/android/voicemail/impl/res/values-gl/strings.xml index b059879bc..22f401fef 100644 --- a/java/com/android/voicemail/impl/res/values-gl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-gl/strings.xml @@ -26,8 +26,6 @@ "Cambiar PIN" "Para poder cambiar o PIN, o correo de voz visual ten que estar activado" "O correo de voz visual aínda non está activado. Téntao de novo máis tarde" - "PIN antigo" - "PIN novo" "Agarda." "O novo PIN é demasiado curto." "O novo PIN é demasiado longo." diff --git a/java/com/android/voicemail/impl/res/values-gu/strings.xml b/java/com/android/voicemail/impl/res/values-gu/strings.xml index 3ec3c5d1a..107fd4762 100644 --- a/java/com/android/voicemail/impl/res/values-gu/strings.xml +++ b/java/com/android/voicemail/impl/res/values-gu/strings.xml @@ -26,8 +26,6 @@ "PIN બદલો" "PIN બદલવા માટે વિઝ્યુઅલ વૉઇસમેઇલ સક્ષમ હોય તે આવશ્યક છે" "વિઝ્યુઅલ વૉઇસમેઇલ હજુ સુધી સક્રિય નથી, કૃપા કરીને પછીથી ફરી પ્રયાસ કરો" - "જૂનો PIN" - "નવો PIN" "કૃપા કરીને રાહ જુઓ." "નવો PIN ખૂબ ટૂંકો છે." "નવો PIN ખૂબ લાંબો છે." diff --git a/java/com/android/voicemail/impl/res/values-hi/strings.xml b/java/com/android/voicemail/impl/res/values-hi/strings.xml index 545fffd4d..88613708b 100644 --- a/java/com/android/voicemail/impl/res/values-hi/strings.xml +++ b/java/com/android/voicemail/impl/res/values-hi/strings.xml @@ -26,8 +26,6 @@ "पिन बदलें" "पिन बदलने के लिए विज़ुअल वॉइसमेल ज़रूर सक्षम होना चाहिए" "विज़ुअल वॉइसमेल को अभी तक सक्रिय नहीं किया गया है, कृपया बाद में फिर से कोशिश करें" - "पुराना पिन" - "नया पिन" "कृपया प्रतीक्षा करें." "नया पिन बहुत छोटा है." "नया पिन बहुत बड़ा है." diff --git a/java/com/android/voicemail/impl/res/values-hr/strings.xml b/java/com/android/voicemail/impl/res/values-hr/strings.xml index 9d5d60636..ee1bf1f57 100644 --- a/java/com/android/voicemail/impl/res/values-hr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-hr/strings.xml @@ -26,8 +26,6 @@ "Promjena PIN-a" "Za promjenu PIN-a potrebno je omogućiti vizualnu govornu poštu" "Vizualna govorna pošta još nije aktivirana, pokušajte ponovno kasnije" - "Stari PIN" - "Novi PIN" "Pričekajte." "Novi PIN je prekratak." "Novi PIN je predugačak." diff --git a/java/com/android/voicemail/impl/res/values-hu/strings.xml b/java/com/android/voicemail/impl/res/values-hu/strings.xml index 982ba995a..d761d40cd 100644 --- a/java/com/android/voicemail/impl/res/values-hu/strings.xml +++ b/java/com/android/voicemail/impl/res/values-hu/strings.xml @@ -26,8 +26,6 @@ "PIN-kód módosítása" "A PIN-kód módosításához engedélyezni kell a vizuális hangpostát." "A vizuális hangposta még nincs aktiválva. Engedélyezze később." - "Régi PIN-kód" - "Új PIN-kód" "Kérjük, várjon." "Az új PIN-kód túl rövid." "Az új PIN-kód túl hosszú." diff --git a/java/com/android/voicemail/impl/res/values-hy/strings.xml b/java/com/android/voicemail/impl/res/values-hy/strings.xml index 00a132ddd..008aeeeb6 100644 --- a/java/com/android/voicemail/impl/res/values-hy/strings.xml +++ b/java/com/android/voicemail/impl/res/values-hy/strings.xml @@ -26,8 +26,6 @@ "Փոխեք PIN կոդը" "PIN կոդը փոխելու համար տեսողական ձայնային փոստը պետք է միացված լինի" "Տեսողական ձայնային փոստը դեռ ակտիվացված չէ: Փորձեք ավելի ուշ:" - "Հին PIN կոդ" - "Նոր PIN կոդ" "Սպասեք:" "Նոր PIN կոդը չափազանց կարճ է:" "Նոր PIN կոդը չափազանց երկար է:" diff --git a/java/com/android/voicemail/impl/res/values-in/strings.xml b/java/com/android/voicemail/impl/res/values-in/strings.xml index 7523fc9e8..cda3a1a50 100644 --- a/java/com/android/voicemail/impl/res/values-in/strings.xml +++ b/java/com/android/voicemail/impl/res/values-in/strings.xml @@ -26,8 +26,6 @@ "Ubah PIN" "Pesan suara visual harus diaktifkan untuk mengubah PIN" "Pesan suara visual belum diaktifkan, coba lagi nanti" - "PIN lama" - "PIN Baru" "Mohon tunggu." "PIN baru terlalu pendek." "PIN baru terlalu panjang." diff --git a/java/com/android/voicemail/impl/res/values-is/strings.xml b/java/com/android/voicemail/impl/res/values-is/strings.xml index b2e616b0e..44ef9e068 100644 --- a/java/com/android/voicemail/impl/res/values-is/strings.xml +++ b/java/com/android/voicemail/impl/res/values-is/strings.xml @@ -26,8 +26,6 @@ "Breyta PIN-númeri" "Kveikt þarf að vera á myndrænu talhólfi til að breyta PIN-númeri" "Ekki er búið að virkja myndrænt talhólf. Reyndu aftur síðar" - "Gamla PIN-númerið" - "Nýtt PIN-númer" "Augnablik." "Nýja PIN-númerið er of stutt." "Nýja PIN-númerið er of langt." diff --git a/java/com/android/voicemail/impl/res/values-it/strings.xml b/java/com/android/voicemail/impl/res/values-it/strings.xml index f4fea84fb..afbbbc234 100644 --- a/java/com/android/voicemail/impl/res/values-it/strings.xml +++ b/java/com/android/voicemail/impl/res/values-it/strings.xml @@ -26,8 +26,6 @@ "Cambia PIN" "La lettura delle segreteria deve essere attivata per cambiare il PIN" "Lettura della segreteria non attivata. Riprova più tardi" - "PIN attuale" - "Nuovo PIN" "Attendi." "Il nuovo PIN è troppo corto." "Il nuovo PIN è troppo lungo." diff --git a/java/com/android/voicemail/impl/res/values-iw/strings.xml b/java/com/android/voicemail/impl/res/values-iw/strings.xml index e48e35ded..acc2e6c50 100644 --- a/java/com/android/voicemail/impl/res/values-iw/strings.xml +++ b/java/com/android/voicemail/impl/res/values-iw/strings.xml @@ -26,8 +26,6 @@ "שינוי קוד הגישה" "צריך להפעיל את הדואר הקולי הוויזואלי כדי לשנות את קוד הגישה" "הדואר הקולי הוויזואלי לא הופעל עדיין. נסה שוב מאוחר יותר" - "קוד הגישה הישן" - "קוד הגישה החדש" "נא להמתין." "קוד הגישה החדש קצר מדי." "קוד הגישה החדש ארוך מדי." diff --git a/java/com/android/voicemail/impl/res/values-ja/strings.xml b/java/com/android/voicemail/impl/res/values-ja/strings.xml index cd825d2e1..f0d6a9b5a 100644 --- a/java/com/android/voicemail/impl/res/values-ja/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ja/strings.xml @@ -26,8 +26,6 @@ "PIN の変更" "PIN を変更するには、ビジュアル ボイスメールを有効にする必要があります" "ビジュアル ボイスメールがまだ有効になっていません。しばらくしてからもう一度お試しください" - "古い PIN" - "新しい PIN" "お待ちください。" "新しい PIN が短すぎます。" "新しい PIN が長すぎます。" diff --git a/java/com/android/voicemail/impl/res/values-ka/strings.xml b/java/com/android/voicemail/impl/res/values-ka/strings.xml index 12a677a62..84c13b10f 100644 --- a/java/com/android/voicemail/impl/res/values-ka/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ka/strings.xml @@ -26,8 +26,6 @@ "PIN-კოდის შეცვლა" "PIN-კოდის შესაცვლელად ჩართული უნდა იყოს ვიზუალური ხმოვანი ფოსტა" "ვიზუალური ხმოვანი ფოსტა ჯერ გააქტიურებული არ არის. გთხოვთ, სცადოთ ხელახლა." - "ძველი PIN-კოდი" - "ახალი PIN-კოდი" "გთხოვთ, დაელოდოთ." "ახალი PIN-კოდი ძალიან მოკლეა." "ახალი PIN-კოდი ძალიან გრძელია." diff --git a/java/com/android/voicemail/impl/res/values-kk/strings.xml b/java/com/android/voicemail/impl/res/values-kk/strings.xml index 08c7cce30..c2afc8e46 100644 --- a/java/com/android/voicemail/impl/res/values-kk/strings.xml +++ b/java/com/android/voicemail/impl/res/values-kk/strings.xml @@ -26,8 +26,6 @@ "PIN кодын өзгерту" "PIN кодын өзгерту үшін визуалды дауыс хабарын қосу қажет" "Визуалды дауыс хабары әлі қосылмаған. Кейінірек қайталап көріңіз" - "Ескі PIN коды" - "Жаңа PIN коды" "Күте тұрыңыз." "Жаңа PIN коды тым қысқа." "Жаңа PIN коды тым ұзын." diff --git a/java/com/android/voicemail/impl/res/values-km/strings.xml b/java/com/android/voicemail/impl/res/values-km/strings.xml index ea3d6ff47..55a225367 100644 --- a/java/com/android/voicemail/impl/res/values-km/strings.xml +++ b/java/com/android/voicemail/impl/res/values-km/strings.xml @@ -26,8 +26,6 @@ "ផ្លាស់ប្ដូរ​កូដ PIN" "សារ​​ជា​សំឡេង​ដែល​មើល​ឃើញ​ត្រូវតែ​បើកដំណើរការ ដើម្បី​ផ្លាស់ប្ដូរ PIN" "សារ​ជាសំឡេង​ដែល​មើល​ឃើញ​មិនទាន់​​ត្រូវ​បាន​ធ្វើ​ឲ្យ​សកម្ម​នៅ​ឡើយ​ទេ សូម​ព្យាយាម​ម្ដង​ទៀត​នៅ​ពេល​ក្រោយ" - "កូដ PIN ចាស់" - "កូដ PIN ថ្មី" "សូមរង់ចាំ។" "កូដ PIN ថ្មី​ ខ្លី​ពេក។" "កូដ PIN ថ្មី​ វែង​ពេក។" diff --git a/java/com/android/voicemail/impl/res/values-kn/strings.xml b/java/com/android/voicemail/impl/res/values-kn/strings.xml index 48e14f57b..695c8d455 100644 --- a/java/com/android/voicemail/impl/res/values-kn/strings.xml +++ b/java/com/android/voicemail/impl/res/values-kn/strings.xml @@ -26,8 +26,6 @@ "ಪಿನ್‌ ಬದಲಾಯಿಸಿ" "ಪಿನ್ ಬದಲಾಯಿಸಲು ದೃಶ್ಯ ಧ್ವನಿಮೇಲ್ ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು" "ದೃಶ್ಯ ಧ್ವನಿಮೇಲ್ ಇನ್ನೂ ಸಕ್ರಿಯವಾಗಿಲ್ಲ, ದಯವಿಟ್ಟು ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ" - "ಹಳೆಯ ಪಿನ್" - "ಹೊಸ ಪಿನ್‌" "ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ." "ಹೊಸ ಪಿನ್ ತುಂಬಾ ಚಿಕ್ಕದಾಗಿದೆ." "ಹೊಸ ಪಿನ್ ತುಂಬಾ ಉದ್ದವಾಗಿದೆ." diff --git a/java/com/android/voicemail/impl/res/values-ko/strings.xml b/java/com/android/voicemail/impl/res/values-ko/strings.xml index 1138a5b0f..7f1d8b03f 100644 --- a/java/com/android/voicemail/impl/res/values-ko/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ko/strings.xml @@ -26,8 +26,6 @@ "PIN 변경" "PIN을 변경하려면 시각적 음성사서함이 사용 설정되어 있어야 합니다." "시각적 음성사서함이 아직 활성 상태가 아닙니다. 나중에 다시 시도해 주세요." - "이전 PIN" - "새 PIN" "기다려 주세요." "새 PIN이 너무 짧습니다." "새 PIN이 너무 깁니다." diff --git a/java/com/android/voicemail/impl/res/values-ky/strings.xml b/java/com/android/voicemail/impl/res/values-ky/strings.xml index b54d2b4d9..736a56ac6 100644 --- a/java/com/android/voicemail/impl/res/values-ky/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ky/strings.xml @@ -26,8 +26,6 @@ "PIN кодду өзгөртүү" "PIN кодду өзгөртүү үчүн визуладык үн почтасын иштетүү керек" "Визуалдык үн почтаңыз күйгүзүлгөн жок. Кайра аракет кылыңыз." - "Эски PIN код" - "Жаңы PIN код" "Күтө туруңуз." "Жаңы PIN код өтө эле кыска." "Жаңы PIN код өтө эле узун." diff --git a/java/com/android/voicemail/impl/res/values-lo/strings.xml b/java/com/android/voicemail/impl/res/values-lo/strings.xml index 2052059b4..fb0313361 100644 --- a/java/com/android/voicemail/impl/res/values-lo/strings.xml +++ b/java/com/android/voicemail/impl/res/values-lo/strings.xml @@ -26,8 +26,6 @@ "​ປ່ຽນ​ລະຫັດ PIN" "ຈະຕ້ອງເປີດໃຊ້ຂໍ້ຄວາມສຽງສະເໝືອນເພື່ອປ່ຽນ PIN" "ຍັງບໍໄດ້ເປີດໃຊ້ຂໍ້ຄວາມສຽງສະເໝືອນເທື່ອ, ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ" - "ລະຫັດ PIN ເກົ່າ" - "ລະຫັດ PIN ໃໝ່" "ກະລຸນາລໍຖ້າ." "ລະຫັດ PIN ໃໝ່ສັ້ນເກີນໄປ." "ລະຫັດ PIN ໃໝ່ຍາວເກີນໄປ." diff --git a/java/com/android/voicemail/impl/res/values-lt/strings.xml b/java/com/android/voicemail/impl/res/values-lt/strings.xml index 4d7d378b9..c9891abf4 100644 --- a/java/com/android/voicemail/impl/res/values-lt/strings.xml +++ b/java/com/android/voicemail/impl/res/values-lt/strings.xml @@ -26,8 +26,6 @@ "PIN kodo keitimas" "Vaizdinis balso paštas turi būti įgalintas, kad būtų galima pakeisti PIN kodą" "Vaizdinis balso paštas dar nesuaktyvintas, vėliau bandykite dar kartą" - "Senas PIN kodas" - "Naujas PIN kodas" "Palaukite." "Naujas PIN kodas per trumpas." "Naujas PIN kodas per ilgas." diff --git a/java/com/android/voicemail/impl/res/values-lv/strings.xml b/java/com/android/voicemail/impl/res/values-lv/strings.xml index 776f1029a..7a26aa043 100644 --- a/java/com/android/voicemail/impl/res/values-lv/strings.xml +++ b/java/com/android/voicemail/impl/res/values-lv/strings.xml @@ -26,8 +26,6 @@ "PIN mainīšana" "Lai varētu mainīt PIN, ir jābūt iespējotam vizuālajam balss pastam." "Vizuālais balss pasts vēl nav aktivizēts. Lūdzu, vēlāk mēģiniet vēlreiz." - "Iepriekšējais PIN" - "Jaunais PIN" "Lūdzu, uzgaidiet!" "Jaunais PIN ir pārāk īss." "Jaunais PIN ir pārāk garš." diff --git a/java/com/android/voicemail/impl/res/values-mk/strings.xml b/java/com/android/voicemail/impl/res/values-mk/strings.xml index 52ec73d7c..2ef8faeb5 100644 --- a/java/com/android/voicemail/impl/res/values-mk/strings.xml +++ b/java/com/android/voicemail/impl/res/values-mk/strings.xml @@ -26,8 +26,6 @@ "Променете PIN" "За променување на PIN-кодот, мора да се овозможи визуелна говорна пошта" "Визуелната говорна пошта сѐ уште не е активна. Обидете се повторно подоцна" - "Стар PIN" - "Нов PIN" "Почекајте." "Новиот PIN е премногу кус." "Новиот PIN е премногу долг." diff --git a/java/com/android/voicemail/impl/res/values-ml/strings.xml b/java/com/android/voicemail/impl/res/values-ml/strings.xml index baece4692..ac0ad23c1 100644 --- a/java/com/android/voicemail/impl/res/values-ml/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ml/strings.xml @@ -26,8 +26,6 @@ "പിൻ മാറ്റുക" "പിൻ മാറ്റുന്നതിന് വിഷ്വൽ വോയ്‌സ്‌മെയിൽ പ്രവർത്തനക്ഷമമാക്കേണ്ടതുണ്ട്" "വിഷ്വൽ വോയ്‌സ്‌മെയിൽ ഇതുവരെ സജീവമാക്കിയിട്ടില്ല, പിന്നീട് വീണ്ടും ശ്രമിച്ചുനോക്കൂ" - "പഴയ പിൻ" - "പുതിയ പിൻ" "കാത്തിരിക്കുക." "പുതിയ പിൻ വളരെ ചെറുതാണ്." "പുതിയ പിൻ വളരെ ദൈർഘ്യമേറിയതാണ്." diff --git a/java/com/android/voicemail/impl/res/values-mn/strings.xml b/java/com/android/voicemail/impl/res/values-mn/strings.xml index 58c31344a..96e0e42b4 100644 --- a/java/com/android/voicemail/impl/res/values-mn/strings.xml +++ b/java/com/android/voicemail/impl/res/values-mn/strings.xml @@ -26,8 +26,6 @@ "PIN өөрчлөх" "Харагдах дуут шуудан PIN-г өөрчлөх боломжтой байх ёстой" "Харагдах дуут шуудан хараахан идэвхжээгүй байна, дараа дахин оролдоно уу" - "Хуучин PIN" - "Шинэ PIN" "Түр хүлээнэ үү." "Шинэ PIN хэт богино байна." "Шинэ PIN хэт урт байна." diff --git a/java/com/android/voicemail/impl/res/values-mr/strings.xml b/java/com/android/voicemail/impl/res/values-mr/strings.xml index 17a7f7a47..85b5270e5 100644 --- a/java/com/android/voicemail/impl/res/values-mr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-mr/strings.xml @@ -26,8 +26,6 @@ "पिन बदला" "पिन बदलण्‍यासाठी व्हिज्युअल व्हॉइसमेल सक्षम करणे आवश्‍यक आहे" "व्हिज्युअल व्हॉइसमेल अद्याप सक्रिय केले नाही, कृपया नंतर पुन्हा प्रयत्न करा" - "जुना पिन" - "नवीन पिन" "कृपया प्रतीक्षा करा." "नवीन पिन खूप लहान आहे." "नवीन पिन खूप दीर्घ आहे." @@ -46,6 +44,6 @@ "पिन %1$d-%2$d अंकी असणे आवश्‍यक आहे." "आपल्या पिनची पुष्टी करा" "पिन जुळत नाहीत" - "व्हॉइसमेल पिन अद्यतनित केला" + "व्हॉइसमेल पिन अपडेट केला" "पिन सेट करण्यात अक्षम" diff --git a/java/com/android/voicemail/impl/res/values-ms/strings.xml b/java/com/android/voicemail/impl/res/values-ms/strings.xml index b58445126..c44ba38a8 100644 --- a/java/com/android/voicemail/impl/res/values-ms/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ms/strings.xml @@ -26,8 +26,6 @@ "Tukar PIN" "Mel suara visual mesti didayakan untuk menukar PIN" "Mel suara visual belum diaktifkan. Sila cuba sebentar lagi" - "PIN Lama" - "PIN Baharu" "Sila tunggu." "PIN baharu terlalu pendek." "PIN baharu terlalu panjang." diff --git a/java/com/android/voicemail/impl/res/values-my/strings.xml b/java/com/android/voicemail/impl/res/values-my/strings.xml index b29c8521f..d9ef363e3 100644 --- a/java/com/android/voicemail/impl/res/values-my/strings.xml +++ b/java/com/android/voicemail/impl/res/values-my/strings.xml @@ -26,8 +26,6 @@ "ပင်နံပါတ် ပြောင်းပါ" "ပင်နံပါတ်ပြောင်းရန် စာသားမှတ်တမ်းပါ အသံမေးလ်ကို ဖွင့်ထားရပါမည်" "စာသားမှတ်တမ်းပါ အသံမေးလ်ကို မဖွင့်ရသေးပါ၊ နောက်မှ ထပ်ဖွင့်ကြည့်ပါ" - "ပင်နံပါတ်အဟောင်း" - "ပင်နံပါတ်အသစ်" "ခဏစောင့်ပါ။" "ပင်နံပါတ်အသစ်မှာ တိုလွန်းနေသည်။" "ပင်နံပါတ်အသစ်မှာ ရှည်လွန်းနေသည်။" diff --git a/java/com/android/voicemail/impl/res/values-nb/strings.xml b/java/com/android/voicemail/impl/res/values-nb/strings.xml index b6a1e1c6d..7139887b9 100644 --- a/java/com/android/voicemail/impl/res/values-nb/strings.xml +++ b/java/com/android/voicemail/impl/res/values-nb/strings.xml @@ -26,8 +26,6 @@ "Endre PIN-koden" "Du må slå på visuell talepost for å endre PIN-koden" "Visuell talepost er ikke slått på ennå – prøv igjen senere" - "Gammel PIN-kode" - "Ny PIN-kode" "Vent litt." "Den nye PIN-koden er for kort." "Den nye PIN-koden er for lang." diff --git a/java/com/android/voicemail/impl/res/values-ne/strings.xml b/java/com/android/voicemail/impl/res/values-ne/strings.xml index f0b4bd88f..44c8bb0fb 100644 --- a/java/com/android/voicemail/impl/res/values-ne/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ne/strings.xml @@ -26,8 +26,6 @@ "PIN परिवर्तन गर्नुहोस्" "PIN परिवर्तन गर्न अनिवार्य रूपले भिजुअल भ्वाइस मेललाई सक्षम पारिनुपर्छ" "भिजुअल भ्वाइस मेललाई अझै सक्रिय पारिएको छैन, कृपया पुन: प्रयास गर्नुहोस्" - "पुरानो PIN" - "नयाँ PIN" "कृपया प्रतीक्षा गर्नुहोस्।" "नयाँ PIN अत्यन्त छोटो छ।" "नयाँ PIN अत्यन्त लामो छ।" diff --git a/java/com/android/voicemail/impl/res/values-nl/strings.xml b/java/com/android/voicemail/impl/res/values-nl/strings.xml index f32723b20..1e3788df4 100644 --- a/java/com/android/voicemail/impl/res/values-nl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-nl/strings.xml @@ -26,8 +26,6 @@ "Pincode wijzigen" "Visuele voicemail moet zijn ingeschakeld om de pincode te wijzigen" "Visuele voicemail is nog niet geactiveerd. Probeer het later opnieuw." - "Oude pincode" - "Nieuwe pincode" "Even geduld." "De nieuwe pincode is te kort." "De nieuwe pincode is te lang." diff --git a/java/com/android/voicemail/impl/res/values-no/strings.xml b/java/com/android/voicemail/impl/res/values-no/strings.xml index b6a1e1c6d..7139887b9 100644 --- a/java/com/android/voicemail/impl/res/values-no/strings.xml +++ b/java/com/android/voicemail/impl/res/values-no/strings.xml @@ -26,8 +26,6 @@ "Endre PIN-koden" "Du må slå på visuell talepost for å endre PIN-koden" "Visuell talepost er ikke slått på ennå – prøv igjen senere" - "Gammel PIN-kode" - "Ny PIN-kode" "Vent litt." "Den nye PIN-koden er for kort." "Den nye PIN-koden er for lang." diff --git a/java/com/android/voicemail/impl/res/values-pa/strings.xml b/java/com/android/voicemail/impl/res/values-pa/strings.xml index 635308577..d65588d50 100644 --- a/java/com/android/voicemail/impl/res/values-pa/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pa/strings.xml @@ -26,8 +26,6 @@ "PIN ਬਦਲੋ" "ਦ੍ਰਿਸ਼ਟਾਂਤਕ ਵੌਇਸਮੇਲ ਨੂੰ PIN ਬਦਲਣ ਲਈ ਯੋਗ ਬਣਾਇਆ ਜਾਣਾ ਲਾਜ਼ਮੀ ਹੈ" "ਦ੍ਰਿਸ਼ਟਾਂਤਕ ਵੌਇਸਮੇਲ ਹਾਲੇ ਕਿਰਿਆਸ਼ੀਲ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ" - "ਪੁਰਾਣਾ PIN" - "ਨਵਾਂ PIN" "ਕਿਰਪਾ ਕਰਕੇ ਉਡੀਕ ਕਰੋ।" "ਨਵਾਂ PIN ਬਹੁਤ ਹੀ ਛੋਟਾ ਹੈ।" "ਨਵਾਂ PIN ਬਹੁਤ ਹੀ ਲੰਬਾ ਹੈ।" diff --git a/java/com/android/voicemail/impl/res/values-pl/strings.xml b/java/com/android/voicemail/impl/res/values-pl/strings.xml index 17382149a..ae3dcf75d 100644 --- a/java/com/android/voicemail/impl/res/values-pl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pl/strings.xml @@ -26,8 +26,6 @@ "Zmień kod PIN" "Aby można było zmienić kod PIN, wizualna poczta głosowa musi być włączona" "Wizualna poczta głosowa nie została jeszcze aktywowana – spróbuj ponownie później" - "Stary kod PIN" - "Nowy kod PIN" "Poczekaj." "Nowy kod PIN jest za krótki." "Nowy kod PIN jest za długi." diff --git a/java/com/android/voicemail/impl/res/values-pt-rBR/strings.xml b/java/com/android/voicemail/impl/res/values-pt-rBR/strings.xml index 69f285b15..f2c2f4e38 100644 --- a/java/com/android/voicemail/impl/res/values-pt-rBR/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pt-rBR/strings.xml @@ -26,8 +26,6 @@ "Alterar PIN" "O correio de voz visual precisa ser ativado para alterar o PIN" "O correio de voz visual ainda não foi ativado, tente novamente mais tarde" - "PIN antigo" - "Novo PIN" "Aguarde." "O novo PIN é curto demais." "O novo PIN é longo demais." diff --git a/java/com/android/voicemail/impl/res/values-pt-rPT/strings.xml b/java/com/android/voicemail/impl/res/values-pt-rPT/strings.xml index ddff14a3b..b92a54c7b 100644 --- a/java/com/android/voicemail/impl/res/values-pt-rPT/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pt-rPT/strings.xml @@ -26,8 +26,6 @@ "Alterar PIN" "A mensagem de correio de voz visual tem de estar ativada para poder alterar o PIN" "A mensagem de correio de voz visual ainda não está ativada. Tente novamente mais tarde" - "PIN antigo" - "Novo PIN" "Aguarde." "O novo PIN é demasiado curto." "O novo PIN é demasiado longo." diff --git a/java/com/android/voicemail/impl/res/values-pt/strings.xml b/java/com/android/voicemail/impl/res/values-pt/strings.xml index 69f285b15..f2c2f4e38 100644 --- a/java/com/android/voicemail/impl/res/values-pt/strings.xml +++ b/java/com/android/voicemail/impl/res/values-pt/strings.xml @@ -26,8 +26,6 @@ "Alterar PIN" "O correio de voz visual precisa ser ativado para alterar o PIN" "O correio de voz visual ainda não foi ativado, tente novamente mais tarde" - "PIN antigo" - "Novo PIN" "Aguarde." "O novo PIN é curto demais." "O novo PIN é longo demais." diff --git a/java/com/android/voicemail/impl/res/values-ro/strings.xml b/java/com/android/voicemail/impl/res/values-ro/strings.xml index 00eee2441..165171bf4 100644 --- a/java/com/android/voicemail/impl/res/values-ro/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ro/strings.xml @@ -26,8 +26,6 @@ "Schimbați codul PIN" "Mesageria vocală vizuală trebuie activată pentru a schimba codul PIN." "Mesageria vocală vizuală nu este activată încă. Încercați din nou mai târziu." - "Codul PIN vechi" - "Codul PIN nou" "Așteptați." "Codul PIN nou este prea scurt." "Codul PIN nou este prea lung." diff --git a/java/com/android/voicemail/impl/res/values-ru/strings.xml b/java/com/android/voicemail/impl/res/values-ru/strings.xml index 8537ac90a..99a0b5404 100644 --- a/java/com/android/voicemail/impl/res/values-ru/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ru/strings.xml @@ -26,8 +26,6 @@ "Изменение PIN-кода" "Чтобы изменить PIN-код, включите визуальную голосовую почту" "Визуальная голосовая почта пока не активирована, повторите попытку позже" - "Прежний PIN-код" - "Новый PIN-код" "Подождите…" "Новый PIN-код слишком короткий." "Новый PIN-код слишком длинный." diff --git a/java/com/android/voicemail/impl/res/values-si/strings.xml b/java/com/android/voicemail/impl/res/values-si/strings.xml index a72200fee..7879678bf 100644 --- a/java/com/android/voicemail/impl/res/values-si/strings.xml +++ b/java/com/android/voicemail/impl/res/values-si/strings.xml @@ -26,8 +26,6 @@ "PIN අංකය වෙනස් කරන්න" "PIN අංකය වෙනස් කිරීමට දෘශ්‍ය හඬ තැපෑල සබල කළ යුතුය" "දෘශ්‍ය හඬ තැපෑල තවම සක්‍රිය කර නැත, කරුණාකර පසුව නැවත උත්සාහ කරන්න" - "පැරණි PIN අංකය" - "නව PIN අංකය" "කරුණාකර රැඳී සිටින්න." "නව PIN අංකය කෙටි වැඩිය." "නව PIN අංකය දිග වැඩිය." diff --git a/java/com/android/voicemail/impl/res/values-sk/strings.xml b/java/com/android/voicemail/impl/res/values-sk/strings.xml index 8e06b68bb..a6deaa6c3 100644 --- a/java/com/android/voicemail/impl/res/values-sk/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sk/strings.xml @@ -26,8 +26,6 @@ "Zmena kódu PIN" "PIN možno zmeniť až po povolení vizuálnej hlasovej schránky" "Vizuálna hlasová schránka ešte nie je aktivovaná, skúste to znova neskôr" - "Starý PIN" - "Nový PIN" "Čakajte." "Nový PIN je príliš krátky." "Nový PIN je príliš dlhý." diff --git a/java/com/android/voicemail/impl/res/values-sl/strings.xml b/java/com/android/voicemail/impl/res/values-sl/strings.xml index a62fa90d3..bf515c0ad 100644 --- a/java/com/android/voicemail/impl/res/values-sl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sl/strings.xml @@ -26,8 +26,6 @@ "Sprememba kode PIN" "Če želite spremeniti kodo PIN, morajo biti vizualna sporočila v odzivniku omogočena" "Vizualna sporočila v odzivniku še niso aktivirana. Poskusite znova pozneje" - "Stara koda PIN" - "Nova koda PIN" "Počakajte." "Nova koda PIN je prekratka." "Nova koda PIN je predolga." diff --git a/java/com/android/voicemail/impl/res/values-sq/strings.xml b/java/com/android/voicemail/impl/res/values-sq/strings.xml index c0f1b1235..09104c886 100644 --- a/java/com/android/voicemail/impl/res/values-sq/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sq/strings.xml @@ -26,8 +26,6 @@ "Ndrysho kodin PIN" "Duhet të aktivizohet posta zanore vizuale për të ndryshuar kodin PIN" "Posta zanore vizuale nuk është aktivizuar ende. Provo përsëri më vonë" - "Kodi PIN i vjetër" - "Kodi PIN i ri" "Prit..." "Kodi i ri PIN është shumë i shkurtër." "Kodi i ri PIN është shumë i gjatë." diff --git a/java/com/android/voicemail/impl/res/values-sr/strings.xml b/java/com/android/voicemail/impl/res/values-sr/strings.xml index ec6d6a420..ea0ce7b74 100644 --- a/java/com/android/voicemail/impl/res/values-sr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sr/strings.xml @@ -26,8 +26,6 @@ "Промените PIN" "Морате да омогућите визуелну говорну пошту да бисте променили PIN" "Визуелна говорна пошта још увек није активирана, пробајте поново касније" - "Стари PIN" - "Нови PIN" "Сачекајте." "Нови PIN је прекратак." "Нови PIN је предугачак." diff --git a/java/com/android/voicemail/impl/res/values-sv/strings.xml b/java/com/android/voicemail/impl/res/values-sv/strings.xml index a23875328..89a1e230a 100644 --- a/java/com/android/voicemail/impl/res/values-sv/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sv/strings.xml @@ -26,8 +26,6 @@ "Ändra pinkod" "Visuell röstbrevlåda måste vara aktiverat för att ändra pinkoden" "Visuell röstbrevlåda är ännu inte aktiverad, försök igen senare" - "Gammal pinkod" - "Ny pinkod" "Vänta." "Den nya pinkoden är för kort." "Den nya pinkoden är för lång." diff --git a/java/com/android/voicemail/impl/res/values-sw/strings.xml b/java/com/android/voicemail/impl/res/values-sw/strings.xml index d749ddfac..d8c7557ba 100644 --- a/java/com/android/voicemail/impl/res/values-sw/strings.xml +++ b/java/com/android/voicemail/impl/res/values-sw/strings.xml @@ -26,8 +26,6 @@ "Badilisha PIN" "Lazima uruhusu kipengele cha ujumbe wa sauti unaoonekana ili ubadilishe PIN" "Kipengele cha ujumbe wa sauti unaoonekana bado hakijawashwa, tafadhali jaribu tena baadaye" - "PIN ya zamani" - "PIN mpya" "Tafadhali subiri." "PIN mpya ni fupi mno." "PIN mpya ni ndefu mno." diff --git a/java/com/android/voicemail/impl/res/values-ta/strings.xml b/java/com/android/voicemail/impl/res/values-ta/strings.xml index de0dc4afc..1b965aa53 100644 --- a/java/com/android/voicemail/impl/res/values-ta/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ta/strings.xml @@ -26,8 +26,6 @@ "பின்னை மாற்று" "பின்னை மாற்ற, விஷுவல் குரலஞ்சலை இயக்க வேண்டும்" "விஷுவல் குரலஞ்சல் இன்னும் இயக்கப்படவில்லை. பிறகு முயலவும்" - "பழைய பின்" - "புதிய பின்" "காத்திருக்கவும்." "புதிய பின் மிகவும் சிறியதாக உள்ளது." "புதிய பின் மிகவும் நீளமாக உள்ளது." diff --git a/java/com/android/voicemail/impl/res/values-te/strings.xml b/java/com/android/voicemail/impl/res/values-te/strings.xml index 1459ddc76..089a1ba63 100644 --- a/java/com/android/voicemail/impl/res/values-te/strings.xml +++ b/java/com/android/voicemail/impl/res/values-te/strings.xml @@ -26,8 +26,6 @@ "PINను మార్చండి" "PINని మార్చడానికి తప్పనిసరిగా దృశ్యమాన వాయిస్ మెయిల్‌ను ప్రారంభించాలి" "దృశ్యమాన వాయిస్ మెయిల్‌ ఇంకా సక్రియం కాలేదు, దయచేసి తర్వాత మళ్లీ ప్రయత్నించండి" - "పాత PIN" - "కొత్త PIN" "దయచేసి వేచి ఉండండి." "కొత్త PIN చాలా చిన్నదిగా ఉంది." "కొత్త PIN చాలా పొడవుగా ఉంది." diff --git a/java/com/android/voicemail/impl/res/values-th/strings.xml b/java/com/android/voicemail/impl/res/values-th/strings.xml index 056800c6f..130ea26ff 100644 --- a/java/com/android/voicemail/impl/res/values-th/strings.xml +++ b/java/com/android/voicemail/impl/res/values-th/strings.xml @@ -26,8 +26,6 @@ "เปลี่ยน PIN" "ต้องเปิดใช้ข้อความเสียงพร้อมภาพเพื่อเปลี่ยน PIN" "ยังไม่ได้เปิดใช้งานข้อความเสียงพร้อมภาพ โปรดลองอีกครั้งในภายหลัง" - "PIN เก่า" - "PIN ใหม่" "โปรดรอสักครู่" "PIN ใหม่สั้นเกินไป" "PIN ใหม่ยาวเกินไป" diff --git a/java/com/android/voicemail/impl/res/values-tl/strings.xml b/java/com/android/voicemail/impl/res/values-tl/strings.xml index c32236231..58d18837a 100644 --- a/java/com/android/voicemail/impl/res/values-tl/strings.xml +++ b/java/com/android/voicemail/impl/res/values-tl/strings.xml @@ -26,8 +26,6 @@ "Palitan ang PIN" "Dapat naka-enable ang visual na voicemail upang palitan ang PIN" "Hindi pa naka-activate ang visual na voicemail, pakisubukang muli sa ibang pagkakataon" - "Lumang PIN" - "Bagong PIN" "Pakihintay." "Masyadong maikli ang bagong PIN." "Masyadong mahaba ang bagong PIN." diff --git a/java/com/android/voicemail/impl/res/values-tr/strings.xml b/java/com/android/voicemail/impl/res/values-tr/strings.xml index a80b40b99..578cf959a 100644 --- a/java/com/android/voicemail/impl/res/values-tr/strings.xml +++ b/java/com/android/voicemail/impl/res/values-tr/strings.xml @@ -26,8 +26,6 @@ "PIN\'i değiştirin" "PIN\'i değiştirebilmek için görsel sesli mesaj etkinleştirilmelidir" "Görsel sesli mesaj henüz etkinleştirilmedi. Lütfen daha sonra tekrar deneyin." - "Eski PIN" - "Yeni PIN" "Lütfen bekleyin." "Yeni PIN çok kısa." "Yeni PIN çok uzun." diff --git a/java/com/android/voicemail/impl/res/values-uk/strings.xml b/java/com/android/voicemail/impl/res/values-uk/strings.xml index a0b3d8f13..b1d7c1036 100644 --- a/java/com/android/voicemail/impl/res/values-uk/strings.xml +++ b/java/com/android/voicemail/impl/res/values-uk/strings.xml @@ -26,8 +26,6 @@ "Змінити PIN-код" "Щоб змінити PIN-код, потрібно ввімкнути візуальну голосову пошту" "Візуальну голосову пошту ще не активовано, повторіть спробу пізніше" - "Старий PIN-код" - "Новий PIN-код" "Зачекайте." "Новий PIN-код закороткий." "Новий PIN-код задовгий." diff --git a/java/com/android/voicemail/impl/res/values-ur/strings.xml b/java/com/android/voicemail/impl/res/values-ur/strings.xml index 81f913fbb..7b1f8d329 100644 --- a/java/com/android/voicemail/impl/res/values-ur/strings.xml +++ b/java/com/android/voicemail/impl/res/values-ur/strings.xml @@ -26,8 +26,6 @@ "‏PIN تبدیل کریں" "‏PIN تبدیل کرنے کیلئے بصری صوتی میل اہل ہونی چاہئیے" "بصری صوتی میل ابھی فعال نہیں ہے، براہ کرم بعد میں دوبارہ کوشش کریں" - "‏پرانا PIN" - "‏نیا PIN" "براہ کرم انتظار کریں۔" "‏نیا PIN بہت مختصر ہے۔" "‏نیا PIN بہت طویل ہے۔" diff --git a/java/com/android/voicemail/impl/res/values-uz/strings.xml b/java/com/android/voicemail/impl/res/values-uz/strings.xml index 8771da7f1..92a7536ae 100644 --- a/java/com/android/voicemail/impl/res/values-uz/strings.xml +++ b/java/com/android/voicemail/impl/res/values-uz/strings.xml @@ -26,8 +26,6 @@ "PIN kodni o‘zgartirish" "PIN kodni o‘zgartirish uchun vizual ovozli pochtani yoqish lozim." "Vizual ovozli pochta yoqilmadi. Keyinroq qayta urinib ko‘ring." - "Eski PIN kod" - "Yangi PIN kod" "Iltimos, kuting…" "Yangi PIN kod juda qisqa." "Yangi PIN kod juda uzun." diff --git a/java/com/android/voicemail/impl/res/values-vi/strings.xml b/java/com/android/voicemail/impl/res/values-vi/strings.xml index cdca9bb60..972c74c28 100644 --- a/java/com/android/voicemail/impl/res/values-vi/strings.xml +++ b/java/com/android/voicemail/impl/res/values-vi/strings.xml @@ -26,8 +26,6 @@ "Thay đổi mã PIN" "Phải bật thư thoại kèm theo hình ảnh để thay đổi mã PIN" "Thư thoại kèm theo hình ảnh chưa được kích hoạt, hãy thử lại sau" - "Mã PIN cũ" - "Mã PIN mới" "Vui lòng đợi." "Mã PIN mới quá ngắn." "Mã PIN mới quá dài." diff --git a/java/com/android/voicemail/impl/res/values-zh-rCN/strings.xml b/java/com/android/voicemail/impl/res/values-zh-rCN/strings.xml index 8b0dde0bd..21edad6f5 100644 --- a/java/com/android/voicemail/impl/res/values-zh-rCN/strings.xml +++ b/java/com/android/voicemail/impl/res/values-zh-rCN/strings.xml @@ -26,8 +26,6 @@ "更改 PIN 码" "必须启用可视语音信箱才可更改 PIN 码" "可视语音信箱尚未激活,请稍后再试" - "旧 PIN 码" - "新 PIN 码" "请稍候。" "新的 PIN 码太短。" "新的 PIN 码太长。" diff --git a/java/com/android/voicemail/impl/res/values-zh-rHK/strings.xml b/java/com/android/voicemail/impl/res/values-zh-rHK/strings.xml index 0ee826952..d80cbba09 100644 --- a/java/com/android/voicemail/impl/res/values-zh-rHK/strings.xml +++ b/java/com/android/voicemail/impl/res/values-zh-rHK/strings.xml @@ -26,8 +26,6 @@ "變更 PIN" "必須啟用視像留言才能變更 PIN" "視像留言尚未啟用,請稍後再試" - "舊的 PIN" - "新的 PIN" "請稍候。" "新的 PIN 太短。" "新的 PIN 太長。" diff --git a/java/com/android/voicemail/impl/res/values-zh-rTW/strings.xml b/java/com/android/voicemail/impl/res/values-zh-rTW/strings.xml index d33c989e2..7d2380679 100644 --- a/java/com/android/voicemail/impl/res/values-zh-rTW/strings.xml +++ b/java/com/android/voicemail/impl/res/values-zh-rTW/strings.xml @@ -26,8 +26,6 @@ "變更 PIN" "必須啟用視覺化語音信箱才能變更 PIN" "視覺化語音信箱尚未啟用,請稍後再試" - "舊的語音信箱密碼" - "新的語音信箱密碼" "請稍候。" "新的語音信箱密碼太短。" "新的語音信箱密碼太長。" diff --git a/java/com/android/voicemail/impl/res/values-zu/strings.xml b/java/com/android/voicemail/impl/res/values-zu/strings.xml index b76209178..630f288e2 100644 --- a/java/com/android/voicemail/impl/res/values-zu/strings.xml +++ b/java/com/android/voicemail/impl/res/values-zu/strings.xml @@ -26,8 +26,6 @@ "Shintsha i-PIN" "Ivoyisimeyili ebonakalayo kumele inikwe amandla ukuze ishintshe i-PIN" "Ivoyisimeyili ebonakalayo ayisebenzi okwamanje, sicela uzame futhi emuva kwesikhathi" - "I-PIN endala" - "I-PIN entsha" "Sicela ulinde." "I-PIN entsha imfushane kakhulu." "I-PIN entsha yinde kakhulu." diff --git a/java/com/android/voicemail/impl/res/values/strings.xml b/java/com/android/voicemail/impl/res/values/strings.xml index 375a1e9ba..66c0e62b0 100644 --- a/java/com/android/voicemail/impl/res/values/strings.xml +++ b/java/com/android/voicemail/impl/res/values/strings.xml @@ -61,11 +61,6 @@ Visual voicemail must be enabled to change PIN Visual voicemail is not activated yet, please try again later - - Old PIN - - New PIN - Please wait. @@ -107,4 +102,8 @@ Voicemail PIN updated Unable to set PIN + + vvm_config_override_load_current + vvm_config_override_enabled + diff --git a/java/com/android/voicemail/impl/scheduling/TaskExecutor.java b/java/com/android/voicemail/impl/scheduling/TaskExecutor.java index e3b718e50..afa77c58c 100644 --- a/java/com/android/voicemail/impl/scheduling/TaskExecutor.java +++ b/java/com/android/voicemail/impl/scheduling/TaskExecutor.java @@ -129,7 +129,7 @@ final class TaskExecutor { private final MainThreadHandler mainThreadHandler; - private final Context context; + private final Context appContext; /** Main thread only, access through {@link #getTasks()} */ private final TaskQueue tasks = new TaskQueue(); @@ -179,7 +179,7 @@ final class TaskExecutor { VvmLog.i("JobFinishedPoller.run", "Job finished"); if (!getTasks().isEmpty()) { TaskSchedulerJobService.scheduleJob( - context, serializePendingTasks(), delayMillis, isNewJob); + appContext, serializePendingTasks(), delayMillis, isNewJob); tasks.clear(); } terminate(); @@ -259,7 +259,7 @@ final class TaskExecutor { } private TaskExecutor(Context context) { - this.context = context; + this.appContext = context.getApplicationContext(); HandlerThread thread = new HandlerThread("VvmTaskExecutor"); thread.start(); @@ -274,7 +274,7 @@ final class TaskExecutor { job = null; workerThreadHandler.getLooper().quit(); instance = null; - TaskReceiver.resendDeferredBroadcasts(context); + TaskReceiver.resendDeferredBroadcasts(appContext); } @MainThread @@ -391,7 +391,7 @@ final class TaskExecutor { public void onStartJob(Job job, List pendingTasks) { VvmLog.i(TAG, "onStartJob"); this.job = job; - tasks.fromBundles(context, pendingTasks); + tasks.fromBundles(appContext, pendingTasks); maybeRunNextTask(); } diff --git a/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java b/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java index 107234edc..baf58041f 100644 --- a/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java +++ b/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java @@ -30,6 +30,7 @@ import android.os.Parcelable; import android.preference.PreferenceManager; import android.support.annotation.MainThread; import com.android.dialer.constants.ScheduledJobIds; +import com.android.dialer.strictmode.DialerStrictMode; import com.android.voicemail.impl.Assert; import com.android.voicemail.impl.VvmLog; import java.util.ArrayList; @@ -58,7 +59,8 @@ public class TaskSchedulerJobService extends JobService implements TaskExecutor. public boolean onStartJob(JobParameters params) { int jobId = params.getTransientExtras().getInt(EXTRA_JOB_ID); int expectedJobId = - PreferenceManager.getDefaultSharedPreferences(this).getInt(EXPECTED_JOB_ID, 0); + DialerStrictMode.bypass( + () -> PreferenceManager.getDefaultSharedPreferences(this).getInt(EXPECTED_JOB_ID, 0)); if (jobId != expectedJobId) { VvmLog.e( TAG, "Job " + jobId + " is not the last scheduled job " + expectedJobId + ", ignoring"); diff --git a/java/com/android/voicemail/impl/scheduling/TaskSchedulerService.java b/java/com/android/voicemail/impl/scheduling/TaskSchedulerService.java deleted file mode 100644 index 5ad2447de..000000000 --- a/java/com/android/voicemail/impl/scheduling/TaskSchedulerService.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.voicemail.impl.scheduling; - -import android.annotation.TargetApi; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.support.annotation.MainThread; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; -import android.support.annotation.WorkerThread; -import com.android.voicemail.impl.Assert; -import com.android.voicemail.impl.NeededForTesting; -import com.android.voicemail.impl.VvmLog; -import com.android.voicemail.impl.scheduling.TaskQueue.NextTask; -import java.util.List; - -/** - * A service to queue and run {@link Task} with the {@link android.app.job.JobScheduler}. A task is - * queued using {@link Context#startService(Intent)}. The intent should contain enough information - * in {@link Intent#getExtras()} to construct the task (see {@link Tasks#createIntent(Context, - * Class)}). - * - *

All tasks are ran in the background with a wakelock being held by the {@link - * android.app.job.JobScheduler}, which is between {@link #onStartJob(Job, List)} and {@link - * #finishJob()}. The {@link TaskSchedulerJobService} also has a {@link TaskQueue}, but the data is - * stored in the {@link android.app.job.JobScheduler} instead of the process memory, so if the - * process is killed the queued tasks will be restored. If a new task is added, a new {@link - * TaskSchedulerJobService} will be scheduled to run the task. If the job is already scheduled, the - * new task will be pushed into the queue of the scheduled job. If the job is already running, the - * job will be queued in process memory. - * - *

Only one task will be ran at a time, and same task cannot exist in the queue at the same time. - * Refer to {@link TaskQueue} for queuing and execution order. - * - *

If there are still tasks in the queue but none are executable immediately, the service will - * enter a "sleep", pushing all remaining task into a new job and end the current job. - * - *

The service will be started when a intent is received, and stopped when there are no more - * tasks in the queue. - * - *

{@link android.app.job.JobScheduler} is not used directly due to: - * - *

    - *
  • The {@link android.telecom.PhoneAccountHandle} used to differentiate task can not be easily - * mapped into an integer for job id - *
  • A job cannot be mutated to store information such as retry count. - *
- */ -@SuppressWarnings("AndroidApiChecker") /* stream() */ -@TargetApi(VERSION_CODES.O) -public class TaskSchedulerService extends Service { - - interface Job { - void finish(); - } - - private static final String TAG = "VvmTaskScheduler"; - - private static final int READY_TOLERANCE_MILLISECONDS = 100; - - /** - * Threshold to determine whether to do a short or long sleep when a task is scheduled in the - * future. - * - *

A short sleep will continue the job and use {@link Handler#postDelayed(Runnable, long)} to - * wait for the next task. - * - *

A long sleep will finish the job and schedule a new one. The exact execution time is - * subjected to {@link android.app.job.JobScheduler} battery optimization, and is not exact. - */ - private static final int SHORT_SLEEP_THRESHOLD_MILLISECONDS = 10_000; - /** - * When there are no more tasks to be run the service should be stopped. But when all tasks has - * finished there might still be more tasks in the message queue waiting to be processed, - * especially the ones submitted in {@link Task#onCompleted()}. Wait for a while before stopping - * the service to make sure there are no pending messages. - */ - private static final int STOP_DELAY_MILLISECONDS = 5_000; - - // The thread to run tasks on - private volatile WorkerThreadHandler mWorkerThreadHandler; - - /** - * Used by tests to turn task handling into a single threaded process by calling {@link - * Handler#handleMessage(Message)} directly - */ - private MessageSender mMessageSender = new MessageSender(); - - private MainThreadHandler mMainThreadHandler; - - // Binder given to clients - private final IBinder mBinder = new LocalBinder(); - - /** Main thread only, access through {@link #getTasks()} */ - private final TaskQueue mTasks = new TaskQueue(); - - private boolean mWorkerThreadIsBusy = false; - - private Job mJob; - - private final Runnable mStopServiceWithDelay = - new Runnable() { - @MainThread - @Override - public void run() { - VvmLog.i(TAG, "Stopping service"); - finishJob(); - stopSelf(); - } - }; - - /** Should attempt to run the next task when a task has finished or been added. */ - private boolean mTaskAutoRunDisabledForTesting = false; - - @VisibleForTesting - final class WorkerThreadHandler extends Handler { - - public WorkerThreadHandler(Looper looper) { - super(looper); - } - - @Override - @WorkerThread - public void handleMessage(Message msg) { - Assert.isNotMainThread(); - Task task = (Task) msg.obj; - try { - VvmLog.i(TAG, "executing task " + task); - task.onExecuteInBackgroundThread(); - } catch (Throwable throwable) { - VvmLog.e(TAG, "Exception while executing task " + task + ":", throwable); - } - - Message schedulerMessage = mMainThreadHandler.obtainMessage(); - schedulerMessage.obj = task; - mMessageSender.send(schedulerMessage); - } - } - - @VisibleForTesting - final class MainThreadHandler extends Handler { - - public MainThreadHandler(Looper looper) { - super(looper); - } - - @Override - @MainThread - public void handleMessage(Message msg) { - Assert.isMainThread(); - Task task = (Task) msg.obj; - getTasks().remove(task); - task.onCompleted(); - mWorkerThreadIsBusy = false; - maybeRunNextTask(); - } - } - - @Override - @MainThread - public void onCreate() { - super.onCreate(); - HandlerThread thread = new HandlerThread("VvmTaskSchedulerService"); - thread.start(); - - mWorkerThreadHandler = new WorkerThreadHandler(thread.getLooper()); - mMainThreadHandler = new MainThreadHandler(Looper.getMainLooper()); - } - - @Override - public void onDestroy() { - mWorkerThreadHandler.getLooper().quit(); - } - - @Override - @MainThread - public int onStartCommand(@Nullable Intent intent, int flags, int startId) { - Assert.isMainThread(); - if (intent == null) { - VvmLog.w(TAG, "null intent received"); - return START_NOT_STICKY; - } - Task task = Tasks.createTask(this, intent.getExtras()); - Assert.isTrue(task != null); - addTask(task); - - mMainThreadHandler.removeCallbacks(mStopServiceWithDelay); - VvmLog.i(TAG, "task added"); - if (mJob == null) { - scheduleJob(0, true); - } else { - maybeRunNextTask(); - } - // STICKY means the service will be automatically restarted will the last intent if it is - // killed. - return START_NOT_STICKY; - } - - @MainThread - @VisibleForTesting - void addTask(Task task) { - Assert.isMainThread(); - getTasks().add(task); - } - - @MainThread - @VisibleForTesting - TaskQueue getTasks() { - Assert.isMainThread(); - return mTasks; - } - - @MainThread - private void maybeRunNextTask() { - Assert.isMainThread(); - if (mWorkerThreadIsBusy) { - return; - } - if (mTaskAutoRunDisabledForTesting) { - // If mTaskAutoRunDisabledForTesting is true, runNextTask() must be explicitly called - // to run the next task. - return; - } - - runNextTask(); - } - - @VisibleForTesting - @MainThread - void runNextTask() { - Assert.isMainThread(); - if (getTasks().isEmpty()) { - prepareStop(); - return; - } - NextTask nextTask = getTasks().getNextTask(READY_TOLERANCE_MILLISECONDS); - - if (nextTask.task != null) { - nextTask.task.onBeforeExecute(); - Message message = mWorkerThreadHandler.obtainMessage(); - message.obj = nextTask.task; - mWorkerThreadIsBusy = true; - mMessageSender.send(message); - return; - } - VvmLog.i(TAG, "minimal wait time:" + nextTask.minimalWaitTimeMillis); - if (!mTaskAutoRunDisabledForTesting && nextTask.minimalWaitTimeMillis != null) { - // No tasks are currently ready. Sleep until the next one should be. - // If a new task is added during the sleep the service will wake immediately. - sleep(nextTask.minimalWaitTimeMillis); - } - } - - @MainThread - private void sleep(long timeMillis) { - VvmLog.i(TAG, "sleep for " + timeMillis + " millis"); - if (timeMillis < SHORT_SLEEP_THRESHOLD_MILLISECONDS) { - mMainThreadHandler.postDelayed( - new Runnable() { - @Override - public void run() { - maybeRunNextTask(); - } - }, - timeMillis); - return; - } - finishJob(); - mMainThreadHandler.post(() -> scheduleJob(timeMillis, false)); - } - - private List serializePendingTasks() { - return getTasks().toBundles(); - } - - private void prepareStop() { - VvmLog.i( - TAG, - "no more tasks, stopping service if no task are added in " - + STOP_DELAY_MILLISECONDS - + " millis"); - mMainThreadHandler.postDelayed(mStopServiceWithDelay, STOP_DELAY_MILLISECONDS); - } - - @NeededForTesting - static class MessageSender { - - public void send(Message message) { - message.sendToTarget(); - } - } - - @NeededForTesting - void setTaskAutoRunDisabledForTest(boolean value) { - mTaskAutoRunDisabledForTesting = value; - } - - @NeededForTesting - void setMessageSenderForTest(MessageSender sender) { - mMessageSender = sender; - } - - /** - * The {@link TaskSchedulerJobService} has started and all queued task should be executed in the - * worker thread. - */ - @MainThread - public void onStartJob(Job job, List pendingTasks) { - VvmLog.i(TAG, "onStartJob"); - mJob = job; - mTasks.fromBundles(this, pendingTasks); - maybeRunNextTask(); - } - - /** - * The {@link TaskSchedulerJobService} is being terminated by the system (timeout or network - * lost). A new job will be queued to resume all pending tasks. The current unfinished job may be - * ran again. - */ - @MainThread - public void onStopJob() { - VvmLog.e(TAG, "onStopJob"); - if (isJobRunning()) { - finishJob(); - mMainThreadHandler.post(() -> scheduleJob(0, true)); - } - } - - /** - * Serializes all pending tasks and schedule a new {@link TaskSchedulerJobService}. - * - * @param delayMillis the delay before stating the job, see {@link - * android.app.job.JobInfo.Builder#setMinimumLatency(long)}. This must be 0 if {@code - * isNewJob} is true. - * @param isNewJob a new job will be requested to run immediately, bypassing all requirements. - */ - @MainThread - private void scheduleJob(long delayMillis, boolean isNewJob) { - Assert.isMainThread(); - TaskSchedulerJobService.scheduleJob(this, serializePendingTasks(), delayMillis, isNewJob); - mTasks.clear(); - } - - /** - * Signals {@link TaskSchedulerJobService} the current session of tasks has finished, and the wake - * lock can be released. Note: this only takes effect after the main thread has been returned. If - * a new job need to be scheduled, it should be posted on the main thread handler instead of - * calling directly. - */ - @MainThread - private void finishJob() { - Assert.isMainThread(); - VvmLog.i(TAG, "finishing Job"); - mJob.finish(); - mJob = null; - } - - @Override - @Nullable - public IBinder onBind(Intent intent) { - return mBinder; - } - - @NeededForTesting - class LocalBinder extends Binder { - - @NeededForTesting - public TaskSchedulerService getService() { - return TaskSchedulerService.this; - } - } - - private boolean isJobRunning() { - return mJob != null; - } -} diff --git a/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java b/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java index ac5f3cac9..4860649b3 100644 --- a/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java +++ b/java/com/android/voicemail/impl/settings/VoicemailSettingsFragment.java @@ -22,6 +22,7 @@ import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.preference.SwitchPreference; +import android.provider.Settings; import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; @@ -29,7 +30,6 @@ import com.android.dialer.common.Assert; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; import com.android.dialer.notification.NotificationChannelManager; -import com.android.dialer.notification.NotificationChannelManager.Channel; import com.android.voicemail.VoicemailClient; import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper; @@ -43,8 +43,7 @@ import com.android.voicemail.impl.sync.VvmAccountManager; */ @TargetApi(VERSION_CODES.O) public class VoicemailSettingsFragment extends PreferenceFragment - implements Preference.OnPreferenceChangeListener, - VvmAccountManager.Listener { + implements Preference.OnPreferenceChangeListener, VvmAccountManager.Listener { private static final String TAG = "VmSettingsActivity"; @@ -83,9 +82,8 @@ public class VoicemailSettingsFragment extends PreferenceFragment voicemailNotificationPreference = findPreference(getString(R.string.voicemail_notifications_key)); - voicemailNotificationPreference.setIntent( - NotificationChannelManager.getInstance() - .getSettingsIntentForChannel(getContext(), Channel.VOICEMAIL, phoneAccountHandle)); + voicemailNotificationPreference.setIntent(getNotificationSettingsIntent()); + voicemailNotificationPreference.setOnPreferenceClickListener( new OnPreferenceClickListener() { @Override @@ -233,4 +231,12 @@ public class VoicemailSettingsFragment extends PreferenceFragment updateChangePin(); } } + + private Intent getNotificationSettingsIntent() { + String channelId = + NotificationChannelManager.getVoicemailChannelId(getContext(), phoneAccountHandle); + return new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_CHANNEL_ID, channelId) + .putExtra(Settings.EXTRA_APP_PACKAGE, getContext().getPackageName()); + } } diff --git a/java/com/android/voicemail/impl/sms/LegacyModeSmsHandler.java b/java/com/android/voicemail/impl/sms/LegacyModeSmsHandler.java index 5decf6376..e902825c0 100644 --- a/java/com/android/voicemail/impl/sms/LegacyModeSmsHandler.java +++ b/java/com/android/voicemail/impl/sms/LegacyModeSmsHandler.java @@ -79,6 +79,7 @@ public class LegacyModeSmsHandler { VvmLog.i(TAG, "sending voicemail notification"); Intent intent = new Intent(VoicemailClient.ACTION_SHOW_LEGACY_VOICEMAIL); intent.setPackage(context.getPackageName()); + intent.putExtra(VoicemailClient.EXTRA_IS_LEGACY_MODE, true); intent.putExtra(TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); // Setting voicemail message count to non-zero will show the telephony voicemail // notification, and zero will clear it. diff --git a/java/com/android/voicemail/impl/sms/OmtpMessageReceiver.java b/java/com/android/voicemail/impl/sms/OmtpMessageReceiver.java index ef0bf10e9..43835276b 100644 --- a/java/com/android/voicemail/impl/sms/OmtpMessageReceiver.java +++ b/java/com/android/voicemail/impl/sms/OmtpMessageReceiver.java @@ -35,7 +35,6 @@ import com.android.voicemail.impl.Voicemail.Builder; import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.protocol.VisualVoicemailProtocol; import com.android.voicemail.impl.settings.VisualVoicemailSettingsUtil; -import com.android.voicemail.impl.sync.OmtpVvmSyncService; import com.android.voicemail.impl.sync.SyncOneTask; import com.android.voicemail.impl.sync.SyncTask; import com.android.voicemail.impl.sync.VoicemailsQueryHelper; @@ -71,6 +70,10 @@ public class OmtpMessageReceiver extends BroadcastReceiver { } OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(mContext, phone); + if (!helper.isValid()) { + VvmLog.e(TAG, "vvm config no longer valid"); + return; + } if (!VisualVoicemailSettingsUtil.isEnabled(mContext, phone)) { if (helper.isLegacyModeEnabled()) { LegacyModeSmsHandler.handle(context, sms); @@ -148,7 +151,7 @@ public class OmtpMessageReceiver extends BroadcastReceiver { } break; case OmtpConstants.MAILBOX_UPDATE: - SyncTask.start(mContext, phone, OmtpVvmSyncService.SYNC_DOWNLOAD_ONLY); + SyncTask.start(mContext, phone); break; case OmtpConstants.GREETINGS_UPDATE: // Not implemented in V1 diff --git a/java/com/android/voicemail/impl/sms/OmtpMessageSender.java b/java/com/android/voicemail/impl/sms/OmtpMessageSender.java index e9d145cde..19661e99d 100644 --- a/java/com/android/voicemail/impl/sms/OmtpMessageSender.java +++ b/java/com/android/voicemail/impl/sms/OmtpMessageSender.java @@ -22,6 +22,7 @@ import android.telecom.PhoneAccountHandle; import android.telephony.SmsManager; import com.android.voicemail.impl.OmtpConstants; import com.android.voicemail.impl.TelephonyMangerCompat; +import com.android.voicemail.impl.VvmLog; /** * Send client originated OMTP messages to the OMTP server. @@ -75,6 +76,11 @@ public abstract class OmtpMessageSender { public void requestVvmStatus(@Nullable PendingIntent sentIntent) {} protected void sendSms(String text, PendingIntent sentIntent) { + + VvmLog.v( + TAG, + String.format("Sending sms '%s' to %s:%d", text, mDestinationNumber, mApplicationPort)); + TelephonyMangerCompat.sendVisualVoicemailSms( mContext, mPhoneAccountHandle, mDestinationNumber, mApplicationPort, text, sentIntent); } diff --git a/java/com/android/voicemail/impl/sync/OmtpVvmSyncReceiver.java b/java/com/android/voicemail/impl/sync/OmtpVvmSyncReceiver.java index b2ec49e9f..1b59eccfc 100644 --- a/java/com/android/voicemail/impl/sync/OmtpVvmSyncReceiver.java +++ b/java/com/android/voicemail/impl/sync/OmtpVvmSyncReceiver.java @@ -52,7 +52,7 @@ public class OmtpVvmSyncReceiver extends BroadcastReceiver { VvmLog.i(TAG, "Unactivated account " + phoneAccount + " found, activating"); ActivationTask.start(context, phoneAccount, null); } else { - SyncTask.start(context, phoneAccount, OmtpVvmSyncService.SYNC_FULL_SYNC); + SyncTask.start(context, phoneAccount); } } } diff --git a/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java b/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java index 793388362..5b5d6b054 100644 --- a/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java +++ b/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java @@ -43,6 +43,7 @@ import com.android.voicemail.impl.sync.VvmNetworkRequest.NetworkWrapper; import com.android.voicemail.impl.sync.VvmNetworkRequest.RequestFailedException; import com.android.voicemail.impl.utils.LoggerUtils; import com.android.voicemail.impl.utils.VoicemailDatabaseUtil; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -50,22 +51,13 @@ import java.util.Map; @TargetApi(VERSION_CODES.O) public class OmtpVvmSyncService { - private static final String TAG = OmtpVvmSyncService.class.getSimpleName(); + private static final String TAG = "OmtpVvmSyncService"; - /** Signifies a sync with both uploading to the server and downloading from the server. */ - public static final String SYNC_FULL_SYNC = "full_sync"; - /** Only upload to the server. */ - public static final String SYNC_UPLOAD_ONLY = "upload_only"; - /** Only download from the server. */ - public static final String SYNC_DOWNLOAD_ONLY = "download_only"; - /** Only download single voicemail transcription. */ - public static final String SYNC_DOWNLOAD_ONE_TRANSCRIPTION = "download_one_transcription"; /** Threshold for whether we should archive and delete voicemails from the remote VM server. */ private static final float AUTO_DELETE_ARCHIVE_VM_THRESHOLD = 0.75f; private final Context mContext; - - private VoicemailsQueryHelper mQueryHelper; + private final VoicemailsQueryHelper mQueryHelper; public OmtpVvmSyncService(Context context) { mContext = context; @@ -74,23 +66,21 @@ public class OmtpVvmSyncService { public void sync( BaseTask task, - String action, PhoneAccountHandle phoneAccount, Voicemail voicemail, VoicemailStatus.Editor status) { Assert.isTrue(phoneAccount != null); - VvmLog.v(TAG, "Sync requested: " + action + " - for account: " + phoneAccount); - setupAndSendRequest(task, phoneAccount, voicemail, action, status); + VvmLog.v(TAG, "Sync requested for account: " + phoneAccount); + setupAndSendRequest(task, phoneAccount, voicemail, status); } private void setupAndSendRequest( BaseTask task, PhoneAccountHandle phoneAccount, Voicemail voicemail, - String action, VoicemailStatus.Editor status) { if (!VisualVoicemailSettingsUtil.isEnabled(mContext, phoneAccount)) { - VvmLog.v(TAG, "Sync requested for disabled account"); + VvmLog.e(TAG, "Sync requested for disabled account"); return; } if (!VvmAccountManager.isAccountActivated(mContext, phoneAccount)) { @@ -102,7 +92,7 @@ public class OmtpVvmSyncService { LoggerUtils.logImpressionOnMainThread(mContext, DialerImpression.Type.VVM_SYNC_STARTED); // DATA_IMAP_OPERATION_STARTED posting should not be deferred. This event clears all data // channel errors, which should happen when the task starts, not when it ends. It is the - // "Sync in progress..." status. + // "Sync in progress..." status, which is currently displayed to the user as no error. config.handleEvent( VoicemailStatus.edit(mContext, phoneAccount), OmtpEvents.DATA_IMAP_OPERATION_STARTED); try (NetworkWrapper network = VvmNetworkRequest.getNetwork(config, phoneAccount, status)) { @@ -111,7 +101,7 @@ public class OmtpVvmSyncService { task.fail(); return; } - doSync(task, network.get(), phoneAccount, voicemail, action, status); + doSync(task, network.get(), phoneAccount, voicemail, status); } catch (RequestFailedException e) { config.handleEvent(status, OmtpEvents.DATA_NO_CONNECTION_CELLULAR_REQUIRED); task.fail(); @@ -123,14 +113,13 @@ public class OmtpVvmSyncService { Network network, PhoneAccountHandle phoneAccount, Voicemail voicemail, - String action, VoicemailStatus.Editor status) { try (ImapHelper imapHelper = new ImapHelper(mContext, phoneAccount, network, status)) { boolean success; if (voicemail == null) { - success = syncAll(action, imapHelper, phoneAccount); + success = syncAll(imapHelper, phoneAccount); } else { - success = syncOne(imapHelper, voicemail, phoneAccount); + success = downloadOneVoicemail(imapHelper, voicemail, phoneAccount); } if (success) { // TODO: b/30569269 failure should interrupt all subsequent task via exceptions @@ -219,79 +208,33 @@ public class OmtpVvmSyncService { } } - private boolean syncAll(String action, ImapHelper imapHelper, PhoneAccountHandle account) { - boolean uploadSuccess = true; - boolean downloadSuccess = true; - - if (SYNC_FULL_SYNC.equals(action) || SYNC_UPLOAD_ONLY.equals(action)) { - uploadSuccess = upload(account, imapHelper); - } - if (SYNC_FULL_SYNC.equals(action) || SYNC_DOWNLOAD_ONLY.equals(action)) { - downloadSuccess = download(imapHelper, account); - } + private boolean syncAll(ImapHelper imapHelper, PhoneAccountHandle account) { - VvmLog.v( - TAG, - "upload succeeded: [" - + String.valueOf(uploadSuccess) - + "] download succeeded: [" - + String.valueOf(downloadSuccess) - + "]"); - - return uploadSuccess && downloadSuccess; - } + List serverVoicemails = imapHelper.fetchAllVoicemails(); + List localVoicemails = mQueryHelper.getAllVoicemails(account); + List deletedVoicemails = mQueryHelper.getDeletedVoicemails(account); + boolean succeeded = true; - private boolean syncOne(ImapHelper imapHelper, Voicemail voicemail, PhoneAccountHandle account) { - if (shouldPerformPrefetch(account, imapHelper)) { - VoicemailFetchedCallback callback = - new VoicemailFetchedCallback(mContext, voicemail.getUri(), account); - imapHelper.fetchVoicemailPayload(callback, voicemail.getSourceData()); + if (localVoicemails == null || serverVoicemails == null) { + // Null value means the query failed. + VvmLog.e(TAG, "syncAll: query failed"); + return false; } - return imapHelper.fetchTranscription( - new TranscriptionFetchedCallback(mContext, voicemail), voicemail.getSourceData()); - } - - private boolean upload(PhoneAccountHandle phoneAccountHandle, ImapHelper imapHelper) { - List readVoicemails = mQueryHelper.getReadVoicemails(phoneAccountHandle); - List deletedVoicemails = mQueryHelper.getDeletedVoicemails(phoneAccountHandle); - - boolean success = true; - if (deletedVoicemails.size() > 0) { if (imapHelper.markMessagesAsDeleted(deletedVoicemails)) { - // We want to delete selectively instead of all the voicemails for this provider - // in case the state changed since the IMAP query was completed. + // Delete only the voicemails that was deleted on the server, in case more are deleted + // since the IMAP query was completed. mQueryHelper.deleteFromDatabase(deletedVoicemails); } else { - success = false; + succeeded = false; } } - if (readVoicemails.size() > 0) { - VvmLog.i(TAG, "Marking voicemails as read"); - if (imapHelper.markMessagesAsRead(readVoicemails)) { - VvmLog.i(TAG, "Marking voicemails as clean"); - mQueryHelper.markCleanInDatabase(readVoicemails); - } else { - success = false; - } - } - - return success; - } - - private boolean download(ImapHelper imapHelper, PhoneAccountHandle account) { - List serverVoicemails = imapHelper.fetchAllVoicemails(); - List localVoicemails = mQueryHelper.getAllVoicemails(account); - - if (localVoicemails == null || serverVoicemails == null) { - // Null value means the query failed. - return false; - } - Map remoteMap = buildMap(serverVoicemails); + List localReadVoicemails = new ArrayList<>(); + // Go through all the local voicemails and check if they are on the server. // They may be read or deleted on the server but not locally. Perform the // appropriate local operation if the status differs from the server. Remove @@ -310,6 +253,8 @@ public class OmtpVvmSyncService { } else { if (remoteVoicemail.isRead() && !localVoicemail.isRead()) { mQueryHelper.markReadInDatabase(localVoicemail); + } else if (localVoicemail.isRead() && !remoteVoicemail.isRead()) { + localReadVoicemails.add(localVoicemail); } if (!TextUtils.isEmpty(remoteVoicemail.getTranscription()) @@ -321,6 +266,16 @@ public class OmtpVvmSyncService { } } + if (localReadVoicemails.size() > 0) { + VvmLog.i(TAG, "Marking voicemails as read"); + if (imapHelper.markMessagesAsRead(localReadVoicemails)) { + VvmLog.i(TAG, "Marking voicemails as clean"); + mQueryHelper.markCleanInDatabase(localReadVoicemails); + } else { + return false; + } + } + // The leftover messages are messages that exist on the server but not locally. boolean prefetchEnabled = shouldPerformPrefetch(account, imapHelper); for (Voicemail remoteVoicemail : remoteMap.values()) { @@ -336,7 +291,19 @@ public class OmtpVvmSyncService { } } - return true; + return succeeded; + } + + private boolean downloadOneVoicemail( + ImapHelper imapHelper, Voicemail voicemail, PhoneAccountHandle account) { + if (shouldPerformPrefetch(account, imapHelper)) { + VoicemailFetchedCallback callback = + new VoicemailFetchedCallback(mContext, voicemail.getUri(), account); + imapHelper.fetchVoicemailPayload(callback, voicemail.getSourceData()); + } + + return imapHelper.fetchTranscription( + new TranscriptionFetchedCallback(mContext, voicemail), voicemail.getSourceData()); } private boolean shouldPerformPrefetch(PhoneAccountHandle account, ImapHelper imapHelper) { diff --git a/java/com/android/voicemail/impl/sync/SyncOneTask.java b/java/com/android/voicemail/impl/sync/SyncOneTask.java index cd2782abb..70c6bd890 100644 --- a/java/com/android/voicemail/impl/sync/SyncOneTask.java +++ b/java/com/android/voicemail/impl/sync/SyncOneTask.java @@ -39,17 +39,14 @@ public class SyncOneTask extends BaseTask { private static final int RETRY_INTERVAL_MILLIS = 5_000; private static final String EXTRA_PHONE_ACCOUNT_HANDLE = "extra_phone_account_handle"; - private static final String EXTRA_SYNC_TYPE = "extra_sync_type"; private static final String EXTRA_VOICEMAIL = "extra_voicemail"; private PhoneAccountHandle mPhone; - private String mSyncType; private Voicemail mVoicemail; public static void start(Context context, PhoneAccountHandle phone, Voicemail voicemail) { Intent intent = BaseTask.createIntent(context, SyncOneTask.class, phone); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phone); - intent.putExtra(EXTRA_SYNC_TYPE, OmtpVvmSyncService.SYNC_DOWNLOAD_ONE_TRANSCRIPTION); intent.putExtra(EXTRA_VOICEMAIL, voicemail); context.sendBroadcast(intent); } @@ -63,14 +60,13 @@ public class SyncOneTask extends BaseTask { public void onCreate(Context context, Bundle extras) { super.onCreate(context, extras); mPhone = extras.getParcelable(EXTRA_PHONE_ACCOUNT_HANDLE); - mSyncType = extras.getString(EXTRA_SYNC_TYPE); mVoicemail = extras.getParcelable(EXTRA_VOICEMAIL); } @Override public void onExecuteInBackgroundThread() { OmtpVvmSyncService service = new OmtpVvmSyncService(getContext()); - service.sync(this, mSyncType, mPhone, mVoicemail, VoicemailStatus.edit(getContext(), mPhone)); + service.sync(this, mPhone, mVoicemail, VoicemailStatus.edit(getContext(), mPhone)); } @Override @@ -78,7 +74,6 @@ public class SyncOneTask extends BaseTask { LoggerUtils.logImpressionOnMainThread(getContext(), DialerImpression.Type.VVM_AUTO_RETRY_SYNC); Intent intent = super.createRestartIntent(); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, mPhone); - intent.putExtra(EXTRA_SYNC_TYPE, mSyncType); intent.putExtra(EXTRA_VOICEMAIL, mVoicemail); return intent; } diff --git a/java/com/android/voicemail/impl/sync/SyncTask.java b/java/com/android/voicemail/impl/sync/SyncTask.java index 0b3e090bf..68ce0122e 100644 --- a/java/com/android/voicemail/impl/sync/SyncTask.java +++ b/java/com/android/voicemail/impl/sync/SyncTask.java @@ -37,17 +37,14 @@ public class SyncTask extends BaseTask { private static final int MINIMAL_INTERVAL_MILLIS = 60_000; private static final String EXTRA_PHONE_ACCOUNT_HANDLE = "extra_phone_account_handle"; - private static final String EXTRA_SYNC_TYPE = "extra_sync_type"; private final RetryPolicy mRetryPolicy; private PhoneAccountHandle mPhone; - private String mSyncType; - public static void start(Context context, PhoneAccountHandle phone, String syncType) { + public static void start(Context context, PhoneAccountHandle phone) { Intent intent = BaseTask.createIntent(context, SyncTask.class, phone); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phone); - intent.putExtra(EXTRA_SYNC_TYPE, syncType); context.sendBroadcast(intent); } @@ -62,13 +59,12 @@ public class SyncTask extends BaseTask { public void onCreate(Context context, Bundle extras) { super.onCreate(context, extras); mPhone = extras.getParcelable(EXTRA_PHONE_ACCOUNT_HANDLE); - mSyncType = extras.getString(EXTRA_SYNC_TYPE); } @Override public void onExecuteInBackgroundThread() { OmtpVvmSyncService service = new OmtpVvmSyncService(getContext()); - service.sync(this, mSyncType, mPhone, null, mRetryPolicy.getVoicemailStatusEditor()); + service.sync(this, mPhone, null, mRetryPolicy.getVoicemailStatusEditor()); } @Override @@ -76,7 +72,6 @@ public class SyncTask extends BaseTask { LoggerUtils.logImpressionOnMainThread(getContext(), DialerImpression.Type.VVM_AUTO_RETRY_SYNC); Intent intent = super.createRestartIntent(); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, mPhone); - intent.putExtra(EXTRA_SYNC_TYPE, mSyncType); return intent; } } diff --git a/java/com/android/voicemail/impl/sync/UploadTask.java b/java/com/android/voicemail/impl/sync/UploadTask.java index f2b2036b5..d8f06db47 100644 --- a/java/com/android/voicemail/impl/sync/UploadTask.java +++ b/java/com/android/voicemail/impl/sync/UploadTask.java @@ -63,10 +63,6 @@ public class UploadTask extends BaseTask { return; } service.sync( - this, - OmtpVvmSyncService.SYNC_UPLOAD_ONLY, - phoneAccountHandle, - null, - VoicemailStatus.edit(getContext(), phoneAccountHandle)); + this, phoneAccountHandle, null, VoicemailStatus.edit(getContext(), phoneAccountHandle)); } } diff --git a/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java b/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java index 9b295dbb7..316e1ca61 100644 --- a/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java +++ b/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java @@ -49,8 +49,6 @@ public class VoicemailsQueryHelper { public static final int DELETED = 3; public static final int TRANSCRIPTION = 4; - static final String READ_SELECTION = - Voicemails.DIRTY + "=1 AND " + Voicemails.DELETED + "!=1 AND " + Voicemails.IS_READ + "=1"; static final String DELETED_SELECTION = Voicemails.DELETED + "=1"; static final String ARCHIVED_SELECTION = Voicemails.ARCHIVED + "=0"; @@ -64,15 +62,6 @@ public class VoicemailsQueryHelper { mSourceUri = VoicemailContract.Voicemails.buildSourceUri(mContext.getPackageName()); } - /** - * Get all the local read voicemails that have not been synced to the server. - * - * @return A list of read voicemails. - */ - public List getReadVoicemails(@NonNull PhoneAccountHandle phoneAccountHandle) { - return getLocalVoicemails(phoneAccountHandle, READ_SELECTION); - } - /** * Get all the locally deleted voicemails that have not been synced to the server. * diff --git a/java/com/android/voicemail/impl/sync/VvmAccountManager.java b/java/com/android/voicemail/impl/sync/VvmAccountManager.java index cc4e31fe3..2625fba0c 100644 --- a/java/com/android/voicemail/impl/sync/VvmAccountManager.java +++ b/java/com/android/voicemail/impl/sync/VvmAccountManager.java @@ -15,14 +15,20 @@ */ package com.android.voicemail.impl.sync; +import android.annotation.TargetApi; import android.content.Context; +import android.os.Build.VERSION_CODES; +import android.os.UserManager; import android.support.annotation.MainThread; import android.support.annotation.NonNull; +import android.support.annotation.VisibleForTesting; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.util.ArraySet; import com.android.dialer.common.Assert; +import com.android.dialer.common.PerAccountSharedPreferences; import com.android.dialer.common.concurrent.ThreadUtil; +import com.android.dialer.util.DialerUtils; import com.android.voicemail.impl.OmtpConstants; import com.android.voicemail.impl.VisualVoicemailPreferences; import com.android.voicemail.impl.VoicemailStatus; @@ -40,6 +46,7 @@ import java.util.Set; * #removeAccount(Context, PhoneAccountHandle)} should be called to clear the connection information * and allow reactivation. */ +@TargetApi(VERSION_CODES.O) public class VvmAccountManager { public static final String TAG = "VvmAccountManager"; @@ -49,7 +56,7 @@ public class VvmAccountManager { void onActivationStateChanged(PhoneAccountHandle phoneAccountHandle, boolean isActivated); } - private static final String IS_ACCOUNT_ACTIVATED = "is_account_activated"; + @VisibleForTesting static final String IS_ACCOUNT_ACTIVATED = "is_account_activated"; private static Set listeners = new ArraySet<>(); @@ -57,7 +64,8 @@ public class VvmAccountManager { Context context, PhoneAccountHandle phoneAccountHandle, StatusMessage statusMessage) { VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(context, phoneAccountHandle); - statusMessage.putStatus(preferences.edit()).putBoolean(IS_ACCOUNT_ACTIVATED, true).apply(); + statusMessage.putStatus(preferences.edit()).apply(); + setAccountActivated(context, phoneAccountHandle, true); ThreadUtil.postOnUiThread( () -> { @@ -69,10 +77,10 @@ public class VvmAccountManager { public static void removeAccount(Context context, PhoneAccountHandle phoneAccount) { VoicemailStatus.disable(context, phoneAccount); + setAccountActivated(context, phoneAccount, false); VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(context, phoneAccount); preferences .edit() - .putBoolean(IS_ACCOUNT_ACTIVATED, false) .putString(OmtpConstants.IMAP_USER_NAME, null) .putString(OmtpConstants.IMAP_PASSWORD, null) .apply(); @@ -86,7 +94,9 @@ public class VvmAccountManager { public static boolean isAccountActivated(Context context, PhoneAccountHandle phoneAccount) { Assert.isNotNull(phoneAccount); - VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(context, phoneAccount); + PerAccountSharedPreferences preferences = + getPreferenceForActivationState(context, phoneAccount); + migrateActivationState(context, preferences, phoneAccount); return preferences.getBoolean(IS_ACCOUNT_ACTIVATED, false); } @@ -113,4 +123,47 @@ public class VvmAccountManager { Assert.isMainThread(); listeners.remove(listener); } + + /** + * The activation state is moved from credential protected storage to device protected storage + * after v10, so it can be checked under FBE. The state should be migrated to avoid reactivation. + */ + private static void migrateActivationState( + Context context, + PerAccountSharedPreferences deviceProtectedPreference, + PhoneAccountHandle phoneAccountHandle) { + if (!context.getSystemService(UserManager.class).isUserUnlocked()) { + return; + } + if (deviceProtectedPreference.contains(IS_ACCOUNT_ACTIVATED)) { + return; + } + + PerAccountSharedPreferences credentialProtectedPreference = + new VisualVoicemailPreferences(context, phoneAccountHandle); + + deviceProtectedPreference + .edit() + .putBoolean( + IS_ACCOUNT_ACTIVATED, + credentialProtectedPreference.getBoolean(IS_ACCOUNT_ACTIVATED, false)) + .apply(); + } + + private static void setAccountActivated( + Context context, PhoneAccountHandle phoneAccountHandle, boolean activated) { + Assert.isNotNull(phoneAccountHandle); + getPreferenceForActivationState(context, phoneAccountHandle) + .edit() + .putBoolean(IS_ACCOUNT_ACTIVATED, activated) + .apply(); + } + + private static PerAccountSharedPreferences getPreferenceForActivationState( + Context context, PhoneAccountHandle phoneAccountHandle) { + return new PerAccountSharedPreferences( + context, + phoneAccountHandle, + DialerUtils.getDefaultSharedPreferenceForDeviceProtectedStorageContext(context)); + } } diff --git a/java/com/android/voicemail/impl/sync/VvmNetworkRequestCallback.java b/java/com/android/voicemail/impl/sync/VvmNetworkRequestCallback.java index 067eff803..068b19b70 100644 --- a/java/com/android/voicemail/impl/sync/VvmNetworkRequestCallback.java +++ b/java/com/android/voicemail/impl/sync/VvmNetworkRequestCallback.java @@ -128,7 +128,7 @@ public abstract class VvmNetworkRequestCallback extends ConnectivityManager.Netw @CallSuper public void onUnavailable() { - // TODO: b/32637799 this is hidden, do we really need this? + // TODO(twyen): b/32637799 this is hidden, do we really need this? mResultReceived = true; onFailed(NETWORK_REQUEST_FAILED_TIMEOUT); } diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java b/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java new file mode 100644 index 000000000..f3c6e64f4 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe; + +import android.app.job.JobInfo; +import android.app.job.JobScheduler; +import android.app.job.JobWorkItem; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.support.annotation.WorkerThread; +import android.support.v4.app.JobIntentService; +import android.support.v4.os.BuildCompat; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.ThreadUtil; +import com.android.dialer.constants.ScheduledJobIds; +import java.util.List; + +/** + * JobScheduler service for transcribing old voicemails. This service does a database scan for + * un-transcribed voicemails and schedules transcription tasks for them, once we have an un-metered + * network connection. + */ +public class TranscriptionBackfillService extends JobIntentService { + + /** Schedule a task to scan the database for untranscribed voicemails */ + public static boolean scheduleTask(Context context) { + if (BuildCompat.isAtLeastO()) { + LogUtil.enterBlock("TranscriptionBackfillService.transcribeOldVoicemails"); + ComponentName componentName = new ComponentName(context, TranscriptionBackfillService.class); + JobInfo.Builder builder = + new JobInfo.Builder(ScheduledJobIds.VVM_TRANSCRIPTION_BACKFILL_JOB, componentName) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); + JobScheduler scheduler = context.getSystemService(JobScheduler.class); + return scheduler.enqueue(builder.build(), makeWorkItem()) == JobScheduler.RESULT_SUCCESS; + } else { + LogUtil.i("TranscriptionBackfillService.transcribeOldVoicemails", "not supported"); + return false; + } + } + + private static JobWorkItem makeWorkItem() { + Intent intent = new Intent(); + return new JobWorkItem(intent); + } + + @Override + @WorkerThread + protected void onHandleWork(Intent intent) { + LogUtil.enterBlock("TranscriptionBackfillService.onHandleWork"); + + TranscriptionDbHelper dbHelper = new TranscriptionDbHelper(this); + List untranscribed = dbHelper.getUntranscribedVoicemails(); + LogUtil.i( + "TranscriptionBackfillService.onHandleWork", + "found " + untranscribed.size() + " untranscribed voicemails"); + // TODO(mdooley): Consider doing the actual transcriptions here instead of scheduling jobs. + for (Uri uri : untranscribed) { + ThreadUtil.postOnUiThread( + () -> { + TranscriptionService.scheduleNewVoicemailTranscriptionJob(this, uri, false); + }); + } + } + + @Override + public void onDestroy() { + LogUtil.enterBlock("TranscriptionBackfillService.onDestroy"); + super.onDestroy(); + } +} diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionConfigProvider.java b/java/com/android/voicemail/impl/transcribe/TranscriptionConfigProvider.java new file mode 100644 index 000000000..83f04dab8 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionConfigProvider.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe; + +import android.content.Context; +import com.android.dialer.configprovider.ConfigProviderBindings; + +/** Provides configuration values needed to connect to the transcription server. */ +public class TranscriptionConfigProvider { + private final Context context; + + public TranscriptionConfigProvider(Context context) { + this.context = context; + } + + public boolean isVoicemailTranscriptionEnabled() { + return ConfigProviderBindings.get(context).getBoolean("voicemail_transcription_enabled", false); + } + + public String getServerAddress() { + // Private voicemail transcription service + return ConfigProviderBindings.get(context) + .getString( + "voicemail_transcription_server_address", "voicemailtranscription-pa.googleapis.com"); + } + + public String getApiKey() { + // Android API key restricted to com.google.android.dialer + return ConfigProviderBindings.get(context) + .getString( + "voicemail_transcription_client_api_key", "AIzaSyAXdDnif6B7sBYxU8hzw9qAp3pRPVHs060"); + } + + public String getAuthToken() { + return null; + } + + public boolean shouldUsePlaintext() { + return ConfigProviderBindings.get(context) + .getBoolean("voicemail_transcription_server_use_plaintext", false); + } + + public boolean shouldUseSyncApi() { + return ConfigProviderBindings.get(context) + .getBoolean("voicemail_transcription_server_use_sync_api", false); + } + + public long getMaxTranscriptionRetries() { + return ConfigProviderBindings.get(context) + .getLong("voicemail_transcription_max_transcription_retries", 2L); + } + + public long getMaxGetTranscriptPolls() { + return ConfigProviderBindings.get(context) + .getLong("voicemail_transcription_max_get_transcript_polls", 20L); + } + + public long getGetTranscriptPollIntervalMillis() { + return ConfigProviderBindings.get(context) + .getLong("voicemail_transcription_get_transcript_poll_interval_millis", 1000L); + } + + @Override + public String toString() { + return String.format( + "{ address: %s, api key: %s, auth token: %s, plaintext: %b, sync: %b, retries: %d, polls:" + + " %d, poll ms: %d }", + getServerAddress(), + getApiKey(), + getAuthToken(), + shouldUsePlaintext(), + shouldUseSyncApi(), + getMaxTranscriptionRetries(), + getMaxGetTranscriptPolls(), + getGetTranscriptPollIntervalMillis()); + } +} diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java b/java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java new file mode 100644 index 000000000..9d3c2e4a7 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionDbHelper.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe; + +import android.annotation.TargetApi; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build.VERSION_CODES; +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; +import java.util.ArrayList; +import java.util.List; + +/** Helper class for reading and writing transcription data in the database */ +@TargetApi(VERSION_CODES.O) +public class TranscriptionDbHelper { + @VisibleForTesting + static final String[] PROJECTION = + new String[] { + Voicemails._ID, // 0 + Voicemails.TRANSCRIPTION, // 1 + VoicemailCompat.TRANSCRIPTION_STATE // 2 + }; + + static final int ID = 0; + static final int TRANSCRIPTION = 1; + static final int TRANSCRIPTION_STATE = 2; + + private final ContentResolver contentResolver; + private final Uri uri; + + TranscriptionDbHelper(Context context, Uri uri) { + Assert.isNotNull(uri); + this.contentResolver = context.getContentResolver(); + this.uri = uri; + } + + TranscriptionDbHelper(Context context) { + this(context, Voicemails.buildSourceUri(context.getPackageName())); + } + + @WorkerThread + @TargetApi(VERSION_CODES.M) // used for try with resources + Pair getTranscriptionAndState() { + Assert.checkState(BuildCompat.isAtLeastO()); + Assert.isWorkerThread(); + try (Cursor cursor = contentResolver.query(uri, PROJECTION, null, null, null)) { + if (cursor == null) { + LogUtil.e("TranscriptionDbHelper.getTranscriptionAndState", "query failed."); + return null; + } + + if (cursor.moveToFirst()) { + String transcription = cursor.getString(TRANSCRIPTION); + int transcriptionState = cursor.getInt(TRANSCRIPTION_STATE); + return new Pair<>(transcription, transcriptionState); + } + } + LogUtil.i("TranscriptionDbHelper.getTranscriptionAndState", "query returned no results"); + return null; + } + + @WorkerThread + @TargetApi(VERSION_CODES.M) // used for try with resources + List getUntranscribedVoicemails() { + Assert.checkArgument(BuildCompat.isAtLeastO()); + Assert.isWorkerThread(); + List untranscribed = new ArrayList<>(); + String whereClause = + Voicemails.TRANSCRIPTION + " is NULL AND " + VoicemailCompat.TRANSCRIPTION_STATE + "=?"; + String[] whereArgs = {String.valueOf(VoicemailCompat.TRANSCRIPTION_NOT_STARTED)}; + try (Cursor cursor = contentResolver.query(uri, PROJECTION, whereClause, whereArgs, null)) { + if (cursor == null) { + LogUtil.e("TranscriptionDbHelper.getUntranscribedVoicemails", "query failed."); + } else { + while (cursor.moveToNext()) { + untranscribed.add(ContentUris.withAppendedId(uri, cursor.getLong(ID))); + } + } + } + return untranscribed; + } + + @WorkerThread + void setTranscriptionState(int transcriptionState) { + Assert.isWorkerThread(); + LogUtil.i( + "TranscriptionDbHelper.setTranscriptionState", + "uri: " + uri + ", state: " + transcriptionState); + ContentValues values = new ContentValues(); + values.put(VoicemailCompat.TRANSCRIPTION_STATE, transcriptionState); + updateDatabase(values); + } + + @WorkerThread + void setTranscriptionAndState(String transcription, int transcriptionState) { + Assert.isWorkerThread(); + LogUtil.i( + "TranscriptionDbHelper.setTranscriptionAndState", + "uri: " + uri + ", state: " + transcriptionState); + ContentValues values = new ContentValues(); + values.put(Voicemails.TRANSCRIPTION, transcription); + values.put(VoicemailCompat.TRANSCRIPTION_STATE, transcriptionState); + updateDatabase(values); + } + + private void updateDatabase(ContentValues values) { + int updatedCount = contentResolver.update(uri, values, null, null); + if (updatedCount != 1) { + LogUtil.e( + "TranscriptionDbHelper.updateDatabase", + "Wrong row count, should have updated 1 row, was: " + updatedCount); + } + } +} diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionService.java b/java/com/android/voicemail/impl/transcribe/TranscriptionService.java new file mode 100644 index 000000000..2ca16fbf2 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionService.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe; + +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.app.job.JobWorkItem; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.support.annotation.MainThread; +import android.support.annotation.VisibleForTesting; +import android.support.v4.os.BuildCompat; +import android.text.TextUtils; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import com.android.dialer.constants.ScheduledJobIds; +import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.Logger; +import com.android.voicemail.impl.transcribe.grpc.TranscriptionClientFactory; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Job scheduler callback for launching voicemail transcription tasks. The transcription tasks will + * run in the background and will typically last for approximately the length of the voicemail audio + * (since thats how long the backend transcription service takes to do the transcription). + */ +public class TranscriptionService extends JobService { + @VisibleForTesting static final String EXTRA_VOICEMAIL_URI = "extra_voicemail_uri"; + + private ExecutorService executorService; + private JobParameters jobParameters; + private TranscriptionClientFactory clientFactory; + private TranscriptionConfigProvider configProvider; + + /** Callback used by a task to indicate it has finished processing its work item */ + interface JobCallback { + void onWorkCompleted(JobWorkItem completedWorkItem); + } + + // Schedule a task to transcribe the indicated voicemail, return true if transcription task was + // scheduled. + @MainThread + public static boolean scheduleNewVoicemailTranscriptionJob( + Context context, Uri voicemailUri, boolean highPriority) { + Assert.isMainThread(); + if (BuildCompat.isAtLeastO()) { + LogUtil.i( + "TranscriptionService.scheduleNewVoicemailTranscriptionJob", "scheduling transcription"); + Logger.get(context).logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_VOICEMAIL_RECEIVED); + + ComponentName componentName = new ComponentName(context, TranscriptionService.class); + JobInfo.Builder builder = + new JobInfo.Builder(ScheduledJobIds.VVM_TRANSCRIPTION_JOB, componentName); + if (highPriority) { + builder + .setMinimumLatency(0) + .setOverrideDeadline(0) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); + } else { + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); + } + JobScheduler scheduler = context.getSystemService(JobScheduler.class); + JobWorkItem workItem = makeWorkItem(voicemailUri); + return scheduler.enqueue(builder.build(), workItem) == JobScheduler.RESULT_SUCCESS; + } else { + LogUtil.i("TranscriptionService.scheduleNewVoicemailTranscriptionJob", "not supported"); + return false; + } + } + + // Cancel all transcription tasks + @MainThread + public static void cancelTranscriptions(Context context) { + Assert.isMainThread(); + LogUtil.enterBlock("TranscriptionService.cancelTranscriptions"); + JobScheduler scheduler = context.getSystemService(JobScheduler.class); + scheduler.cancel(ScheduledJobIds.VVM_TRANSCRIPTION_JOB); + } + + @MainThread + public TranscriptionService() { + Assert.isMainThread(); + } + + @VisibleForTesting + TranscriptionService( + ExecutorService executorService, + TranscriptionClientFactory clientFactory, + TranscriptionConfigProvider configProvider) { + this.executorService = executorService; + this.clientFactory = clientFactory; + this.configProvider = configProvider; + } + + @Override + @MainThread + public boolean onStartJob(JobParameters params) { + Assert.isMainThread(); + LogUtil.enterBlock("TranscriptionService.onStartJob"); + if (!getConfigProvider().isVoicemailTranscriptionEnabled()) { + LogUtil.i("TranscriptionService.onStartJob", "transcription not enabled, exiting."); + return false; + } else if (TextUtils.isEmpty(getConfigProvider().getServerAddress())) { + LogUtil.i("TranscriptionService.onStartJob", "transcription server not configured, exiting."); + return false; + } else { + LogUtil.i( + "TranscriptionService.onStartJob", + "transcription server address: " + configProvider.getServerAddress()); + jobParameters = params; + return checkForWork(); + } + } + + @Override + @MainThread + public boolean onStopJob(JobParameters params) { + Assert.isMainThread(); + LogUtil.enterBlock("TranscriptionService.onStopJob"); + cleanup(); + return true; + } + + @Override + @MainThread + public void onDestroy() { + Assert.isMainThread(); + LogUtil.enterBlock("TranscriptionService.onDestroy"); + cleanup(); + } + + private void cleanup() { + if (clientFactory != null) { + clientFactory.shutdown(); + clientFactory = null; + } + if (executorService != null) { + executorService.shutdownNow(); + executorService = null; + } + } + + @MainThread + private boolean checkForWork() { + Assert.isMainThread(); + JobWorkItem workItem = jobParameters.dequeueWork(); + if (workItem != null) { + TranscriptionTask task = + configProvider.shouldUseSyncApi() + ? new TranscriptionTaskSync( + this, new Callback(), workItem, getClientFactory(), configProvider) + : new TranscriptionTaskAsync( + this, new Callback(), workItem, getClientFactory(), configProvider); + getExecutorService().execute(task); + return true; + } else { + return false; + } + } + + static Uri getVoicemailUri(JobWorkItem workItem) { + return workItem.getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI); + } + + private ExecutorService getExecutorService() { + if (executorService == null) { + // The common use case is transcribing a single voicemail so just use a single thread executor + // The reason we're not using DialerExecutor here is because the transcription task can be + // very long running (ie. multiple minutes). + executorService = Executors.newSingleThreadExecutor(); + } + return executorService; + } + + private class Callback implements JobCallback { + @Override + @MainThread + public void onWorkCompleted(JobWorkItem completedWorkItem) { + Assert.isMainThread(); + LogUtil.i("TranscriptionService.Callback.onWorkCompleted", completedWorkItem.toString()); + jobParameters.completeWork(completedWorkItem); + checkForWork(); + } + } + + private static JobWorkItem makeWorkItem(Uri voicemailUri) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_VOICEMAIL_URI, voicemailUri); + return new JobWorkItem(intent); + } + + private TranscriptionConfigProvider getConfigProvider() { + if (configProvider == null) { + configProvider = new TranscriptionConfigProvider(this); + } + return configProvider; + } + + private TranscriptionClientFactory getClientFactory() { + if (clientFactory == null) { + clientFactory = new TranscriptionClientFactory(this, getConfigProvider()); + } + return clientFactory; + } +} diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionTask.java b/java/com/android/voicemail/impl/transcribe/TranscriptionTask.java new file mode 100644 index 000000000..b5f29da00 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionTask.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe; + +import android.annotation.TargetApi; +import android.app.job.JobWorkItem; +import android.content.Context; +import android.net.Uri; +import android.text.TextUtils; +import android.util.Pair; +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; +import com.android.voicemail.impl.transcribe.TranscriptionService.JobCallback; +import com.android.voicemail.impl.transcribe.grpc.TranscriptionClient; +import com.android.voicemail.impl.transcribe.grpc.TranscriptionClientFactory; +import com.android.voicemail.impl.transcribe.grpc.TranscriptionResponse; +import com.google.internal.communications.voicemailtranscription.v1.AudioFormat; +import com.google.internal.communications.voicemailtranscription.v1.TranscriptionStatus; +import com.google.protobuf.ByteString; +import java.io.IOException; +import java.io.InputStream; + +/** + * Background task to get a voicemail transcription and update the database. + * + *

+ * This task performs the following steps:
+ *   1. Update the transcription-state in the database to 'in-progress'
+ *   2. Create grpc client and transcription request
+ *   3. Make synchronous or asynchronous grpc transcription request to backend server
+ *     3a. On response
+ *       Update the database with transcription (if successful) and new transcription-state
+ *     3b. On network error
+ *       If retry-count < max then increment retry-count and retry the request
+ *       Otherwise update the transcription-state in the database to 'transcription-failed'
+ *   4. Notify the callback that the work item is complete
+ * 
+ */ +public abstract class TranscriptionTask implements Runnable { + private static final String TAG = "TranscriptionTask"; + + private final Context context; + private final JobCallback callback; + private final JobWorkItem workItem; + private final TranscriptionClientFactory clientFactory; + private final Uri voicemailUri; + private final TranscriptionDbHelper databaseHelper; + protected final TranscriptionConfigProvider configProvider; + protected ByteString audioData; + protected AudioFormat encoding; + + static final String AMR_PREFIX = "#!AMR\n"; + + /** Functional interface for sending requests to the transcription server */ + public interface Request { + TranscriptionResponse getResponse(TranscriptionClient client); + } + + TranscriptionTask( + Context context, + JobCallback callback, + JobWorkItem workItem, + TranscriptionClientFactory clientFactory, + TranscriptionConfigProvider configProvider) { + this.context = context; + this.callback = callback; + this.workItem = workItem; + this.clientFactory = clientFactory; + this.voicemailUri = TranscriptionService.getVoicemailUri(workItem); + this.configProvider = configProvider; + databaseHelper = new TranscriptionDbHelper(context, voicemailUri); + } + + @Override + public void run() { + VvmLog.i(TAG, "run"); + if (readAndValidateAudioFile()) { + updateTranscriptionState(VoicemailCompat.TRANSCRIPTION_IN_PROGRESS); + transcribeVoicemail(); + } else { + if (AudioFormat.AUDIO_FORMAT_UNSPECIFIED.equals(encoding)) { + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_VOICEMAIL_FORMAT_NOT_SUPPORTED); + } else { + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_VOICEMAIL_INVALID_DATA); + } + updateTranscriptionState(VoicemailCompat.TRANSCRIPTION_FAILED); + } + ThreadUtil.postOnUiThread( + () -> { + callback.onWorkCompleted(workItem); + }); + } + + protected abstract Pair getTranscription(); + + protected abstract DialerImpression.Type getRequestSentImpression(); + + private void transcribeVoicemail() { + VvmLog.i(TAG, "transcribeVoicemail"); + Pair pair = getTranscription(); + String transcript = pair.first; + TranscriptionStatus status = pair.second; + if (!TextUtils.isEmpty(transcript)) { + updateTranscriptionAndState(transcript, VoicemailCompat.TRANSCRIPTION_AVAILABLE); + VvmLog.i(TAG, "transcribeVoicemail, got response"); + Logger.get(context).logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_RESPONSE_SUCCESS); + } else { + VvmLog.i(TAG, "transcribeVoicemail, transcription unsuccessful, " + status); + switch (status) { + case FAILED_LANGUAGE_NOT_SUPPORTED: + Logger.get(context) + .logImpression( + DialerImpression.Type.VVM_TRANSCRIPTION_RESPONSE_LANGUAGE_NOT_SUPPORTED); + break; + case FAILED_NO_SPEECH_DETECTED: + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_RESPONSE_NO_SPEECH_DETECTED); + break; + case EXPIRED: + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_RESPONSE_EXPIRED); + break; + default: + Logger.get(context).logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_RESPONSE_EMPTY); + break; + } + updateTranscriptionAndState(transcript, VoicemailCompat.TRANSCRIPTION_FAILED); + } + } + + protected TranscriptionResponse sendRequest(Request request) { + VvmLog.i(TAG, "sendRequest"); + TranscriptionClient client = clientFactory.getClient(); + for (int i = 0; i < configProvider.getMaxTranscriptionRetries(); i++) { + VvmLog.i(TAG, "sendRequest, try: " + (i + 1)); + if (i == 0) { + Logger.get(context).logImpression(getRequestSentImpression()); + } else { + Logger.get(context).logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_REQUEST_RETRY); + } + + TranscriptionResponse response = request.getResponse(client); + if (response.hasRecoverableError()) { + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_RESPONSE_RECOVERABLE_ERROR); + backoff(i); + } else { + return response; + } + } + + Logger.get(context) + .logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_RESPONSE_TOO_MANY_ERRORS); + return null; + } + + private static void backoff(int retryCount) { + VvmLog.i(TAG, "backoff, count: " + retryCount); + long millis = (1L << retryCount) * 1000; + sleep(millis); + } + + protected static void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + VvmLog.w(TAG, "interrupted"); + Thread.currentThread().interrupt(); + } + } + + private void updateTranscriptionAndState(String transcript, int newState) { + databaseHelper.setTranscriptionAndState(transcript, newState); + } + + private void updateTranscriptionState(int newState) { + databaseHelper.setTranscriptionState(newState); + } + + // Uses try-with-resource + @TargetApi(android.os.Build.VERSION_CODES.M) + private boolean readAndValidateAudioFile() { + if (voicemailUri == null) { + VvmLog.i(TAG, "Transcriber.readAndValidateAudioFile, file not found."); + return false; + } else { + VvmLog.i(TAG, "Transcriber.readAndValidateAudioFile, reading: " + voicemailUri); + } + + try (InputStream in = context.getContentResolver().openInputStream(voicemailUri)) { + audioData = ByteString.readFrom(in); + VvmLog.i(TAG, "Transcriber.readAndValidateAudioFile, read " + audioData.size() + " bytes"); + } catch (IOException e) { + VvmLog.e(TAG, "Transcriber.readAndValidateAudioFile", e); + return false; + } + + if (audioData.startsWith(ByteString.copyFromUtf8(AMR_PREFIX))) { + encoding = AudioFormat.AMR_NB_8KHZ; + } else { + VvmLog.i(TAG, "Transcriber.readAndValidateAudioFile, unknown encoding"); + encoding = AudioFormat.AUDIO_FORMAT_UNSPECIFIED; + return false; + } + + return true; + } +} diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java b/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java new file mode 100644 index 000000000..3c41aef89 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionTaskAsync.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe; + +import android.app.job.JobWorkItem; +import android.content.Context; +import android.util.Pair; +import com.android.dialer.common.Assert; +import com.android.dialer.logging.DialerImpression; +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.GetTranscriptRequest; +import com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest; +import com.google.internal.communications.voicemailtranscription.v1.TranscriptionStatus; + +/** + * Background task to get a voicemail transcription using the asynchronous API. The async API works + * as follows: + * + *
    + *
  1. client uploads voicemail data to the server + *
  2. server responds with a transcription-id and an estimated transcription wait time + *
  3. client waits appropriate amount of time then begins polling for the result + *
+ * + * This implementation blocks until the response or an error is received, even though it is using + * the asynchronous server API. + */ +public class TranscriptionTaskAsync extends TranscriptionTask { + private static final String TAG = "TranscriptionTaskAsync"; + + public TranscriptionTaskAsync( + Context context, + JobCallback callback, + JobWorkItem workItem, + TranscriptionClientFactory clientFactory, + TranscriptionConfigProvider configProvider) { + super(context, callback, workItem, clientFactory, configProvider); + } + + @Override + protected Pair getTranscription() { + VvmLog.i(TAG, "getTranscription"); + + TranscriptionResponseAsync uploadResponse = + (TranscriptionResponseAsync) + sendRequest((client) -> client.sendUploadRequest(getUploadRequest())); + + if (uploadResponse == null) { + VvmLog.i(TAG, "getTranscription, failed to upload voicemail."); + return new Pair<>(null, TranscriptionStatus.FAILED_NO_RETRY); + } else { + waitForTranscription(uploadResponse); + return pollForTranscription(uploadResponse); + } + } + + @Override + protected DialerImpression.Type getRequestSentImpression() { + return DialerImpression.Type.VVM_TRANSCRIPTION_REQUEST_SENT_ASYNC; + } + + private static void waitForTranscription(TranscriptionResponseAsync uploadResponse) { + long millis = uploadResponse.getEstimatedWaitMillis(); + VvmLog.i(TAG, "waitForTranscription, " + millis + " millis"); + sleep(millis); + } + + private Pair pollForTranscription( + TranscriptionResponseAsync uploadResponse) { + VvmLog.i(TAG, "pollForTranscription"); + GetTranscriptRequest request = getGetTranscriptRequest(uploadResponse); + for (int i = 0; i < configProvider.getMaxGetTranscriptPolls(); i++) { + GetTranscriptResponseAsync response = + (GetTranscriptResponseAsync) + sendRequest((client) -> client.sendGetTranscriptRequest(request)); + if (response == null) { + VvmLog.i(TAG, "pollForTranscription, no transcription result."); + } else if (response.isTranscribing()) { + VvmLog.i(TAG, "pollForTranscription, poll count: " + (i + 1)); + } else if (response.hasFatalError()) { + VvmLog.i(TAG, "pollForTranscription, fail. " + response.getErrorDescription()); + return new Pair<>(null, response.getTranscriptionStatus()); + } else { + VvmLog.i(TAG, "pollForTranscription, got transcription"); + return new Pair<>(response.getTranscript(), TranscriptionStatus.SUCCESS); + } + sleep(configProvider.getGetTranscriptPollIntervalMillis()); + } + VvmLog.i(TAG, "pollForTranscription, timed out."); + return new Pair<>(null, TranscriptionStatus.FAILED_NO_RETRY); + } + + private TranscribeVoicemailAsyncRequest getUploadRequest() { + return TranscribeVoicemailAsyncRequest.newBuilder() + .setVoicemailData(audioData) + .setAudioFormat(encoding) + .build(); + } + + private GetTranscriptRequest getGetTranscriptRequest(TranscriptionResponseAsync uploadResponse) { + Assert.checkArgument(uploadResponse.getTranscriptionId() != null); + return GetTranscriptRequest.newBuilder() + .setTranscriptionId(uploadResponse.getTranscriptionId()) + .build(); + } +} diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionTaskSync.java b/java/com/android/voicemail/impl/transcribe/TranscriptionTaskSync.java new file mode 100644 index 000000000..bee68590a --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionTaskSync.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe; + +import android.app.job.JobWorkItem; +import android.content.Context; +import android.util.Pair; +import com.android.dialer.logging.DialerImpression; +import com.android.voicemail.impl.VvmLog; +import com.android.voicemail.impl.transcribe.TranscriptionService.JobCallback; +import com.android.voicemail.impl.transcribe.grpc.TranscriptionClientFactory; +import com.android.voicemail.impl.transcribe.grpc.TranscriptionResponseSync; +import com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest; +import com.google.internal.communications.voicemailtranscription.v1.TranscriptionStatus; + +/** Background task to get a voicemail transcription using the synchronous API */ +public class TranscriptionTaskSync extends TranscriptionTask { + private static final String TAG = "TranscriptionTaskSync"; + + public TranscriptionTaskSync( + Context context, + JobCallback callback, + JobWorkItem workItem, + TranscriptionClientFactory clientFactory, + TranscriptionConfigProvider configProvider) { + super(context, callback, workItem, clientFactory, configProvider); + } + + @Override + protected Pair getTranscription() { + VvmLog.i(TAG, "getTranscription"); + + TranscriptionResponseSync response = + (TranscriptionResponseSync) + sendRequest((client) -> client.sendSyncRequest(getSyncRequest())); + if (response == null) { + VvmLog.i(TAG, "getTranscription, failed to transcribe voicemail."); + return new Pair<>(null, TranscriptionStatus.FAILED_NO_RETRY); + } else { + VvmLog.i(TAG, "getTranscription, got transcription"); + return new Pair<>(response.getTranscript(), TranscriptionStatus.SUCCESS); + } + } + + @Override + protected DialerImpression.Type getRequestSentImpression() { + return DialerImpression.Type.VVM_TRANSCRIPTION_REQUEST_SENT; + } + + private TranscribeVoicemailRequest getSyncRequest() { + return TranscribeVoicemailRequest.newBuilder() + .setVoicemailData(audioData) + .setAudioFormat(encoding) + .build(); + } +} diff --git a/java/com/android/voicemail/impl/transcribe/VoicemailCompat.java b/java/com/android/voicemail/impl/transcribe/VoicemailCompat.java new file mode 100644 index 000000000..c6e30c6de --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/VoicemailCompat.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe; + +/** + * Provide access to new API constants before they're publicly available + * + *

Copied from android.provider.VoicemailContract.Voicemails. These should become public in O-MR1 + * and these constants can be removed then. + */ +public class VoicemailCompat { + + /** + * The state of the voicemail transcription. + * + *

Possible values: {@link #TRANSCRIPTION_NOT_STARTED}, {@link #TRANSCRIPTION_IN_PROGRESS}, + * {@link #TRANSCRIPTION_FAILED}, {@link #TRANSCRIPTION_AVAILABLE}. + * + *

Type: INTEGER + */ + public static final String TRANSCRIPTION_STATE = "transcription_state"; + + /** + * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has not yet been + * attempted. + */ + public static final int TRANSCRIPTION_NOT_STARTED = 0; + + /** + * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has begun but is not yet + * complete. + */ + public static final int TRANSCRIPTION_IN_PROGRESS = 1; + + /** + * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has been attempted and + * failed. + */ + public static final int TRANSCRIPTION_FAILED = 2; + + /** + * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has completed and the + * result has been stored in the {@link #TRANSCRIPTION} column. + */ + public static final int TRANSCRIPTION_AVAILABLE = 3; +} diff --git a/java/com/android/voicemail/impl/transcribe/grpc/GetTranscriptResponseAsync.java b/java/com/android/voicemail/impl/transcribe/grpc/GetTranscriptResponseAsync.java new file mode 100644 index 000000000..f979d69ce --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/grpc/GetTranscriptResponseAsync.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe.grpc; + +import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; +import com.android.dialer.common.Assert; +import com.google.internal.communications.voicemailtranscription.v1.GetTranscriptResponse; +import com.google.internal.communications.voicemailtranscription.v1.TranscriptionStatus; +import io.grpc.Status; + +/** Container for response and status objects for an asynchronous get-transcript request */ +public class GetTranscriptResponseAsync extends TranscriptionResponse { + @Nullable private final GetTranscriptResponse response; + + @VisibleForTesting + public GetTranscriptResponseAsync(GetTranscriptResponse response) { + Assert.checkArgument(response != null); + this.response = response; + } + + @VisibleForTesting + public GetTranscriptResponseAsync(Status status) { + super(status); + this.response = null; + } + + public @Nullable String getTranscript() { + if (response != null) { + return response.getTranscript(); + } + return null; + } + + public @Nullable String getErrorDescription() { + if (!hasRecoverableError() && !hasFatalError()) { + return null; + } + if (status != null) { + return "Grpc error: " + status; + } + if (response != null) { + return "Transcription error: " + response.getStatus(); + } + Assert.fail("Impossible state"); + return null; + } + + public TranscriptionStatus getTranscriptionStatus() { + if (response == null) { + return TranscriptionStatus.TRANSCRIPTION_STATUS_UNSPECIFIED; + } else { + return response.getStatus(); + } + } + + public boolean isTranscribing() { + return response != null && response.getStatus() == TranscriptionStatus.PENDING; + } + + @Override + public boolean hasRecoverableError() { + if (super.hasRecoverableError()) { + return true; + } + + if (response != null) { + return response.getStatus() == TranscriptionStatus.EXPIRED + || response.getStatus() == TranscriptionStatus.FAILED_RETRY; + } + + return false; + } + + @Override + public boolean hasFatalError() { + if (super.hasFatalError()) { + return true; + } + + if (response != null) { + return response.getStatus() == TranscriptionStatus.FAILED_NO_RETRY + || response.getStatus() == TranscriptionStatus.FAILED_LANGUAGE_NOT_SUPPORTED + || response.getStatus() == TranscriptionStatus.FAILED_NO_SPEECH_DETECTED; + } + + return false; + } +} diff --git a/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionClient.java b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionClient.java new file mode 100644 index 000000000..b18d95627 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionClient.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe.grpc; + +import android.support.annotation.WorkerThread; +import com.google.internal.communications.voicemailtranscription.v1.GetTranscriptRequest; +import com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncRequest; +import com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailRequest; +import com.google.internal.communications.voicemailtranscription.v1.VoicemailTranscriptionServiceGrpc; +import io.grpc.StatusRuntimeException; + +/** Wrapper around Grpc transcription server stub */ +public class TranscriptionClient { + + private final VoicemailTranscriptionServiceGrpc.VoicemailTranscriptionServiceBlockingStub stub; + + TranscriptionClient( + VoicemailTranscriptionServiceGrpc.VoicemailTranscriptionServiceBlockingStub stub) { + this.stub = stub; + } + + @WorkerThread + public TranscriptionResponseSync sendSyncRequest(TranscribeVoicemailRequest request) { + try { + return new TranscriptionResponseSync(stub.transcribeVoicemail(request)); + } catch (StatusRuntimeException e) { + return new TranscriptionResponseSync(e.getStatus()); + } + } + + @WorkerThread + public TranscriptionResponseAsync sendUploadRequest(TranscribeVoicemailAsyncRequest request) { + try { + return new TranscriptionResponseAsync(stub.transcribeVoicemailAsync(request)); + } catch (StatusRuntimeException e) { + return new TranscriptionResponseAsync(e.getStatus()); + } + } + + @WorkerThread + public GetTranscriptResponseAsync sendGetTranscriptRequest(GetTranscriptRequest request) { + try { + return new GetTranscriptResponseAsync(stub.getTranscript(request)); + } catch (StatusRuntimeException e) { + return new GetTranscriptResponseAsync(e.getStatus()); + } + } +} diff --git a/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionClientFactory.java b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionClientFactory.java new file mode 100644 index 000000000..c57b01fd7 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionClientFactory.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe.grpc; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.text.TextUtils; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import com.android.voicemail.impl.transcribe.TranscriptionConfigProvider; +import com.google.internal.communications.voicemailtranscription.v1.VoicemailTranscriptionServiceGrpc; +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ClientInterceptors; +import io.grpc.ForwardingClientCall; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.okhttp.OkHttpChannelBuilder; +import java.security.MessageDigest; + +/** + * Factory for creating grpc clients that talk to the transcription server. This allows all clients + * to share the same channel, which is relatively expensive to create. + */ +public class TranscriptionClientFactory { + private static final String DIGEST_ALGORITHM_SHA1 = "SHA1"; + private static final char[] HEX_UPPERCASE = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + private final TranscriptionConfigProvider configProvider; + private final ManagedChannel originalChannel; + private final String packageName; + private final String cert; + + public TranscriptionClientFactory(Context context, TranscriptionConfigProvider configProvider) { + this(context, configProvider, getManagedChannel(configProvider)); + } + + public TranscriptionClientFactory( + Context context, TranscriptionConfigProvider configProvider, ManagedChannel managedChannel) { + this.configProvider = configProvider; + this.packageName = context.getPackageName(); + this.cert = getCertificateFingerprint(context); + originalChannel = managedChannel; + } + + public TranscriptionClient getClient() { + LogUtil.enterBlock("TranscriptionClientFactory.getClient"); + Assert.checkState(!originalChannel.isShutdown()); + Channel channel = + ClientInterceptors.intercept( + originalChannel, + new Interceptor( + packageName, cert, configProvider.getApiKey(), configProvider.getAuthToken())); + return new TranscriptionClient(VoicemailTranscriptionServiceGrpc.newBlockingStub(channel)); + } + + public void shutdown() { + LogUtil.enterBlock("TranscriptionClientFactory.shutdown"); + if (!originalChannel.isShutdown()) { + originalChannel.shutdown(); + } + } + + private static ManagedChannel getManagedChannel(TranscriptionConfigProvider configProvider) { + ManagedChannelBuilder builder = + OkHttpChannelBuilder.forTarget(configProvider.getServerAddress()); + // Only use plaintext for debugging + if (configProvider.shouldUsePlaintext()) { + // Just passing 'false' doesnt have the same effect as not setting this field + builder.usePlaintext(true); + } + return builder.build(); + } + + private static String getCertificateFingerprint(Context context) { + try { + PackageInfo packageInfo = + context + .getPackageManager() + .getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); + if (packageInfo != null + && packageInfo.signatures != null + && packageInfo.signatures.length > 0) { + MessageDigest messageDigest = MessageDigest.getInstance(DIGEST_ALGORITHM_SHA1); + if (messageDigest == null) { + LogUtil.w( + "TranscriptionClientFactory.getCertificateFingerprint", "error getting digest."); + return null; + } + byte[] bytes = messageDigest.digest(packageInfo.signatures[0].toByteArray()); + if (bytes == null) { + LogUtil.w( + "TranscriptionClientFactory.getCertificateFingerprint", "empty message digest."); + return null; + } + + int length = bytes.length; + StringBuilder out = new StringBuilder(length * 2); + for (int i = 0; i < length; i++) { + out.append(HEX_UPPERCASE[(bytes[i] & 0xf0) >>> 4]); + out.append(HEX_UPPERCASE[bytes[i] & 0x0f]); + } + return out.toString(); + } else { + LogUtil.w( + "TranscriptionClientFactory.getCertificateFingerprint", + "failed to get package signature."); + } + } catch (Exception e) { + LogUtil.e( + "TranscriptionClientFactory.getCertificateFingerprint", + "error getting certificate fingerprint.", + e); + } + + return null; + } + + private static final class Interceptor implements ClientInterceptor { + private final String packageName; + private final String cert; + private final String apiKey; + private final String authToken; + + private static final Metadata.Key API_KEY_HEADER = + Metadata.Key.of("X-Goog-Api-Key", Metadata.ASCII_STRING_MARSHALLER); + private static final Metadata.Key ANDROID_PACKAGE_HEADER = + Metadata.Key.of("X-Android-Package", Metadata.ASCII_STRING_MARSHALLER); + private static final Metadata.Key ANDROID_CERT_HEADER = + Metadata.Key.of("X-Android-Cert", Metadata.ASCII_STRING_MARSHALLER); + private static final Metadata.Key AUTHORIZATION_HEADER = + Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER); + + public Interceptor(String packageName, String cert, String apiKey, String authToken) { + this.packageName = packageName; + this.cert = cert; + this.apiKey = apiKey; + this.authToken = authToken; + } + + @Override + public ClientCall interceptCall( + MethodDescriptor method, CallOptions callOptions, Channel next) { + LogUtil.enterBlock( + "TranscriptionClientFactory.interceptCall, intercepted " + method.getFullMethodName()); + ClientCall call = next.newCall(method, callOptions); + + call = + new ForwardingClientCall.SimpleForwardingClientCall(call) { + @Override + public void start(Listener responseListener, Metadata headers) { + if (!TextUtils.isEmpty(packageName)) { + LogUtil.i( + "TranscriptionClientFactory.interceptCall", + "attaching package name: " + packageName); + headers.put(ANDROID_PACKAGE_HEADER, packageName); + } + if (!TextUtils.isEmpty(cert)) { + LogUtil.i("TranscriptionClientFactory.interceptCall", "attaching android cert"); + headers.put(ANDROID_CERT_HEADER, cert); + } + if (!TextUtils.isEmpty(apiKey)) { + LogUtil.i("TranscriptionClientFactory.interceptCall", "attaching API Key"); + headers.put(API_KEY_HEADER, apiKey); + } + if (!TextUtils.isEmpty(authToken)) { + LogUtil.i("TranscriptionClientFactory.interceptCall", "attaching auth token"); + headers.put(AUTHORIZATION_HEADER, "Bearer " + authToken); + } + super.start(responseListener, headers); + } + }; + return call; + } + } +} diff --git a/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponse.java b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponse.java new file mode 100644 index 000000000..f0823de32 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponse.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe.grpc; + +import android.support.annotation.Nullable; +import com.android.dialer.common.Assert; +import io.grpc.Status; + +/** + * Base class for encapulating a voicemail transcription server response. This handles the Grpc + * status response, subclasses will handle request specific responses. + */ +public abstract class TranscriptionResponse { + @Nullable public final Status status; + + TranscriptionResponse() { + this.status = null; + } + + TranscriptionResponse(Status status) { + Assert.checkArgument(status != null); + this.status = status; + } + + public boolean hasRecoverableError() { + if (status != null) { + return status.getCode() == Status.Code.UNAVAILABLE; + } + + return false; + } + + public boolean hasFatalError() { + if (status != null) { + return status.getCode() != Status.Code.OK && status.getCode() != Status.Code.UNAVAILABLE; + } + + return false; + } +} diff --git a/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponseAsync.java b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponseAsync.java new file mode 100644 index 000000000..38b463053 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponseAsync.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe.grpc; + +import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; +import com.android.dialer.common.Assert; +import com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailAsyncResponse; +import io.grpc.Status; + +/** Container for response and status objects for an asynchronous transcription upload request */ +public class TranscriptionResponseAsync extends TranscriptionResponse { + @Nullable private final TranscribeVoicemailAsyncResponse response; + + @VisibleForTesting + public TranscriptionResponseAsync(TranscribeVoicemailAsyncResponse response) { + Assert.checkArgument(response != null); + this.response = response; + } + + @VisibleForTesting + public TranscriptionResponseAsync(Status status) { + super(status); + this.response = null; + } + + public @Nullable String getTranscriptionId() { + if (response != null) { + return response.getTranscriptionId(); + } + return null; + } + + public long getEstimatedWaitMillis() { + if (response != null) { + return response.getEstimatedWaitSecs() * 1_000L; + } + return 0; + } +} diff --git a/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponseSync.java b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponseSync.java new file mode 100644 index 000000000..d2e2e218c --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/grpc/TranscriptionResponseSync.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.android.voicemail.impl.transcribe.grpc; + +import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; +import com.android.dialer.common.Assert; +import com.google.internal.communications.voicemailtranscription.v1.TranscribeVoicemailResponse; +import io.grpc.Status; + +/** Container for response and status objects for a synchronous transcription request */ +public class TranscriptionResponseSync extends TranscriptionResponse { + @Nullable private final TranscribeVoicemailResponse response; + + @VisibleForTesting + public TranscriptionResponseSync(Status status) { + super(status); + this.response = null; + } + + @VisibleForTesting + public TranscriptionResponseSync(TranscribeVoicemailResponse response) { + Assert.checkArgument(response != null); + this.response = response; + } + + public @Nullable String getTranscript() { + return (response != null) ? response.getTranscript() : null; + } +} diff --git a/java/com/android/voicemail/impl/transcribe/grpc/voicemail_transcription.proto b/java/com/android/voicemail/impl/transcribe/grpc/voicemail_transcription.proto new file mode 100644 index 000000000..a2064d193 --- /dev/null +++ b/java/com/android/voicemail/impl/transcribe/grpc/voicemail_transcription.proto @@ -0,0 +1,133 @@ +// LINT.IfChange + +syntax = "proto2"; + +package google.internal.communications.voicemailtranscription.v1; + +option java_multiple_files = true; +option optimize_for = LITE_RUNTIME; + +option java_package = "com.google.internal.communications.voicemailtranscription.v1"; + +// Enum that specifies supported audio formats. +enum AudioFormat { + // Default but invalid value. + AUDIO_FORMAT_UNSPECIFIED = 0; + + // Adaptive Multi-Rate Narrowband, 8kHz sampling frequency. + // https://en.wikipedia.org/wiki/Adaptive_Multi-Rate_audio_codec + AMR_NB_8KHZ = 1; +} + +// Enum that describes the status of the transcription process. +enum TranscriptionStatus { + // Default but invalid value. + TRANSCRIPTION_STATUS_UNSPECIFIED = 0; + + // Transcription was successful and the transcript is present. + SUCCESS = 1; + + // Transcription is progress. Check again later. + PENDING = 2; + + // Transcription was successful, but the expiration period has passed, which + // means that the sensative data (including the transcript) has been deleted. + // Resend the voicemail through TranscribeVoicemailAsync to retry. + EXPIRED = 3; + + // Internal error encountered during the transcription. + // Resend the voicemail through TranscribeVoicemailAsync to retry. + // This is a catch-all status for all retriable errors that aren't captured by + // a more specfic status. + FAILED_RETRY = 4; + + // Internal error encountered during the transcription. + // Do not resend the voicemail. + // This is a catch-all status for all non-retriable errors that aren't + // captured by a more specfic status. + FAILED_NO_RETRY = 5; + + // The language detected is not yet supported by this service. + // Do not resend the voicemail. + FAILED_LANGUAGE_NOT_SUPPORTED = 6; + + // No speech was detected in the voicemail. + // Do not resend the voicemail. + FAILED_NO_SPEECH_DETECTED = 7; +} + +// Request for synchronous voicemail transcription. +message TranscribeVoicemailRequest { + // Voicemail audio file containing the raw bytes we receive from the carrier. + optional bytes voicemail_data = 1; + + // Audio format of the voicemail file. + optional AudioFormat audio_format = 2; +} + +// Response for synchronous voicemail transcription. +message TranscribeVoicemailResponse { + // The transcribed text of the voicemail. + optional string transcript = 1; +} + +// Request for asynchronous voicemail transcription. +message TranscribeVoicemailAsyncRequest { + // Voicemail audio data encoded in the format specified by audio_format. + optional bytes voicemail_data = 1; + + // Audio format of the voicemail file. + optional AudioFormat audio_format = 2; +} + +// Response for asynchronous voicemail transcription containing information +// needed to fetch the transcription results through the GetTranscript method. +message TranscribeVoicemailAsyncResponse { + // Unique ID for the transcription. This ID is used for retrieving the + // voicemail transcript later. + optional string transcription_id = 1; + + // The estimated amount of time in seconds before the transcription will be + // available. + // The client should not call GetTranscript until this time has elapsed, but + // the transcript is not guaranteed to be ready by this time. + optional int64 estimated_wait_secs = 2; +} + +// Request for retrieving an asynchronously generated transcript. +message GetTranscriptRequest { + // Unique ID for the transcription. This ID was returned by + // TranscribeVoicemailAsync. + optional string transcription_id = 1; +} + +// Response for retrieving an asynchronously generated transcript. +message GetTranscriptResponse { + // Status of the trascription process. + optional TranscriptionStatus status = 1; + + // The transcribed text of the voicemail. This is only present if the status + // is SUCCESS. + optional string transcript = 2; +} + +// RPC service for transcribing voicemails. +service VoicemailTranscriptionService { + // Returns a transcript of the given voicemail. + rpc TranscribeVoicemail(TranscribeVoicemailRequest) + returns (TranscribeVoicemailResponse) {} + + // Schedules a transcription of the given voicemail. The transcript can be + // retrieved using the returned ID. + rpc TranscribeVoicemailAsync(TranscribeVoicemailAsyncRequest) + returns (TranscribeVoicemailAsyncResponse) { + } + + // Returns the transcript corresponding to the given ID, which was returned + // by TranscribeVoicemailAsync. + rpc GetTranscript(GetTranscriptRequest) returns (GetTranscriptResponse) { + } +} + +// LINT.ThenChange(//depot/google3/google/internal/communications/voicemailtranscription/v1/\ +// voicemail_transcription.proto) -- cgit v1.2.3