summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarmad Hashmi <mhashmi@google.com>2016-03-04 19:51:03 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-03-04 19:51:03 +0000
commitaf04b7b8d5bad8998f875ee0a28df36d5b6e97c5 (patch)
tree9fd03026dabe7c5b0a0696da0db89a8b7de78c5c
parent5054493a465991ad2b8d4b1d885a66810e08414a (diff)
parentee8f5a3c0d865bee5d54ef486fed063f08ceb818 (diff)
Merge "Add files for voicemail archive tab." into nyc-dev
am: ee8f5a3c0d * commit 'ee8f5a3c0d865bee5d54ef486fed063f08ceb818': Add files for voicemail archive tab.
-rw-r--r--AndroidManifest.xml5
-rw-r--r--src/com/android/dialer/DialtactsActivity.java5
-rw-r--r--src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java25
-rw-r--r--src/com/android/dialer/database/VoicemailArchiveProvider.java10
-rw-r--r--src/com/android/dialer/voicemail/VoicemailArchiveActivity.java160
-rw-r--r--src/com/android/dialer/voicemail/VoicemailArchivePlaybackPresenter.java85
-rw-r--r--src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java194
-rw-r--r--src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java281
-rw-r--r--tests/src/com/android/dialer/voicemail/VoicemailActivityInstrumentationTestCase2.java212
-rw-r--r--tests/src/com/android/dialer/voicemail/VoicemailArchiveTest.java118
-rw-r--r--tests/src/com/android/dialer/voicemail/VoicemailPlaybackTest.java206
11 files changed, 1037 insertions, 264 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d23fca617..06f579515 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -158,6 +158,11 @@
android:exported="false">
</activity>
+ <activity android:name="com.android.dialer.voicemail.VoicemailArchiveActivity"
+ android:label="@string/voicemail_archive_activity_title"
+ android:theme="@style/DialtactsThemeWithoutActionBarOverlay">
+ </activity>
+
<activity android:name="com.android.dialer.calllog.CallLogActivity"
android:label="@string/call_log_activity_title"
android:theme="@style/DialtactsThemeWithoutActionBarOverlay"
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index d12cf24df..e775b0ad1 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -16,6 +16,7 @@
package com.android.dialer;
+import com.android.dialer.voicemail.VoicemailArchiveActivity;
import com.google.common.annotations.VisibleForTesting;
import android.app.Fragment;
@@ -690,6 +691,10 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
handleMenuSettings();
Logger.logScreenView(ScreenEvent.SETTINGS, this);
return true;
+ } else if (resId == R.id.menu_archive) {
+ final Intent intent = new Intent(this, VoicemailArchiveActivity.class);
+ startActivity(intent);
+ return true;
}
return false;
}
diff --git a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
index 982591814..13de0775d 100644
--- a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
+++ b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
@@ -16,6 +16,7 @@
package com.android.dialer.calllog;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +33,7 @@ import com.android.contacts.common.GeoUtil;
import com.android.contacts.common.util.PermissionsUtil;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.PhoneCallDetails;
+import com.android.dialer.database.VoicemailArchiveContract;
import com.android.dialer.util.AppCompatConstants;
import com.android.dialer.util.AsyncTaskExecutor;
import com.android.dialer.util.AsyncTaskExecutors;
@@ -413,16 +415,16 @@ public class CallLogAsyncTaskUtil {
}
/**
- * Updates the duration of a voicemail call log entry.
+ * Updates the duration of a voicemail call log entry if the duration given is greater than 0,
+ * and if if the duration currently in the database is less than or equal to 0 (non-existent).
*/
public static void updateVoicemailDuration(
final Context context,
final Uri voicemailUri,
- final int duration) {
- if (!PermissionsUtil.hasPhonePermissions(context)) {
+ final long duration) {
+ if (duration <= 0 || !PermissionsUtil.hasPhonePermissions(context)) {
return;
}
-
if (sAsyncTaskExecutor == null) {
initTaskExecutor();
}
@@ -430,9 +432,18 @@ public class CallLogAsyncTaskUtil {
sAsyncTaskExecutor.submit(Tasks.UPDATE_DURATION, new AsyncTask<Void, Void, Void>() {
@Override
public Void doInBackground(Void... params) {
- ContentValues values = new ContentValues(1);
- values.put(CallLog.Calls.DURATION, duration);
- context.getContentResolver().update(voicemailUri, values, null, null);
+ ContentResolver contentResolver = context.getContentResolver();
+ Cursor cursor = contentResolver.query(
+ voicemailUri,
+ new String[] { VoicemailArchiveContract.VoicemailArchive.DURATION },
+ null, null, null);
+ if (cursor != null && cursor.moveToFirst() && cursor.getInt(
+ cursor.getColumnIndex(
+ VoicemailArchiveContract.VoicemailArchive.DURATION)) <= 0) {
+ ContentValues values = new ContentValues(1);
+ values.put(CallLog.Calls.DURATION, duration);
+ context.getContentResolver().update(voicemailUri, values, null, null);
+ }
return null;
}
});
diff --git a/src/com/android/dialer/database/VoicemailArchiveProvider.java b/src/com/android/dialer/database/VoicemailArchiveProvider.java
index ae73670b8..79b7a7630 100644
--- a/src/com/android/dialer/database/VoicemailArchiveProvider.java
+++ b/src/com/android/dialer/database/VoicemailArchiveProvider.java
@@ -115,11 +115,13 @@ public class VoicemailArchiveProvider extends ContentProvider {
// Create the directory for archived voicemails if it doesn't already exist
File directory = new File(getFilesDir(), VOICEMAIL_FOLDER);
directory.mkdirs();
-
- // Update the row's _data column with a file path in the voicemails folder
Uri newUri = ContentUris.withAppendedId(uri, id);
- File voicemailFile = new File(directory, Long.toString(id));
- values.put(VoicemailArchiveContract.VoicemailArchive._DATA, voicemailFile.getPath());
+
+ // Create new file only if path is not provided to one
+ if (!values.containsKey(VoicemailArchiveContract.VoicemailArchive._DATA)) {
+ File voicemailFile = new File(directory, Long.toString(id));
+ values.put(VoicemailArchiveContract.VoicemailArchive._DATA, voicemailFile.getPath());
+ }
update(newUri, values, null, null);
return newUri;
}
diff --git a/src/com/android/dialer/voicemail/VoicemailArchiveActivity.java b/src/com/android/dialer/voicemail/VoicemailArchiveActivity.java
new file mode 100644
index 000000000..16b947cd3
--- /dev/null
+++ b/src/com/android/dialer/voicemail/VoicemailArchiveActivity.java
@@ -0,0 +1,160 @@
+/*
+ * 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.dialer.voicemail;
+
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.support.v7.app.ActionBar;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.android.contacts.common.GeoUtil;
+import com.android.dialer.DialtactsActivity;
+import com.android.dialer.R;
+import com.android.dialer.TransactionSafeActivity;
+import com.android.dialer.calllog.CallLogAdapter;
+import com.android.dialer.calllog.CallLogQueryHandler;
+import com.android.dialer.calllog.ContactInfoHelper;
+import com.android.dialer.widget.EmptyContentView;
+import com.android.dialerbind.ObjectFactory;
+
+/**
+ * This activity manages all the voicemails archived by the user.
+ */
+public class VoicemailArchiveActivity extends TransactionSafeActivity
+ implements CallLogAdapter.CallFetcher, CallLogQueryHandler.Listener {
+ private RecyclerView mRecyclerView;
+ private LinearLayoutManager mLayoutManager;
+ private EmptyContentView mEmptyListView;
+ private CallLogAdapter mAdapter;
+ private VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
+ private CallLogQueryHandler mCallLogQueryHandler;
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (!isSafeToCommitTransactions()) {
+ return true;
+ }
+
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ Intent intent = new Intent(this, DialtactsActivity.class);
+ // Clears any activities between VoicemailArchiveActivity and DialtactsActivity
+ // on the activity stack and reuses the existing instance of DialtactsActivity
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.call_log_fragment);
+
+ // Make window opaque to reduce overdraw
+ getWindow().setBackgroundDrawable(null);
+
+ ActionBar actionBar = getSupportActionBar();
+ actionBar.setDisplayShowHomeEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowTitleEnabled(true);
+ actionBar.setElevation(0);
+
+ mCallLogQueryHandler = new CallLogQueryHandler(this, getContentResolver(), this);
+ mVoicemailPlaybackPresenter = VoicemailArchivePlaybackPresenter
+ .getInstance(this, savedInstanceState);
+
+ mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
+ mRecyclerView.setHasFixedSize(true);
+ mLayoutManager = new LinearLayoutManager(this);
+ mRecyclerView.setLayoutManager(mLayoutManager);
+ mEmptyListView = (EmptyContentView) findViewById(R.id.empty_list_view);
+ mEmptyListView.setDescription(R.string.voicemail_archive_empty);
+ mEmptyListView.setImage(R.drawable.empty_call_log);
+
+ mAdapter = ObjectFactory.newCallLogAdapter(
+ this,
+ this,
+ new ContactInfoHelper(this, GeoUtil.getCurrentCountryIso(this)),
+ mVoicemailPlaybackPresenter,
+ CallLogAdapter.ACTIVITY_TYPE_ARCHIVE);
+ mRecyclerView.setAdapter(mAdapter);
+ fetchCalls();
+ }
+
+ @Override
+ protected void onPause() {
+ mVoicemailPlaybackPresenter.onPause();
+ mAdapter.onPause();
+ super.onPause();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mAdapter.onResume();
+ mVoicemailPlaybackPresenter.onResume();
+ }
+
+ @Override
+ public void onDestroy() {
+ mVoicemailPlaybackPresenter.onDestroy();
+ mAdapter.changeCursor(null);
+ super.onDestroy();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mVoicemailPlaybackPresenter.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void fetchCalls() {
+ mCallLogQueryHandler.fetchVoicemailArchive();
+ }
+
+ @Override
+ public void onVoicemailStatusFetched(Cursor statusCursor) {
+ // Do nothing
+ }
+
+ @Override
+ public void onVoicemailUnreadCountFetched(Cursor cursor) {
+ // Do nothing
+ }
+
+ @Override
+ public void onMissedCallsUnreadCountFetched(Cursor cursor) {
+ // Do nothing
+ }
+
+ @Override
+ public boolean onCallsFetched(Cursor cursor) {
+ mAdapter.changeCursorVoicemail(cursor);
+ boolean showListView = cursor != null && cursor.getCount() > 0;
+ mRecyclerView.setVisibility(showListView ? View.VISIBLE : View.GONE);
+ mEmptyListView.setVisibility(!showListView ? View.VISIBLE : View.GONE);
+ return true;
+ }
+}
diff --git a/src/com/android/dialer/voicemail/VoicemailArchivePlaybackPresenter.java b/src/com/android/dialer/voicemail/VoicemailArchivePlaybackPresenter.java
new file mode 100644
index 000000000..050b8ac62
--- /dev/null
+++ b/src/com/android/dialer/voicemail/VoicemailArchivePlaybackPresenter.java
@@ -0,0 +1,85 @@
+/*
+ * 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.dialer.voicemail;
+
+import android.app.Activity;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import com.android.dialer.calllog.CallLogAsyncTaskUtil;
+import com.android.dialer.database.VoicemailArchiveContract;
+import java.io.FileNotFoundException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Similar to the {@link VoicemailPlaybackPresenter}, but for the archive voicemail tab. It checks
+ * whether the voicemail file exists locally before preparing it.
+ */
+public class VoicemailArchivePlaybackPresenter extends VoicemailPlaybackPresenter {
+ private static final String TAG = "VMPlaybackPresenter";
+ private static VoicemailPlaybackPresenter sInstance;
+
+ public VoicemailArchivePlaybackPresenter(Activity activity) {
+ super(activity);
+ }
+
+ public static VoicemailPlaybackPresenter getInstance(
+ Activity activity, Bundle savedInstanceState) {
+ if (sInstance == null) {
+ sInstance = new VoicemailArchivePlaybackPresenter(activity);
+ }
+
+ sInstance.init(activity, savedInstanceState);
+ return sInstance;
+ }
+
+ @Override
+ protected void checkForContent(final OnContentCheckedListener callback) {
+ mAsyncTaskExecutor.submit(Tasks.CHECK_FOR_CONTENT, new AsyncTask<Void, Void, Boolean>() {
+ @Override
+ public Boolean doInBackground(Void... params) {
+ try {
+ // Check if the _data column of the archived voicemail is valid
+ if (mVoicemailUri != null) {
+ mContext.getContentResolver().openInputStream(mVoicemailUri);
+ return true;
+ }
+ } catch (FileNotFoundException e) {
+ Log.d(TAG, "Voicemail file not found for " + mVoicemailUri);
+ handleError(e);
+ }
+ return false;
+ }
+
+ @Override
+ public void onPostExecute(Boolean hasContent) {
+ callback.onContentChecked(hasContent);
+ }
+ });
+ }
+
+ @Override
+ protected boolean requestContent(int code) {
+ if (mContext == null || mVoicemailUri == null) {
+ return false;
+ }
+ prepareContent();
+ return true;
+ }
+}
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java b/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
index 19b592d50..436fc7952 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
@@ -16,40 +16,44 @@
package com.android.dialer.voicemail;
-import android.app.Activity;
-import android.app.Fragment;
+import android.content.ContentUris;
import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
import android.graphics.drawable.Drawable;
-import android.media.MediaPlayer;
import android.net.Uri;
-import android.os.Bundle;
+import android.os.AsyncTask;
import android.os.Handler;
-import android.os.PowerManager;
-import android.provider.VoicemailContract;
import android.util.AttributeSet;
-import android.util.Log;
import android.support.design.widget.Snackbar;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.common.io.MoreCloseables;
import com.android.dialer.PhoneCallDetails;
import com.android.dialer.R;
import com.android.dialer.calllog.CallLogAsyncTaskUtil;
+import com.android.dialer.database.VoicemailArchiveContract;
+import com.android.dialer.database.VoicemailArchiveContract.VoicemailArchive;
+import com.android.dialer.util.AsyncTaskExecutor;
+import com.android.dialer.util.AsyncTaskExecutors;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledExecutorService;
+import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.NotThreadSafe;
import javax.annotation.concurrent.ThreadSafe;
@@ -67,6 +71,12 @@ public class VoicemailPlaybackLayout extends LinearLayout
CallLogAsyncTaskUtil.CallLogAsyncTaskListener {
private static final String TAG = VoicemailPlaybackLayout.class.getSimpleName();
private static final int VOICEMAIL_DELETE_DELAY_MS = 3000;
+ private static final int VOICEMAIL_ARCHIVE_DELAY_MS = 3000;
+
+ /** The enumeration of {@link AsyncTask} objects we use in this class. */
+ public enum Tasks {
+ QUERY_ARCHIVED_STATUS
+ }
/**
* Controls the animation of the playback slider.
@@ -202,7 +212,7 @@ public class VoicemailPlaybackLayout extends LinearLayout
final Runnable deleteCallback = new Runnable() {
@Override
public void run() {
- if (mVoicemailUri == deleteUri) {
+ if (Objects.equals(deleteUri, mVoicemailUri)) {
CallLogAsyncTaskUtil.deleteVoicemail(mContext, deleteUri,
VoicemailPlaybackLayout.this);
}
@@ -214,8 +224,6 @@ public class VoicemailPlaybackLayout extends LinearLayout
// window.
handler.postDelayed(deleteCallback, VOICEMAIL_DELETE_DELAY_MS + 50);
- final int actionTextColor =
- mContext.getResources().getColor(R.color.dialer_snackbar_action_text_color);
Snackbar.make(VoicemailPlaybackLayout.this, R.string.snackbar_voicemail_deleted,
Snackbar.LENGTH_LONG)
.setDuration(VOICEMAIL_DELETE_DELAY_MS)
@@ -227,21 +235,44 @@ public class VoicemailPlaybackLayout extends LinearLayout
handler.removeCallbacks(deleteCallback);
}
})
- .setActionTextColor(actionTextColor)
+ .setActionTextColor(
+ mContext.getResources().getColor(
+ R.color.dialer_snackbar_action_text_color))
.show();
}
};
+ private final View.OnClickListener mArchiveButtonListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mPresenter == null || isArchiving(mVoicemailUri)) {
+ return;
+ }
+ mIsArchiving.add(mVoicemailUri);
+ mPresenter.pausePlayback();
+ updateArchiveUI(mVoicemailUri);
+ disableUiElements();
+ mPresenter.archiveContent(mVoicemailUri, true);
+ }
+ };
+
private Context mContext;
private VoicemailPlaybackPresenter mPresenter;
private Uri mVoicemailUri;
-
+ private final AsyncTaskExecutor mAsyncTaskExecutor =
+ AsyncTaskExecutors.createAsyncTaskExecutor();
private boolean mIsPlaying = false;
+ /**
+ * Keeps track of which voicemails are currently being archived in order to update the voicemail
+ * card UI every time a user opens a new card.
+ */
+ private static final ArrayList<Uri> mIsArchiving = new ArrayList<>();
private SeekBar mPlaybackSeek;
private ImageButton mStartStopButton;
private ImageButton mPlaybackSpeakerphone;
private ImageButton mDeleteButton;
+ private ImageButton mArchiveButton;
private TextView mStateText;
private TextView mPositionText;
private TextView mTotalDurationText;
@@ -256,7 +287,6 @@ public class VoicemailPlaybackLayout extends LinearLayout
public VoicemailPlaybackLayout(Context context, AttributeSet attrs) {
super(context, attrs);
-
mContext = context;
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -267,6 +297,8 @@ public class VoicemailPlaybackLayout extends LinearLayout
public void setPresenter(VoicemailPlaybackPresenter presenter, Uri voicemailUri) {
mPresenter = presenter;
mVoicemailUri = voicemailUri;
+ updateArchiveUI(mVoicemailUri);
+ updateArchiveButton(mVoicemailUri);
}
@Override
@@ -277,6 +309,7 @@ public class VoicemailPlaybackLayout extends LinearLayout
mStartStopButton = (ImageButton) findViewById(R.id.playback_start_stop);
mPlaybackSpeakerphone = (ImageButton) findViewById(R.id.playback_speakerphone);
mDeleteButton = (ImageButton) findViewById(R.id.delete_voicemail);
+ mArchiveButton =(ImageButton) findViewById(R.id.archive_voicemail);
mStateText = (TextView) findViewById(R.id.playback_state_text);
mPositionText = (TextView) findViewById(R.id.playback_position_text);
mTotalDurationText = (TextView) findViewById(R.id.total_duration_text);
@@ -285,6 +318,7 @@ public class VoicemailPlaybackLayout extends LinearLayout
mStartStopButton.setOnClickListener(mStartStopButtonListener);
mPlaybackSpeakerphone.setOnClickListener(mSpeakerphoneListener);
mDeleteButton.setOnClickListener(mDeleteButtonListener);
+ mArchiveButton.setOnClickListener(mArchiveButtonListener);
mPositionText.setText(formatAsMinutesAndSeconds(0));
mTotalDurationText.setText(formatAsMinutesAndSeconds(0));
@@ -358,7 +392,6 @@ public class VoicemailPlaybackLayout extends LinearLayout
mPositionText.setText(formatAsMinutesAndSeconds(seekBarPositionMs));
mTotalDurationText.setText(formatAsMinutesAndSeconds(durationMs));
- mStateText.setText(null);
}
@Override
@@ -386,6 +419,7 @@ public class VoicemailPlaybackLayout extends LinearLayout
@Override
public void enableUiElements() {
+ mDeleteButton.setEnabled(true);
mStartStopButton.setEnabled(true);
mPlaybackSeek.setEnabled(true);
mPlaybackSeek.setThumb(mVoicemailSeekHandleEnabled);
@@ -429,6 +463,134 @@ public class VoicemailPlaybackLayout extends LinearLayout
return String.format("%02d:%02d", minutes, seconds);
}
+ /**
+ * Called when a voicemail archive succeeded. If the expanded voicemail was being
+ * archived, update the card UI. Either way, display a snackbar linking user to archive.
+ */
+ @Override
+ public void onVoicemailArchiveSucceded(Uri voicemailUri) {
+ if (isArchiving(voicemailUri)) {
+ mIsArchiving.remove(voicemailUri);
+ if (Objects.equals(voicemailUri, mVoicemailUri)) {
+ onVoicemailArchiveResult();
+ hideArchiveButton();
+ }
+ }
+
+ Snackbar.make(this, R.string.snackbar_voicemail_archived,
+ Snackbar.LENGTH_LONG)
+ .setDuration(VOICEMAIL_ARCHIVE_DELAY_MS)
+ .setAction(R.string.snackbar_voicemail_archived_goto,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(mContext,
+ VoicemailArchiveActivity.class);
+ mContext.startActivity(intent);
+ }
+ })
+ .setActionTextColor(
+ mContext.getResources().getColor(R.color.dialer_snackbar_action_text_color))
+ .show();
+ }
+
+ /**
+ * If a voicemail archive failed, and the expanded card was being archived, update the card UI.
+ * Either way, display a toast saying the voicemail archive failed.
+ */
+ @Override
+ public void onVoicemailArchiveFailed(Uri voicemailUri) {
+ if (isArchiving(voicemailUri)) {
+ mIsArchiving.remove(voicemailUri);
+ if (Objects.equals(voicemailUri, mVoicemailUri)) {
+ onVoicemailArchiveResult();
+ }
+ }
+ String toastStr = mContext.getString(R.string.voicemail_archive_failed);
+ Toast.makeText(mContext, toastStr, Toast.LENGTH_SHORT).show();
+ }
+
+ public void hideArchiveButton() {
+ mArchiveButton.setVisibility(View.GONE);
+ mArchiveButton.setClickable(false);
+ mArchiveButton.setEnabled(false);
+ }
+
+ /**
+ * Whenever a voicemail archive succeeds or fails, clear the text displayed in the voicemail
+ * card.
+ */
+ private void onVoicemailArchiveResult() {
+ enableUiElements();
+ mStateText.setText(null);
+ mArchiveButton.setColorFilter(null);
+ }
+
+ /**
+ * Whether or not the voicemail with the given uri is being archived.
+ */
+ private boolean isArchiving(@Nullable Uri uri) {
+ return uri != null && mIsArchiving.contains(uri);
+ }
+
+ /**
+ * Show the proper text and hide the archive button if the voicemail is still being archived.
+ */
+ private void updateArchiveUI(@Nullable Uri voicemailUri) {
+ if (!Objects.equals(voicemailUri, mVoicemailUri)) {
+ return;
+ }
+ if (isArchiving(voicemailUri)) {
+ // If expanded card was in the middle of archiving, disable buttons and display message
+ disableUiElements();
+ mDeleteButton.setEnabled(false);
+ mArchiveButton.setColorFilter(getResources().getColor(R.color.setting_disabled_color));
+ mStateText.setText(getString(R.string.voicemail_archiving_content));
+ } else {
+ onVoicemailArchiveResult();
+ }
+ }
+
+ /**
+ * Hides the archive button if the voicemail has already been archived, shows otherwise.
+ * @param voicemailUri the URI of the voicemail for which the archive button needs to be updated
+ */
+ private void updateArchiveButton(@Nullable final Uri voicemailUri) {
+ if (voicemailUri == null ||
+ !Objects.equals(voicemailUri, mVoicemailUri) || isArchiving(voicemailUri) ||
+ Objects.equals(voicemailUri.getAuthority(),VoicemailArchiveContract.AUTHORITY)) {
+ return;
+ }
+ mAsyncTaskExecutor.submit(Tasks.QUERY_ARCHIVED_STATUS,
+ new AsyncTask<Void, Void, Boolean>() {
+ @Override
+ public Boolean doInBackground(Void... params) {
+ Cursor cursor = mContext.getContentResolver().query(VoicemailArchive.CONTENT_URI,
+ null, VoicemailArchive.SERVER_ID + "=" + ContentUris.parseId(mVoicemailUri)
+ + " AND " + VoicemailArchive.ARCHIVED + "= 1", null, null);
+ boolean archived = cursor != null && cursor.getCount() > 0;
+ cursor.close();
+ return archived;
+ }
+
+ @Override
+ public void onPostExecute(Boolean archived) {
+ if (!Objects.equals(voicemailUri, mVoicemailUri)) {
+ return;
+ }
+
+ if (archived) {
+ hideArchiveButton();
+ } else {
+ mArchiveButton.setVisibility(View.VISIBLE);
+ mArchiveButton.setClickable(true);
+ mArchiveButton.setEnabled(true);
+ }
+
+ }
+ });
+ }
+
@VisibleForTesting
public String getStateText() {
return mStateText.getText().toString();
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
index fcb35e57b..3151a5ea5 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
@@ -19,6 +19,9 @@ package com.android.dialer.voicemail;
import com.google.common.annotations.VisibleForTesting;
import android.app.Activity;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -30,20 +33,30 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
+import android.provider.CallLog;
import android.provider.VoicemailContract;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.WindowManager.LayoutParams;
-import com.android.common.io.MoreCloseables;
import com.android.dialer.calllog.CallLogAsyncTaskUtil;
+import com.android.dialer.calllog.CallLogQuery;
+import com.android.dialer.database.VoicemailArchiveContract;
import com.android.dialer.util.AsyncTaskExecutor;
import com.android.dialer.util.AsyncTaskExecutors;
-
+import com.android.common.io.MoreCloseables;
+import com.android.dialer.util.TelecomUtil;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.io.ByteStreams;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -81,6 +94,8 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
void setClipPosition(int clipPositionInMillis, int clipLengthInMillis);
void setFetchContentTimeout();
void setIsFetchingContent();
+ void onVoicemailArchiveSucceded(Uri voicemailUri);
+ void onVoicemailArchiveFailed(Uri voicemailUri);
void setPresenter(VoicemailPlaybackPresenter presenter, Uri voicemailUri);
void resetSeekBar();
}
@@ -95,10 +110,10 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
public enum Tasks {
CHECK_FOR_CONTENT,
CHECK_CONTENT_AFTER_CHANGE,
+ ARCHIVE_VOICEMAIL
}
- private interface OnContentCheckedListener {
-
+ protected interface OnContentCheckedListener {
void onContentChecked(boolean hasContent);
}
@@ -123,6 +138,8 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
VoicemailPlaybackPresenter.class.getName() + ".CLIP_POSITION_KEY";
private static final String IS_SPEAKERPHONE_ON_KEY =
VoicemailPlaybackPresenter.class.getName() + ".IS_SPEAKER_PHONE_ON";
+ public static final int PLAYBACK_REQUEST = 0;
+ public static final int ARCHIVE_REQUEST = 1;
/**
* The most recently cached duration. We cache this since we don't want to keep requesting it
@@ -134,11 +151,11 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
private static VoicemailPlaybackPresenter sInstance;
private Activity mActivity;
- private Context mContext;
+ protected Context mContext;
private PlaybackView mView;
- private Uri mVoicemailUri;
+ protected Uri mVoicemailUri;
- private MediaPlayer mMediaPlayer;
+ protected MediaPlayer mMediaPlayer;
private int mPosition;
private boolean mIsPlaying;
// MediaPlayer crashes on some method calls if not prepared but does not have a method which
@@ -150,7 +167,7 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
private int mInitialOrientation;
// Used to run async tasks that need to interact with the UI.
- private AsyncTaskExecutor mAsyncTaskExecutor;
+ protected AsyncTaskExecutor mAsyncTaskExecutor;
private static ScheduledExecutorService mScheduledExecutorService;
/**
* Used to handle the result of a successful or time-out fetch result.
@@ -158,6 +175,7 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
* This variable is thread-contained, accessed only on the ui thread.
*/
private FetchResultHandler mFetchResultHandler;
+ private final List<FetchResultHandler> mArchiveResultHandlers = new ArrayList<>();
private Handler mHandler = new Handler();
private PowerManager.WakeLock mProximityWakeLock;
private VoicemailAudioManager mVoicemailAudioManager;
@@ -186,11 +204,10 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
/**
* Initialize variables which are activity-independent and state-independent.
*/
- private VoicemailPlaybackPresenter(Activity activity) {
+ protected VoicemailPlaybackPresenter(Activity activity) {
Context context = activity.getApplicationContext();
mAsyncTaskExecutor = AsyncTaskExecutors.createAsyncTaskExecutor();
mVoicemailAudioManager = new VoicemailAudioManager(context, this);
-
PowerManager powerManager =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
@@ -202,7 +219,7 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
/**
* Update variables which are activity-dependent or state-dependent.
*/
- private void init(Activity activity, Bundle savedInstanceState) {
+ protected void init(Activity activity, Bundle savedInstanceState) {
mActivity = activity;
mContext = activity;
@@ -274,11 +291,9 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
public void onContentChecked(boolean hasContent) {
if (hasContent) {
prepareContent();
- } else {
- if (mView != null) {
- mView.resetSeekBar();
- mView.setClipPosition(0, mDuration.get());
- }
+ } else if (mView != null) {
+ mView.resetSeekBar();
+ mView.setClipPosition(0, mDuration.get());
}
}
});
@@ -377,6 +392,13 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
mScheduledExecutorService = null;
}
+ if (!mArchiveResultHandlers.isEmpty()) {
+ for (FetchResultHandler fetchResultHandler : mArchiveResultHandlers) {
+ fetchResultHandler.destroy();
+ }
+ mArchiveResultHandlers.clear();
+ }
+
if (mFetchResultHandler != null) {
mFetchResultHandler.destroy();
mFetchResultHandler = null;
@@ -386,7 +408,7 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
/**
* Checks to see if we have content available for this voicemail.
*/
- private void checkForContent(final OnContentCheckedListener callback) {
+ protected void checkForContent(final OnContentCheckedListener callback) {
mAsyncTaskExecutor.submit(Tasks.CHECK_FOR_CONTENT, new AsyncTask<Void, Void, Boolean>() {
@Override
public Boolean doInBackground(Void... params) {
@@ -438,18 +460,26 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
*
* @return whether issued request to fetch content
*/
- private boolean requestContent() {
+ protected boolean requestContent(int code) {
if (mContext == null || mVoicemailUri == null) {
return false;
}
- if (mFetchResultHandler != null) {
- mFetchResultHandler.destroy();
- }
-
- mFetchResultHandler = new FetchResultHandler(new Handler(), mVoicemailUri);
+ FetchResultHandler tempFetchResultHandler =
+ new FetchResultHandler(new Handler(), mVoicemailUri, code);
- mView.setIsFetchingContent();
+ switch (code) {
+ case ARCHIVE_REQUEST:
+ mArchiveResultHandlers.add(tempFetchResultHandler);
+ break;
+ default:
+ if (mFetchResultHandler != null) {
+ mFetchResultHandler.destroy();
+ }
+ mView.setIsFetchingContent();
+ mFetchResultHandler = tempFetchResultHandler;
+ break;
+ }
// Send voicemail fetch request.
Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, mVoicemailUri);
@@ -461,14 +491,18 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
private class FetchResultHandler extends ContentObserver implements Runnable {
private AtomicBoolean mIsWaitingForResult = new AtomicBoolean(true);
private final Handler mFetchResultHandler;
+ private final Uri mVoicemailUri;
+ private final int mRequestCode;
+ private Uri mArchivedVoicemailUri;
- public FetchResultHandler(Handler handler, Uri voicemailUri) {
+ public FetchResultHandler(Handler handler, Uri uri, int code) {
super(handler);
mFetchResultHandler = handler;
-
+ mRequestCode = code;
+ mVoicemailUri = uri;
if (mContext != null) {
mContext.getContentResolver().registerContentObserver(
- voicemailUri, false, this);
+ mVoicemailUri, false, this);
mFetchResultHandler.postDelayed(this, FETCH_CONTENT_TIMEOUT_MS);
}
}
@@ -481,7 +515,11 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
if (mIsWaitingForResult.getAndSet(false) && mContext != null) {
mContext.getContentResolver().unregisterContentObserver(this);
if (mView != null) {
- mView.setFetchContentTimeout();
+ if (mRequestCode == ARCHIVE_REQUEST) {
+ notifyUiOfArchiveResult(mVoicemailUri, false);
+ } else {
+ mView.setFetchContentTimeout();
+ }
}
}
}
@@ -497,9 +535,16 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
public void onChange(boolean selfChange) {
mAsyncTaskExecutor.submit(Tasks.CHECK_CONTENT_AFTER_CHANGE,
new AsyncTask<Void, Void, Boolean>() {
+
@Override
public Boolean doInBackground(Void... params) {
- return queryHasContent(mVoicemailUri);
+ boolean hasContent = queryHasContent(mVoicemailUri);
+ if (hasContent && mRequestCode == ARCHIVE_REQUEST) {
+ mArchivedVoicemailUri =
+ performArchiveVoicemailOnBackgroundThread(mVoicemailUri, true);
+ return mArchivedVoicemailUri != null;
+ }
+ return hasContent;
}
@Override
@@ -507,7 +552,12 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
if (hasContent && mContext != null && mIsWaitingForResult.getAndSet(false)) {
mContext.getContentResolver().unregisterContentObserver(
FetchResultHandler.this);
- prepareContent();
+ switch (mRequestCode) {
+ case ARCHIVE_REQUEST:
+ notifyUiOfArchiveResult(mVoicemailUri, true);
+ default:
+ prepareContent();
+ }
}
}
});
@@ -522,7 +572,7 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
* media player. If preparation is successful, the media player will {@link #onPrepared()},
* and it will call {@link #onError()} otherwise.
*/
- private void prepareContent() {
+ protected void prepareContent() {
if (mView == null) {
return;
}
@@ -564,10 +614,8 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
mIsPrepared = true;
// Update the duration in the database if it was not previously retrieved
- if (mDuration.get() == 0) {
- CallLogAsyncTaskUtil.updateVoicemailDuration(mContext, mVoicemailUri,
- mMediaPlayer.getDuration() / 1000);
- }
+ CallLogAsyncTaskUtil.updateVoicemailDuration(mContext, mVoicemailUri,
+ TimeUnit.MILLISECONDS.toSeconds(mMediaPlayer.getDuration()));
mDuration.set(mMediaPlayer.getDuration());
@@ -593,7 +641,7 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
return true;
}
- private void handleError(Exception e) {
+ protected void handleError(Exception e) {
Log.d(TAG, "handleError: Could not play voicemail " + e);
if (mIsPrepared) {
@@ -664,7 +712,7 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
if (!hasContent) {
// No local content, download from server. Queue playing if the request was
// issued,
- mIsPlaying = requestContent();
+ mIsPlaying = requestContent(PLAYBACK_REQUEST);
} else {
// Queue playing once the media play loaded the content.
mIsPlaying = true;
@@ -831,6 +879,17 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
return mIsPrepared && mMediaPlayer != null ? mMediaPlayer.getCurrentPosition() : 0;
}
+ public void notifyUiOfArchiveResult(Uri voicemailUri, boolean archived) {
+ if (mView == null) {
+ return;
+ }
+ if (archived) {
+ mView.onVoicemailArchiveSucceded(voicemailUri);
+ } else {
+ mView.onVoicemailArchiveFailed(voicemailUri);
+ }
+ }
+
/* package */ void onVoicemailDeleted() {
// Trampoline the event notification to the interested listener.
if (mOnVoicemailDeletedListener != null) {
@@ -859,6 +918,154 @@ public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListene
return mScheduledExecutorService;
}
+ /**
+ * If voicemail has already been downloaded, go straight to archiving. Otherwise, request
+ * the voicemail content first.
+ */
+ public void archiveContent(Uri voicemailUri, boolean archivedByUser) {
+ if (!mIsPrepared) {
+ requestContent(ARCHIVE_REQUEST);
+ } else {
+ startArchiveVoicemailTask(voicemailUri, archivedByUser);
+ }
+ }
+
+ /**
+ * Asynchronous task used to archive a voicemail given its uri.
+ */
+ private void startArchiveVoicemailTask(final Uri voicemailUri, final boolean archivedByUser) {
+ mAsyncTaskExecutor.submit(Tasks.ARCHIVE_VOICEMAIL, new AsyncTask<Void, Void, Uri>() {
+ @Override
+ public Uri doInBackground(Void... params) {
+ return performArchiveVoicemailOnBackgroundThread(voicemailUri, archivedByUser);
+ }
+
+ @Override
+ public void onPostExecute(Uri archivedVoicemailUri) {
+ notifyUiOfArchiveResult(voicemailUri, archivedVoicemailUri != null);
+ }
+ });
+ }
+
+ /**
+ * Copy the voicemail information to the local dialer database, and copy
+ * the voicemail content to a local file in the dialer application's
+ * internal storage (voicemails directory).
+ *
+ * @param voicemailUri the uri of the voicemail to archive
+ * @return If archive was successful, archived voicemail URI, otherwise null.
+ */
+ private Uri performArchiveVoicemailOnBackgroundThread(Uri voicemailUri,
+ boolean archivedByUser) {
+ Cursor callLogInfo = mContext.getContentResolver().query(
+ ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
+ ContentUris.parseId(mVoicemailUri)),
+ CallLogQuery._PROJECTION, null, null, null);
+ Cursor contentInfo = mContext.getContentResolver().query(
+ voicemailUri, null, null, null, null);
+
+ if (callLogInfo == null || contentInfo == null) {
+ return null;
+ }
+
+ callLogInfo.moveToFirst();
+ contentInfo.moveToFirst();
+
+ // Create values to insert into database
+ ContentValues values = new ContentValues();
+ values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER,
+ contentInfo.getString(contentInfo.getColumnIndex(
+ VoicemailContract.Voicemails.NUMBER)));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.DATE,
+ contentInfo.getLong(contentInfo.getColumnIndex(
+ VoicemailContract.Voicemails.DATE)));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.DURATION,
+ contentInfo.getLong(contentInfo.getColumnIndex(
+ VoicemailContract.Voicemails.DURATION)));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.MIME_TYPE,
+ contentInfo.getString(contentInfo.getColumnIndex(
+ VoicemailContract.Voicemails.MIME_TYPE)));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.COUNTRY_ISO,
+ callLogInfo.getString(CallLogQuery.COUNTRY_ISO));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.GEOCODED_LOCATION,
+ callLogInfo.getString(CallLogQuery.GEOCODED_LOCATION));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NAME,
+ callLogInfo.getString(CallLogQuery.CACHED_NAME));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_TYPE,
+ callLogInfo.getInt(CallLogQuery.CACHED_NUMBER_TYPE));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_LABEL,
+ callLogInfo.getString(CallLogQuery.CACHED_NUMBER_LABEL));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_LOOKUP_URI,
+ callLogInfo.getString(CallLogQuery.CACHED_LOOKUP_URI));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_MATCHED_NUMBER,
+ callLogInfo.getString(CallLogQuery.CACHED_MATCHED_NUMBER));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NORMALIZED_NUMBER,
+ callLogInfo.getString(CallLogQuery.CACHED_NORMALIZED_NUMBER));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_FORMATTED_NUMBER,
+ callLogInfo.getString(CallLogQuery.CACHED_FORMATTED_NUMBER));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED, archivedByUser);
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER_PRESENTATION,
+ callLogInfo.getInt(CallLogQuery.NUMBER_PRESENTATION));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_COMPONENT_NAME,
+ callLogInfo.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_ID,
+ callLogInfo.getString(CallLogQuery.ACCOUNT_ID));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.FEATURES,
+ callLogInfo.getInt(CallLogQuery.FEATURES));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.SERVER_ID,
+ contentInfo.getInt(contentInfo.getColumnIndex(
+ VoicemailContract.Voicemails._ID)));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.TRANSCRIPTION,
+ contentInfo.getString(contentInfo.getColumnIndex(
+ VoicemailContract.Voicemails.TRANSCRIPTION)));
+
+ values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_PHOTO_URI,
+ callLogInfo.getLong(CallLogQuery.CACHED_PHOTO_URI));
+
+ callLogInfo.close();
+ contentInfo.close();
+
+ // Insert info into dialer database
+ Uri archivedVoicemailUri = mContext.getContentResolver().insert(
+ VoicemailArchiveContract.VoicemailArchive.CONTENT_URI, values);
+ try {
+ // Copy voicemail content to a local file
+ InputStream inputStream = mContext.getContentResolver()
+ .openInputStream(voicemailUri);
+ OutputStream outputStream = mContext.getContentResolver()
+ .openOutputStream(archivedVoicemailUri);
+
+ ByteStreams.copy(inputStream, outputStream);
+ inputStream.close();
+ outputStream.close();
+ } catch (IOException e) {
+ // Roll back insert if new file creation failed
+ mContext.getContentResolver().delete(archivedVoicemailUri, null, null);
+ Log.w(TAG, "Failed to copy voicemail content to temporary file");
+ return null;
+ }
+ return archivedVoicemailUri;
+ }
+
@VisibleForTesting
public boolean isPlaying() {
return mIsPlaying;
diff --git a/tests/src/com/android/dialer/voicemail/VoicemailActivityInstrumentationTestCase2.java b/tests/src/com/android/dialer/voicemail/VoicemailActivityInstrumentationTestCase2.java
new file mode 100644
index 000000000..a992e8bd0
--- /dev/null
+++ b/tests/src/com/android/dialer/voicemail/VoicemailActivityInstrumentationTestCase2.java
@@ -0,0 +1,212 @@
+package com.android.dialer.voicemail;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.res.AssetManager;
+import android.net.Uri;
+import android.provider.VoicemailContract;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.Suppress;
+import android.view.View;
+
+import com.android.dialer.R;
+import com.android.dialer.util.AsyncTaskExecutors;
+import com.android.dialer.util.FakeAsyncTaskExecutor;
+import com.android.dialer.util.LocaleTestUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Locale;
+
+import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT;
+
+
+/**
+ * Common methods and attributes between {@link VoicemailArchiveTest} and
+ * {@link VoicemailPlaybackTest}.
+ */
+public class VoicemailActivityInstrumentationTestCase2<T extends Activity>
+ extends ActivityInstrumentationTestCase2<T> {
+ protected static final String TEST_ASSET_NAME = "quick_test_recording.mp3";
+ protected static final String MIME_TYPE = "audio/mp3";
+ protected static final String CONTACT_NUMBER = "+1412555555";
+ protected static final String VOICEMAIL_FILE_LOCATION = "/sdcard/sadlfj893w4j23o9sfu.mp3";
+
+ private T mActivity;
+ protected VoicemailPlaybackPresenter mPresenter;
+ private VoicemailPlaybackLayout mLayout;
+
+ protected Uri mVoicemailUri;
+ private LocaleTestUtils mLocaleTestUtils;
+ protected FakeAsyncTaskExecutor mFakeAsyncTaskExecutor;
+
+ public VoicemailActivityInstrumentationTestCase2(Class<T> activityClass) {
+ super(activityClass);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mFakeAsyncTaskExecutor = new FakeAsyncTaskExecutor(getInstrumentation());
+ AsyncTaskExecutors.setFactoryForTest(mFakeAsyncTaskExecutor.getFactory());
+
+ // Some of the tests rely on the text - safest to force a specific locale.
+ mLocaleTestUtils = new LocaleTestUtils(getInstrumentation().getTargetContext());
+ mLocaleTestUtils.setLocale(Locale.US);
+
+ mActivity = getActivity();
+ mLayout = new VoicemailPlaybackLayout(mActivity);
+ mLayout.onFinishInflate();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ cleanUpVoicemailUri();
+
+ mLocaleTestUtils.restoreLocale();
+ mLocaleTestUtils = null;
+
+ mPresenter.clearInstance();
+ AsyncTaskExecutors.setFactoryForTest(null);
+
+ mActivity = null;
+ mPresenter = null;
+ mLayout = null;
+
+ super.tearDown();
+ }
+
+ @Suppress
+ public void testFetchingVoicemail() throws Throwable {
+ setUriForUnfetchedVoicemailEntry();
+ setPlaybackViewForPresenter();
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mPresenter.resumePlayback();
+ assertStateTextContains("Loading voicemail");
+ }
+ });
+ }
+
+ @Suppress
+ public void testInvalidVoicemailShowsErrorMessage() throws Throwable {
+ setUriForInvalidVoicemailEntry();
+ setPlaybackViewForPresenter();
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mPresenter.resumePlayback();
+ }
+ });
+ mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
+ getInstrumentation().waitForIdleSync();
+
+ // The media player will have thrown an IOException since the file doesn't exist.
+ // This should have put a failed to play message on screen, buffering is gone.
+ assertStateTextContains("Couldn't play voicemail");
+ assertStateTextNotContains("Buffering");
+ }
+
+ public void testClickingSpeakerphoneButton() throws Throwable {
+ setUriForRealFileVoicemailEntry();
+ setPlaybackViewForPresenter();
+
+ // Check that the speakerphone is false to start.
+ assertFalse(mPresenter.isSpeakerphoneOn());
+
+ View speakerphoneButton = mLayout.findViewById(R.id.playback_speakerphone);
+ speakerphoneButton.performClick();
+ assertTrue(mPresenter.isSpeakerphoneOn());
+ }
+
+ protected void cleanUpVoicemailUri() {
+ if (mVoicemailUri != null) {
+ getContentResolver().delete(VoicemailContract.Voicemails.CONTENT_URI,
+ "_ID = ?", new String[] { String.valueOf(ContentUris.parseId(mVoicemailUri)) });
+ mVoicemailUri = null;
+ }
+ }
+
+ protected void setUriForRealFileVoicemailEntry() throws IOException {
+ assertNull(mVoicemailUri);
+ ContentValues values = new ContentValues();
+ values.put(VoicemailContract.Voicemails.DATE, String.valueOf(System.currentTimeMillis()));
+ values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
+ values.put(VoicemailContract.Voicemails.MIME_TYPE, MIME_TYPE);
+ values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
+ String packageName = getInstrumentation().getTargetContext().getPackageName();
+ mVoicemailUri = getContentResolver().insert(
+ VoicemailContract.Voicemails.buildSourceUri(packageName), values);
+ AssetManager assets = getAssets();
+ try (InputStream inputStream = assets.open(TEST_ASSET_NAME);
+ OutputStream outputStream = getContentResolver().openOutputStream(mVoicemailUri)) {
+ copyBetweenStreams(inputStream, outputStream);
+ }
+ }
+
+ protected void setUriForUnfetchedVoicemailEntry() {
+ assertNull(mVoicemailUri);
+ ContentValues values = new ContentValues();
+ values.put(VoicemailContract.Voicemails.DATE, String.valueOf(System.currentTimeMillis()));
+ values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
+ values.put(VoicemailContract.Voicemails.MIME_TYPE, MIME_TYPE);
+ values.put(VoicemailContract.Voicemails.HAS_CONTENT, 0);
+ String packageName = getInstrumentation().getTargetContext().getPackageName();
+ mVoicemailUri = getContentResolver().insert(
+ VoicemailContract.Voicemails.buildSourceUri(packageName), values);
+ }
+
+ protected void setUriForInvalidVoicemailEntry() {
+ assertNull(mVoicemailUri);
+ ContentResolver contentResolver = getContentResolver();
+ ContentValues values = new ContentValues();
+ values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
+ values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
+ // VoicemailContract.Voicemails._DATA
+ values.put("_data", VOICEMAIL_FILE_LOCATION);
+ mVoicemailUri = contentResolver.insert(VoicemailContract.Voicemails.CONTENT_URI, values);
+ }
+
+ protected void setPlaybackViewForPresenter() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mPresenter.setPlaybackView(mLayout, mVoicemailUri, false);
+ }
+ });
+ }
+
+ protected void copyBetweenStreams(InputStream in, OutputStream out) throws IOException {
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = in.read(buffer)) > 0) {
+ out.write(buffer, 0, bytesRead);
+ }
+ }
+
+ protected void assertStateTextContains(String text) {
+ assertNotNull(mLayout);
+ assertTrue(mLayout.getStateText().contains(text));
+ }
+
+ protected void assertStateTextNotContains(String text) {
+ assertNotNull(mLayout);
+ assertFalse(mLayout.getStateText().contains(text));
+ }
+
+ protected ContentResolver getContentResolver() {
+ return getInstrumentation().getTargetContext().getContentResolver();
+ }
+
+ protected AssetManager getAssets() {
+ return getInstrumentation().getContext().getAssets();
+ }
+
+}
diff --git a/tests/src/com/android/dialer/voicemail/VoicemailArchiveTest.java b/tests/src/com/android/dialer/voicemail/VoicemailArchiveTest.java
new file mode 100644
index 000000000..8cbd344a2
--- /dev/null
+++ b/tests/src/com/android/dialer/voicemail/VoicemailArchiveTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.dialer.voicemail;
+import android.content.ContentUris;
+import android.content.ContentValues;
+
+import com.android.dialer.R;
+import com.android.dialer.database.VoicemailArchiveContract.VoicemailArchive;
+
+import android.content.res.AssetManager;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Unit tests for {@link VoicemailArchiveActivity} and {@link VoicemailArchivePlaybackPresenter}.
+ */
+public class VoicemailArchiveTest
+ extends VoicemailActivityInstrumentationTestCase2<VoicemailArchiveActivity> {
+
+ public VoicemailArchiveTest() {
+ super(VoicemailArchiveActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mPresenter = VoicemailArchivePlaybackPresenter.getInstance(getActivity(), null);
+ }
+
+ @Override
+ public void testFetchingVoicemail() throws Throwable {
+ setUriForRealFileVoicemailEntry();
+ setPlaybackViewForPresenter();
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mPresenter.checkForContent(
+ new VoicemailPlaybackPresenter.OnContentCheckedListener() {
+ @Override
+ public void onContentChecked(boolean hasContent) {
+ mPresenter.resumePlayback();
+ assertEquals(true, mPresenter.isPlaying());
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ public void testInvalidVoicemailShowsErrorMessage() throws Throwable {
+ setUriForInvalidVoicemailEntry();
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mPresenter.checkForContent(
+ new VoicemailPlaybackPresenter.OnContentCheckedListener() {
+ @Override
+ public void onContentChecked(boolean hasContent) {
+ assertStateTextContains("Couldn't play voicemail");
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ protected void setUriForInvalidVoicemailEntry() {
+ assertNull(mVoicemailUri);
+ ContentValues values = new ContentValues();
+ values.put(VoicemailArchive.NUMBER, CONTACT_NUMBER);
+ values.put(VoicemailArchive.DATE, String.valueOf(System.currentTimeMillis()));
+ values.put(VoicemailArchive.MIME_TYPE, MIME_TYPE);
+ values.put(VoicemailArchive._DATA, VOICEMAIL_FILE_LOCATION);
+ mVoicemailUri = getContentResolver().insert(VoicemailArchive.CONTENT_URI, values);
+ }
+
+ @Override
+ protected void setUriForRealFileVoicemailEntry() throws IOException {
+ assertNull(mVoicemailUri);
+ ContentValues values = new ContentValues();
+ values.put(VoicemailArchive.DATE, String.valueOf(System.currentTimeMillis()));
+ values.put(VoicemailArchive.NUMBER, CONTACT_NUMBER);
+ values.put(VoicemailArchive.MIME_TYPE, MIME_TYPE);
+ values.put(VoicemailArchive.DURATION, 0);
+ mVoicemailUri = getContentResolver().insert(VoicemailArchive.CONTENT_URI, values);
+ AssetManager assets = getAssets();
+ try (InputStream inputStream = assets.open(TEST_ASSET_NAME);
+ OutputStream outputStream = getContentResolver().openOutputStream(mVoicemailUri)) {
+ copyBetweenStreams(inputStream, outputStream);
+ }
+ }
+
+ @Override
+ protected void cleanUpVoicemailUri() {
+ if (mVoicemailUri != null) {
+ getContentResolver().delete(VoicemailArchive.CONTENT_URI,
+ "_ID = ?", new String[] { String.valueOf(ContentUris.parseId(mVoicemailUri)) });
+ mVoicemailUri = null;
+ }
+ }
+}
diff --git a/tests/src/com/android/dialer/voicemail/VoicemailPlaybackTest.java b/tests/src/com/android/dialer/voicemail/VoicemailPlaybackTest.java
index 630789cf7..abd582bec 100644
--- a/tests/src/com/android/dialer/voicemail/VoicemailPlaybackTest.java
+++ b/tests/src/com/android/dialer/voicemail/VoicemailPlaybackTest.java
@@ -16,54 +16,17 @@
package com.android.dialer.voicemail;
-import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT;
-import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_CONTENT_AFTER_CHANGE;
-
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.net.Uri;
-import android.provider.VoicemailContract;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
-import android.view.View;
-import android.widget.TextView;
-import com.android.dialer.R;
import com.android.dialer.calllog.CallLogActivity;
-import com.android.dialer.util.AsyncTaskExecutors;
-import com.android.dialer.util.FakeAsyncTaskExecutor;
-import com.android.dialer.util.LocaleTestUtils;
-import com.android.dialer.voicemail.VoicemailPlaybackLayout;
-import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Locale;
+import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT;
/**
- * Unit tests for the {@link VoicemailPlaybackPresenter} and {@link VoicemailPlaybackLayout}.
+ * Unit tests for {@link VoicemailPlaybackPresenter} and {@link VoicemailPlaybackLayout}.
*/
-@LargeTest
-public class VoicemailPlaybackTest extends ActivityInstrumentationTestCase2<CallLogActivity> {
- private static final String TEST_ASSET_NAME = "quick_test_recording.mp3";
- private static final String MIME_TYPE = "audio/mp3";
- private static final String CONTACT_NUMBER = "+1412555555";
- private static final String VOICEMAIL_FILE_LOCATION = "/sdcard/sadlfj893w4j23o9sfu.mp3";
-
- private Activity mActivity;
- private VoicemailPlaybackPresenter mPresenter;
- private VoicemailPlaybackLayout mLayout;
-
- private Uri mVoicemailUri;
- private LocaleTestUtils mLocaleTestUtils;
- private FakeAsyncTaskExecutor mFakeAsyncTaskExecutor;
+public class VoicemailPlaybackTest
+ extends VoicemailActivityInstrumentationTestCase2<CallLogActivity> {
public VoicemailPlaybackTest() {
super(CallLogActivity.class);
@@ -72,49 +35,7 @@ public class VoicemailPlaybackTest extends ActivityInstrumentationTestCase2<Call
@Override
public void setUp() throws Exception {
super.setUp();
-
- mFakeAsyncTaskExecutor = new FakeAsyncTaskExecutor(getInstrumentation());
- AsyncTaskExecutors.setFactoryForTest(mFakeAsyncTaskExecutor.getFactory());
-
- // Some of the tests rely on the text - safest to force a specific locale.
- mLocaleTestUtils = new LocaleTestUtils(getInstrumentation().getTargetContext());
- mLocaleTestUtils.setLocale(Locale.US);
-
- mActivity = getActivity();
- mLayout = new VoicemailPlaybackLayout(mActivity);
- mLayout.onFinishInflate();
-
- mPresenter = VoicemailPlaybackPresenter.getInstance(mActivity, null);
- }
-
- @Override
- protected void tearDown() throws Exception {
- cleanUpVoicemailUri();
-
- mLocaleTestUtils.restoreLocale();
- mLocaleTestUtils = null;
-
- mPresenter.clearInstance();
- AsyncTaskExecutors.setFactoryForTest(null);
-
- mActivity = null;
- mPresenter = null;
- mLayout = null;
-
- super.tearDown();
- }
-
- public void testFetchingVoicemail() throws Throwable {
- setUriForUnfetchedVoicemailEntry();
- setPlaybackViewForPresenter();
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mPresenter.resumePlayback();
- assertStateTextContains("Loading voicemail");
- }
- });
+ mPresenter = VoicemailPlaybackPresenter.getInstance(getActivity(), null);
}
@Suppress
@@ -133,119 +54,4 @@ public class VoicemailPlaybackTest extends ActivityInstrumentationTestCase2<Call
assertStateTextContains("Loading voicemail");
}
-
- @Suppress
- public void testInvalidVoicemailShowsErrorMessage() throws Throwable {
- setUriForInvalidVoicemailEntry();
- setPlaybackViewForPresenter();
-
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mPresenter.resumePlayback();
- }
- });
- mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
- getInstrumentation().waitForIdleSync();
-
- // The media player will have thrown an IOException since the file doesn't exist.
- // This should have put a failed to play message on screen, buffering is gone.
- assertStateTextContains("Couldn't play voicemail");
- assertStateTextNotContains("Buffering");
- }
-
- public void testClickingSpeakerphoneButton() throws Throwable {
- setUriForRealFileVoicemailEntry();
- setPlaybackViewForPresenter();
-
- // Check that the speakerphone is false to start.
- assertFalse(mPresenter.isSpeakerphoneOn());
-
- View speakerphoneButton = mLayout.findViewById(R.id.playback_speakerphone);
- speakerphoneButton.performClick();
- assertTrue(mPresenter.isSpeakerphoneOn());
- }
-
- private void cleanUpVoicemailUri() {
- if (mVoicemailUri != null) {
- getContentResolver().delete(VoicemailContract.Voicemails.CONTENT_URI,
- "_ID = ?", new String[] { String.valueOf(ContentUris.parseId(mVoicemailUri)) });
- mVoicemailUri = null;
- }
- }
-
- private void setUriForRealFileVoicemailEntry() throws IOException {
- assertNull(mVoicemailUri);
- ContentValues values = new ContentValues();
- values.put(VoicemailContract.Voicemails.DATE, String.valueOf(System.currentTimeMillis()));
- values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
- values.put(VoicemailContract.Voicemails.MIME_TYPE, MIME_TYPE);
- values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
- String packageName = getInstrumentation().getTargetContext().getPackageName();
- mVoicemailUri = getContentResolver().insert(
- VoicemailContract.Voicemails.buildSourceUri(packageName), values);
- AssetManager assets = getAssets();
- try (InputStream inputStream = assets.open(TEST_ASSET_NAME);
- OutputStream outputStream = getContentResolver().openOutputStream(mVoicemailUri)) {
- copyBetweenStreams(inputStream, outputStream);
- }
- }
-
- private void setUriForUnfetchedVoicemailEntry() {
- assertNull(mVoicemailUri);
- ContentValues values = new ContentValues();
- values.put(VoicemailContract.Voicemails.DATE, String.valueOf(System.currentTimeMillis()));
- values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
- values.put(VoicemailContract.Voicemails.MIME_TYPE, MIME_TYPE);
- values.put(VoicemailContract.Voicemails.HAS_CONTENT, 0);
- String packageName = getInstrumentation().getTargetContext().getPackageName();
- mVoicemailUri = getContentResolver().insert(
- VoicemailContract.Voicemails.buildSourceUri(packageName), values);
- }
-
- private void setUriForInvalidVoicemailEntry() {
- assertNull(mVoicemailUri);
- ContentResolver contentResolver = getContentResolver();
- ContentValues values = new ContentValues();
- values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
- values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
- // VoicemailContract.Voicemails._DATA
- values.put("_data", VOICEMAIL_FILE_LOCATION);
- mVoicemailUri = contentResolver.insert(VoicemailContract.Voicemails.CONTENT_URI, values);
- }
-
- private void setPlaybackViewForPresenter() {
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mPresenter.setPlaybackView(mLayout, mVoicemailUri, false);
- }
- });
- }
-
- public void copyBetweenStreams(InputStream in, OutputStream out) throws IOException {
- byte[] buffer = new byte[1024];
- int bytesRead;
- while ((bytesRead = in.read(buffer)) > 0) {
- out.write(buffer, 0, bytesRead);
- }
- }
-
- private void assertStateTextContains(String text) {
- assertNotNull(mLayout);
- assertTrue(mLayout.getStateText().contains(text));
- }
-
- private void assertStateTextNotContains(String text) {
- assertNotNull(mLayout);
- assertFalse(mLayout.getStateText().contains(text));
- }
-
- private ContentResolver getContentResolver() {
- return getInstrumentation().getTargetContext().getContentResolver();
- }
-
- private AssetManager getAssets() {
- return getInstrumentation().getContext().getAssets();
- }
-}
+} \ No newline at end of file