diff options
Diffstat (limited to 'java/com/android/voicemail/impl/sync')
7 files changed, 113 insertions, 55 deletions
diff --git a/java/com/android/voicemail/impl/sync/OmtpVvmSyncReceiver.java b/java/com/android/voicemail/impl/sync/OmtpVvmSyncReceiver.java index 1b59eccfc..b2ec49e9f 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); + SyncTask.start(context, phoneAccount, OmtpVvmSyncService.SYNC_FULL_SYNC); } } } diff --git a/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java b/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java index 5b5d6b054..793388362 100644 --- a/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java +++ b/java/com/android/voicemail/impl/sync/OmtpVvmSyncService.java @@ -43,7 +43,6 @@ 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; @@ -51,13 +50,22 @@ import java.util.Map; @TargetApi(VERSION_CODES.O) public class OmtpVvmSyncService { - private static final String TAG = "OmtpVvmSyncService"; + private static final String TAG = OmtpVvmSyncService.class.getSimpleName(); + /** 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 final VoicemailsQueryHelper mQueryHelper; + + private VoicemailsQueryHelper mQueryHelper; public OmtpVvmSyncService(Context context) { mContext = context; @@ -66,21 +74,23 @@ 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 for account: " + phoneAccount); - setupAndSendRequest(task, phoneAccount, voicemail, status); + VvmLog.v(TAG, "Sync requested: " + action + " - for account: " + phoneAccount); + setupAndSendRequest(task, phoneAccount, voicemail, action, status); } private void setupAndSendRequest( BaseTask task, PhoneAccountHandle phoneAccount, Voicemail voicemail, + String action, VoicemailStatus.Editor status) { if (!VisualVoicemailSettingsUtil.isEnabled(mContext, phoneAccount)) { - VvmLog.e(TAG, "Sync requested for disabled account"); + VvmLog.v(TAG, "Sync requested for disabled account"); return; } if (!VvmAccountManager.isAccountActivated(mContext, phoneAccount)) { @@ -92,7 +102,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, which is currently displayed to the user as no error. + // "Sync in progress..." status. config.handleEvent( VoicemailStatus.edit(mContext, phoneAccount), OmtpEvents.DATA_IMAP_OPERATION_STARTED); try (NetworkWrapper network = VvmNetworkRequest.getNetwork(config, phoneAccount, status)) { @@ -101,7 +111,7 @@ public class OmtpVvmSyncService { task.fail(); return; } - doSync(task, network.get(), phoneAccount, voicemail, status); + doSync(task, network.get(), phoneAccount, voicemail, action, status); } catch (RequestFailedException e) { config.handleEvent(status, OmtpEvents.DATA_NO_CONNECTION_CELLULAR_REQUIRED); task.fail(); @@ -113,13 +123,14 @@ 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(imapHelper, phoneAccount); + success = syncAll(action, imapHelper, phoneAccount); } else { - success = downloadOneVoicemail(imapHelper, voicemail, phoneAccount); + success = syncOne(imapHelper, voicemail, phoneAccount); } if (success) { // TODO: b/30569269 failure should interrupt all subsequent task via exceptions @@ -208,32 +219,78 @@ public class OmtpVvmSyncService { } } - private boolean syncAll(ImapHelper imapHelper, PhoneAccountHandle account) { + private boolean syncAll(String action, ImapHelper imapHelper, PhoneAccountHandle account) { + boolean uploadSuccess = true; + boolean downloadSuccess = true; - List<Voicemail> serverVoicemails = imapHelper.fetchAllVoicemails(); - List<Voicemail> localVoicemails = mQueryHelper.getAllVoicemails(account); - List<Voicemail> deletedVoicemails = mQueryHelper.getDeletedVoicemails(account); - boolean succeeded = 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); + } - if (localVoicemails == null || serverVoicemails == null) { - // Null value means the query failed. - VvmLog.e(TAG, "syncAll: query failed"); - return false; + VvmLog.v( + TAG, + "upload succeeded: [" + + String.valueOf(uploadSuccess) + + "] download succeeded: [" + + String.valueOf(downloadSuccess) + + "]"); + + return uploadSuccess && downloadSuccess; + } + + 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()); } + return imapHelper.fetchTranscription( + new TranscriptionFetchedCallback(mContext, voicemail), voicemail.getSourceData()); + } + + private boolean upload(PhoneAccountHandle phoneAccountHandle, ImapHelper imapHelper) { + List<Voicemail> readVoicemails = mQueryHelper.getReadVoicemails(phoneAccountHandle); + List<Voicemail> deletedVoicemails = mQueryHelper.getDeletedVoicemails(phoneAccountHandle); + + boolean success = true; + if (deletedVoicemails.size() > 0) { if (imapHelper.markMessagesAsDeleted(deletedVoicemails)) { - // Delete only the voicemails that was deleted on the server, in case more are deleted - // since the IMAP query was completed. + // We want to delete selectively instead of all the voicemails for this provider + // in case the state changed since the IMAP query was completed. mQueryHelper.deleteFromDatabase(deletedVoicemails); } else { - succeeded = false; + success = false; } } - Map<String, Voicemail> remoteMap = buildMap(serverVoicemails); + 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; + } + } - List<Voicemail> localReadVoicemails = new ArrayList<>(); + return success; + } + + private boolean download(ImapHelper imapHelper, PhoneAccountHandle account) { + List<Voicemail> serverVoicemails = imapHelper.fetchAllVoicemails(); + List<Voicemail> localVoicemails = mQueryHelper.getAllVoicemails(account); + + if (localVoicemails == null || serverVoicemails == null) { + // Null value means the query failed. + return false; + } + + Map<String, Voicemail> remoteMap = buildMap(serverVoicemails); // 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 @@ -253,8 +310,6 @@ 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()) @@ -266,16 +321,6 @@ 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()) { @@ -291,19 +336,7 @@ public class OmtpVvmSyncService { } } - 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()); + return true; } 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 70c6bd890..cd2782abb 100644 --- a/java/com/android/voicemail/impl/sync/SyncOneTask.java +++ b/java/com/android/voicemail/impl/sync/SyncOneTask.java @@ -39,14 +39,17 @@ 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); } @@ -60,13 +63,14 @@ 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, mPhone, mVoicemail, VoicemailStatus.edit(getContext(), mPhone)); + service.sync(this, mSyncType, mPhone, mVoicemail, VoicemailStatus.edit(getContext(), mPhone)); } @Override @@ -74,6 +78,7 @@ 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 68ce0122e..0b3e090bf 100644 --- a/java/com/android/voicemail/impl/sync/SyncTask.java +++ b/java/com/android/voicemail/impl/sync/SyncTask.java @@ -37,14 +37,17 @@ 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) { + public static void start(Context context, PhoneAccountHandle phone, String syncType) { Intent intent = BaseTask.createIntent(context, SyncTask.class, phone); intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phone); + intent.putExtra(EXTRA_SYNC_TYPE, syncType); context.sendBroadcast(intent); } @@ -59,12 +62,13 @@ 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, mPhone, null, mRetryPolicy.getVoicemailStatusEditor()); + service.sync(this, mSyncType, mPhone, null, mRetryPolicy.getVoicemailStatusEditor()); } @Override @@ -72,6 +76,7 @@ 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 d8f06db47..f2b2036b5 100644 --- a/java/com/android/voicemail/impl/sync/UploadTask.java +++ b/java/com/android/voicemail/impl/sync/UploadTask.java @@ -63,6 +63,10 @@ public class UploadTask extends BaseTask { return; } service.sync( - this, phoneAccountHandle, null, VoicemailStatus.edit(getContext(), phoneAccountHandle)); + this, + OmtpVvmSyncService.SYNC_UPLOAD_ONLY, + 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 316e1ca61..9b295dbb7 100644 --- a/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java +++ b/java/com/android/voicemail/impl/sync/VoicemailsQueryHelper.java @@ -49,6 +49,8 @@ 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"; @@ -63,6 +65,15 @@ public class VoicemailsQueryHelper { } /** + * Get all the local read voicemails that have not been synced to the server. + * + * @return A list of read voicemails. + */ + public List<Voicemail> getReadVoicemails(@NonNull PhoneAccountHandle phoneAccountHandle) { + return getLocalVoicemails(phoneAccountHandle, READ_SELECTION); + } + + /** * Get all the locally deleted voicemails that have not been synced to the server. * * @return A list of deleted voicemails. diff --git a/java/com/android/voicemail/impl/sync/VvmNetworkRequestCallback.java b/java/com/android/voicemail/impl/sync/VvmNetworkRequestCallback.java index 068b19b70..067eff803 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(twyen): b/32637799 this is hidden, do we really need this? + // TODO: b/32637799 this is hidden, do we really need this? mResultReceived = true; onFailed(NETWORK_REQUEST_FAILED_TIMEOUT); } |