1c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi/*
2c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * Copyright (C) 2016 The Android Open Source Project
3c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi *
4c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * Licensed under the Apache License, Version 2.0 (the "License");
5c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * you may not use this file except in compliance with the License.
6c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * You may obtain a copy of the License at
7c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi *
8c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi *      http://www.apache.org/licenses/LICENSE-2.0
9c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi *
10c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * Unless required by applicable law or agreed to in writing, software
11c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * distributed under the License is distributed on an "AS IS" BASIS,
12c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * See the License for the specific language governing permissions and
14c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * limitations under the License
15c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi */
16c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
17c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmipackage com.android.dialer.voicemail;
18c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
19c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport com.android.contacts.common.testing.NeededForTesting;
20c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport com.android.dialer.calllog.CallLogQuery;
21c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport com.android.dialer.database.VoicemailArchiveContract;
22c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport com.android.dialer.util.AsyncTaskExecutor;
23c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport com.android.dialer.util.AsyncTaskExecutors;
24c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport com.google.common.base.Preconditions;
25c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport com.google.common.io.ByteStreams;
26c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
27c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.content.ContentResolver;
28c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.content.ContentUris;
29c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.content.ContentValues;
30c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.database.Cursor;
31c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.net.Uri;
32c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.os.AsyncTask;
33c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.provider.CallLog;
34c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.provider.VoicemailContract;
35c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport android.util.Log;
36c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport com.android.common.io.MoreCloseables;
37c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
38c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport java.io.IOException;
39c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport java.io.InputStream;
40c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport java.io.OutputStream;
41c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
42c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmiimport javax.annotation.Nullable;
43c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
44c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi/**
45c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi * Class containing asynchronous tasks for voicemails.
46c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi */
47c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi@NeededForTesting
48c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmipublic class VoicemailAsyncTaskUtil {
49c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private static final String TAG = "VoicemailAsyncTaskUtil";
50c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
51c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    /** The enumeration of {@link AsyncTask} objects we use in this class. */
52c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    public enum Tasks {
53c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        GET_VOICEMAIL_FILE_PATH,
54c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        SET_VOICEMAIL_ARCHIVE_STATUS,
55c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        ARCHIVE_VOICEMAIL_CONTENT
56c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
57c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
58c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @NeededForTesting
59c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    public interface OnArchiveVoicemailListener {
60c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        /**
61c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         * Called after the voicemail has been archived.
62c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         *
63c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         * @param archivedVoicemailUri the URI of the archived voicemail
64c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         */
65c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        void onArchiveVoicemail(@Nullable Uri archivedVoicemailUri);
66c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
67c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
68c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @NeededForTesting
69c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    public interface OnSetVoicemailArchiveStatusListener {
70c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        /**
71c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         * Called after the voicemail archived_by_user column is updated.
72c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         *
73c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         * @param success whether the update was successful or not
74c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         */
75c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        void onSetVoicemailArchiveStatus(boolean success);
76c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
77c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
78c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @NeededForTesting
79c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    public interface OnGetArchivedVoicemailFilePathListener {
80c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        /**
81c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         * Called after the voicemail file path is obtained.
82c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         *
83c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         * @param filePath the file path of the archived voicemail
84c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi         */
85c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        void onGetArchivedVoicemailFilePath(@Nullable String filePath);
86c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
87c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
88c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private final ContentResolver mResolver;
89c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private final AsyncTaskExecutor mAsyncTaskExecutor;
90c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
91c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @NeededForTesting
92c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    public VoicemailAsyncTaskUtil(ContentResolver contentResolver) {
93c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        mResolver = Preconditions.checkNotNull(contentResolver);
94c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        mAsyncTaskExecutor = AsyncTaskExecutors.createThreadPoolExecutor();
95c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
96c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
97c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    /**
98c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * Returns the archived voicemail file path.
99c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     */
100c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @NeededForTesting
101c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    public void getVoicemailFilePath(
102c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            final OnGetArchivedVoicemailFilePathListener listener,
103c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            final Uri voicemailUri) {
104c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        Preconditions.checkNotNull(listener);
105c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        Preconditions.checkNotNull(voicemailUri);
106c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        mAsyncTaskExecutor.submit(Tasks.GET_VOICEMAIL_FILE_PATH,
107c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                new AsyncTask<Void, Void, String>() {
108c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    @Nullable
109c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    @Override
110c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    protected String doInBackground(Void... params) {
111c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        try (Cursor cursor = mResolver.query(voicemailUri,
112c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                new String[]{VoicemailArchiveContract.VoicemailArchive._DATA},
113c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                null, null, null)) {
114c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            if (hasContent(cursor)) {
115c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                return cursor.getString(cursor.getColumnIndex(
116c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                        VoicemailArchiveContract.VoicemailArchive._DATA));
117c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            }
118c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        }
119c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        return null;
120c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    }
121c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
122c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    @Override
123c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    protected void onPostExecute(String filePath) {
124c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        listener.onGetArchivedVoicemailFilePath(filePath);
125c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    }
126c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                });
127c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
128c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
129c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    /**
130c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * Updates the archived_by_user flag of the archived voicemail.
131c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     */
132c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @NeededForTesting
133c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    public void setVoicemailArchiveStatus(
134c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            final OnSetVoicemailArchiveStatusListener listener,
135c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            final Uri voicemailUri,
136c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            final boolean archivedByUser) {
137c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        Preconditions.checkNotNull(listener);
138c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        Preconditions.checkNotNull(voicemailUri);
139c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        mAsyncTaskExecutor.submit(Tasks.SET_VOICEMAIL_ARCHIVE_STATUS,
140c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                new AsyncTask<Void, Void, Boolean>() {
141c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    @Override
142c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    protected Boolean doInBackground(Void... params) {
143c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        ContentValues values = new ContentValues(1);
144c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED,
145c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                archivedByUser);
146c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        return mResolver.update(voicemailUri, values, null, null) > 0;
147c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    }
148c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
149c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    @Override
150c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    protected void onPostExecute(Boolean success) {
151c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        listener.onSetVoicemailArchiveStatus(success);
152c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    }
153c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                });
154c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
155c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
156c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    /**
157c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * Checks if a voicemail has already been archived, if so, return the previously archived URI.
158c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * Otherwise, copy the voicemail information to the local dialer database. If archive was
159c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * successful, archived voicemail URI is returned to listener, otherwise null.
160c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     */
161c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @NeededForTesting
162c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    public void archiveVoicemailContent(
163c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            final OnArchiveVoicemailListener listener,
164c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            final Uri voicemailUri) {
165c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        Preconditions.checkNotNull(listener);
166c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        Preconditions.checkNotNull(voicemailUri);
167c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        mAsyncTaskExecutor.submit(Tasks.ARCHIVE_VOICEMAIL_CONTENT,
168c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                new AsyncTask<Void, Void, Uri>() {
169c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    @Nullable
170c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    @Override
171c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    protected Uri doInBackground(Void... params) {
172c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        Uri archivedVoicemailUri = getArchivedVoicemailUri(voicemailUri);
173c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
174c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        // If previously archived, return uri, otherwise archive everything.
175c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        if (archivedVoicemailUri != null) {
176c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            return archivedVoicemailUri;
177c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        }
178c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
179c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        // Combine call log and voicemail content info.
180c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        ContentValues values = getVoicemailContentValues(voicemailUri);
181c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        if (values == null) {
182c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            return null;
183c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        }
184c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
185c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        Uri insertedVoicemailUri = mResolver.insert(
186c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                VoicemailArchiveContract.VoicemailArchive.CONTENT_URI, values);
187c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        if (insertedVoicemailUri == null) {
188c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            return null;
189c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        }
190c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
191c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        // Copy voicemail content to a new file.
192c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        boolean copiedFile = false;
193c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        try (InputStream inputStream = mResolver.openInputStream(voicemailUri);
194c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                             OutputStream outputStream =
195c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                     mResolver.openOutputStream(insertedVoicemailUri)) {
196c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            if (inputStream != null && outputStream != null) {
197c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                ByteStreams.copy(inputStream, outputStream);
198c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                copiedFile = true;
199c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                return insertedVoicemailUri;
200c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            }
201c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        } catch (IOException e) {
202c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            Log.w(TAG, "Failed to copy voicemail content to new file: "
203c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                    + e.toString());
204c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        } finally {
205c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            if (!copiedFile) {
206c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                // Roll back insert if the voicemail content was not copied.
207c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                mResolver.delete(insertedVoicemailUri, null, null);
208c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                            }
209c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        }
210c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        return null;
211c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    }
212c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
213c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    @Override
214c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    protected void onPostExecute(Uri archivedVoicemailUri) {
215c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        listener.onArchiveVoicemail(archivedVoicemailUri);
216c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                    }
217c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                });
218c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
219c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
220c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    /**
221c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * Helper method to get the archived URI of a voicemail.
222c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     *
223c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * @param voicemailUri a {@link android.provider.VoicemailContract.Voicemails#CONTENT_URI} URI.
224c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * @return the URI of the archived voicemail or {@code null}
225c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     */
226c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @Nullable
227c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private Uri getArchivedVoicemailUri(Uri voicemailUri) {
228c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        try (Cursor cursor = getArchiveExistsCursor(voicemailUri)) {
229c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            if (hasContent(cursor)) {
230c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                return VoicemailArchiveContract.VoicemailArchive
231c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        .buildWithId(cursor.getInt(cursor.getColumnIndex(
232c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                VoicemailArchiveContract.VoicemailArchive._ID)));
233c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            }
234c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        }
235c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        return null;
236c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
237c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
238c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    /**
239c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * Helper method to make a copy of all the values needed to display a voicemail.
240c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     *
241c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * @param voicemailUri a {@link VoicemailContract.Voicemails#CONTENT_URI} URI.
242c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     * @return the combined call log and voicemail values for the given URI, or {@code null}
243c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi     */
244c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @Nullable
245c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private ContentValues getVoicemailContentValues(Uri voicemailUri) {
246c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        try (Cursor callLogInfo = getCallLogInfoCursor(voicemailUri);
247c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi             Cursor contentInfo = getContentInfoCursor(voicemailUri)) {
248c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
249c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            if (hasContent(callLogInfo) && hasContent(contentInfo)) {
250c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                // Create values to insert into database.
251c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                ContentValues values = new ContentValues();
252c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
253c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                // Insert voicemail call log info.
254c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.COUNTRY_ISO,
255c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.COUNTRY_ISO));
256c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.GEOCODED_LOCATION,
257c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.GEOCODED_LOCATION));
258c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NAME,
259c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.CACHED_NAME));
260c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_TYPE,
261c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getInt(CallLogQuery.CACHED_NUMBER_TYPE));
262c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_LABEL,
263c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.CACHED_NUMBER_LABEL));
264c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_LOOKUP_URI,
265c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.CACHED_LOOKUP_URI));
266c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_MATCHED_NUMBER,
267c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.CACHED_MATCHED_NUMBER));
268c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NORMALIZED_NUMBER,
269c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.CACHED_NORMALIZED_NUMBER));
270c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_FORMATTED_NUMBER,
271c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.CACHED_FORMATTED_NUMBER));
272c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER_PRESENTATION,
273c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getInt(CallLogQuery.NUMBER_PRESENTATION));
274c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_COMPONENT_NAME,
275c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME));
276c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_ID,
277c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.ACCOUNT_ID));
278c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.FEATURES,
279c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getInt(CallLogQuery.FEATURES));
280c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_PHOTO_URI,
281c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        callLogInfo.getString(CallLogQuery.CACHED_PHOTO_URI));
282c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
283c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                // Insert voicemail content info.
284c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.SERVER_ID,
285c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        contentInfo.getInt(contentInfo.getColumnIndex(
286c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                VoicemailContract.Voicemails._ID)));
287c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER,
288c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        contentInfo.getString(contentInfo.getColumnIndex(
289c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                VoicemailContract.Voicemails.NUMBER)));
290c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.DATE,
291c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        contentInfo.getLong(contentInfo.getColumnIndex(
292c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                VoicemailContract.Voicemails.DATE)));
293c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.DURATION,
294c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        contentInfo.getLong(contentInfo.getColumnIndex(
295c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                VoicemailContract.Voicemails.DURATION)));
296c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.MIME_TYPE,
297c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        contentInfo.getString(contentInfo.getColumnIndex(
298c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                VoicemailContract.Voicemails.MIME_TYPE)));
299c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.TRANSCRIPTION,
300c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        contentInfo.getString(contentInfo.getColumnIndex(
301c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                                VoicemailContract.Voicemails.TRANSCRIPTION)));
302c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
303c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                // Achived is false by default because it is updated after insertion.
304c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED, false);
305c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
306c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                return values;
307c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi            }
308c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        }
309c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        return null;
310c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
311c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
312c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private boolean hasContent(@Nullable Cursor cursor) {
313c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        return cursor != null && cursor.moveToFirst();
314c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
315c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
316c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @Nullable
317c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private Cursor getCallLogInfoCursor(Uri voicemailUri) {
318c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        return mResolver.query(
319c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
320c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        ContentUris.parseId(voicemailUri)),
321c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                CallLogQuery._PROJECTION, null, null, null);
322c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
323c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
324c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @Nullable
325c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private Cursor getContentInfoCursor(Uri voicemailUri) {
326c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        return mResolver.query(voicemailUri,
327c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                new String[] {
328c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        VoicemailContract.Voicemails._ID,
329c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        VoicemailContract.Voicemails.NUMBER,
330c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        VoicemailContract.Voicemails.DATE,
331c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        VoicemailContract.Voicemails.DURATION,
332c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        VoicemailContract.Voicemails.MIME_TYPE,
333c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        VoicemailContract.Voicemails.TRANSCRIPTION,
334c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                }, null, null, null);
335c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
336c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi
337c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    @Nullable
338c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    private Cursor getArchiveExistsCursor(Uri voicemailUri) {
339c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi        return mResolver.query(VoicemailArchiveContract.VoicemailArchive.CONTENT_URI,
340c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                new String[] {VoicemailArchiveContract.VoicemailArchive._ID},
341c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                VoicemailArchiveContract.VoicemailArchive.SERVER_ID + "="
342c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                        + ContentUris.parseId(voicemailUri),
343c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                null,
344c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi                null);
345c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi    }
346c70343becd3734fd380e0d20f05b7605e6233d43Sarmad Hashmi}
347