Merge "Added empty states for ContactTileList."
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index 1e40964..c20df49 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -36,12 +36,24 @@
             android:src="@drawable/ic_call_log_home"
         />
     </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/voicemail_status"
+        android:layout_below="@id/action_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentLeft="true"
+        android:visibility="gone"
+    >
+        <include layout="@layout/call_log_voicemail_status"/>
+    </FrameLayout>
+
     <ImageView
         android:id="@+id/contact_background"
         android:layout_width="match_parent"
         android:layout_height="?attr/call_detail_contact_background_height"
         android:layout_alignParentLeft="true"
-        android:layout_below="@id/action_bar"
+        android:layout_below="@id/voicemail_status"
         android:adjustViewBounds="true"
         android:scaleType="centerCrop"
         android:background="@drawable/ic_contact_picture"
diff --git a/res/layout/call_log_fragment.xml b/res/layout/call_log_fragment.xml
index 573969b..2d0b9b5 100644
--- a/res/layout/call_log_fragment.xml
+++ b/res/layout/call_log_fragment.xml
@@ -19,7 +19,16 @@
     android:layout_height="match_parent"
     android:orientation="vertical"
 >
-    <include layout="@layout/call_log_voicemail_status"/>
+    <FrameLayout
+        android:id="@+id/voicemail_status"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentBottom="true"
+        android:visibility="gone">
+        <include layout="@layout/call_log_voicemail_status"
+    />
+    </FrameLayout>
     <FrameLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -29,7 +38,6 @@
             android:layout_height="match_parent"
             android:scrollbarStyle="outsideOverlay"
         />
-
         <TextView android:id="@android:id/empty"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
@@ -39,4 +47,3 @@
         />
     </FrameLayout>
 </LinearLayout>
-
diff --git a/res/layout/call_log_voicemail_status.xml b/res/layout/call_log_voicemail_status.xml
index fee2210..c7def4d 100644
--- a/res/layout/call_log_voicemail_status.xml
+++ b/res/layout/call_log_voicemail_status.xml
@@ -13,41 +13,40 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/voicemail_status"
-    android:layout_width="match_parent"
-    android:layout_height="?attr/call_log_voicemail_status_height"
-    android:layout_alignParentLeft="true"
-    android:layout_alignParentBottom="true"
-    android:background="?attr/call_log_voicemail_status_background_color"
-    android:baselineAligned="false"
-    android:visibility="gone">
-    <TextView
-        android:id="@+id/voicemail_status_message"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:paddingLeft="14dip"
-        android:paddingRight="14dip"
-        android:textColor="?attr/call_log_voicemail_status_text_color"
-        android:layout_gravity="left"
-        android:layout_weight="5"/>
-    <View android:id="@+id/divider"
-        android:layout_width="1px"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="5dip"
-        android:layout_marginBottom="5dip"
-        android:layout_marginLeft="11dip"
-        android:background="@drawable/divider_vertical_dark"/>
-    <TextView
-        android:id="@+id/voicemail_status_action"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="right"
-        android:paddingLeft="14dip"
-        android:paddingRight="14dip"
-        android:textColor="?attr/call_log_voicemail_status_text_color"
-        android:gravity="right"
-        android:layout_alignParentRight="true"
-        android:clickable="true"
-    />
-</LinearLayout>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="?attr/call_log_voicemail_status_height"
+        android:background="?attr/call_log_voicemail_status_background_color">
+        <TextView
+            android:id="@+id/voicemail_status_message"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:paddingLeft="14dip"
+            android:paddingRight="14dip"
+            android:textColor="?attr/call_log_voicemail_status_text_color"
+            android:layout_gravity="left"
+            android:layout_weight="5"
+        />
+        <View android:id="@+id/divider"
+            android:layout_width="1px"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dip"
+            android:layout_marginBottom="5dip"
+            android:layout_marginLeft="11dip"
+            android:background="@drawable/divider_vertical_dark"
+        />
+        <TextView
+            android:id="@+id/voicemail_status_action"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="right"
+            android:paddingLeft="14dip"
+            android:paddingRight="14dip"
+            android:textColor="?attr/call_log_voicemail_status_text_color"
+            android:gravity="right"
+            android:layout_alignParentRight="true"
+            android:clickable="true"
+        />
+    </LinearLayout>
+</merge>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3fa411c..9a73373 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -71,6 +71,10 @@
         <item name="call_log_secondary_text_color">#FFFFFF</item>
         <item name="call_log_secondary_background_color">#333333</item>
         <item name="call_log_header_color">#33b5e5</item>
+        <!-- VoicemailStatus -->
+        <item name="call_log_voicemail_status_height">40dip</item>
+        <item name="call_log_voicemail_status_background_color">#FFFFE0</item>
+        <item name="call_log_voicemail_status_text_color">#000000</item>
     </style>
 
     <style name="ContactDetailActivityTheme" parent="android:Theme.Holo.Light">
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index d2c193e..d411927 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -20,6 +20,9 @@
 import com.android.contacts.calllog.CallTypeHelper;
 import com.android.contacts.calllog.PhoneNumberHelper;
 import com.android.contacts.voicemail.VoicemailPlaybackFragment;
+import com.android.contacts.voicemail.VoicemailStatusHelper;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
 
 import android.app.FragmentManager;
 import android.app.ListActivity;
@@ -87,6 +90,14 @@
     /* package */ Resources mResources;
     /** Helper to load contact photos. */
     private ContactPhotoManager mContactPhotoManager;
+    /** Helper to make async queries to content resolver. */
+    private CallDetailActivityQueryHandler mAsyncQueryHandler;
+    /** Helper to get voicemail status messages. */
+    private VoicemailStatusHelper mVoicemailStatusHelper;
+    // Views related to voicemail status message.
+    private View mStatusMessageView;
+    private TextView mStatusMessageText;
+    private TextView mStatusMessageAction;
 
     static final String[] CALL_LOG_PROJECTION = new String[] {
         CallLog.Calls.DATE,
@@ -137,6 +148,11 @@
         mPhoneNumberHelper = new PhoneNumberHelper(mResources, getVoicemailNumber());
         mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(this, mResources, mCallTypeHelper,
                 mPhoneNumberHelper);
+        mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
+        mAsyncQueryHandler = new CallDetailActivityQueryHandler(this);
+        mStatusMessageView = findViewById(R.id.voicemail_status);
+        mStatusMessageText = (TextView) findViewById(R.id.voicemail_status_message);
+        mStatusMessageAction = (TextView) findViewById(R.id.voicemail_status_action);
         mHomeActionView = findViewById(R.id.action_bar_home);
         mMainActionView = (ImageView) findViewById(R.id.main_action);
         mContactBackgroundView = (ImageView) findViewById(R.id.contact_background);
@@ -153,11 +169,18 @@
         });
     }
 
+
     @Override
     public void onResume() {
         super.onResume();
         updateData(getCallLogEntryUris());
-        optionallyHandleVoicemail();
+        Uri voicemailUri = getIntent().getExtras().getParcelable(EXTRA_VOICEMAIL_URI);
+        optionallyHandleVoicemail(voicemailUri);
+        if (voicemailUri != null) {
+            mAsyncQueryHandler.startVoicemailStatusQuery(voicemailUri);
+        } else {
+            mStatusMessageView.setVisibility(View.GONE);
+        }
     }
 
     /**
@@ -166,11 +189,10 @@
      * If the Intent used to start this Activity contains the suitable extras, then start voicemail
      * playback.  If it doesn't, then hide the voicemail ui.
      */
-    private void optionallyHandleVoicemail() {
+    private void optionallyHandleVoicemail(Uri voicemailUri) {
         FragmentManager manager = getFragmentManager();
         VoicemailPlaybackFragment fragment = (VoicemailPlaybackFragment) manager.findFragmentById(
                 R.id.voicemail_playback_fragment);
-        Uri voicemailUri = getIntent().getExtras().getParcelable(EXTRA_VOICEMAIL_URI);
         if (voicemailUri == null) {
             // No voicemail uri: hide the voicemail fragment.
             manager.beginTransaction().hide(fragment).commit();
@@ -419,8 +441,7 @@
                     numberText = candidateNumberText;
                 }
             }
-            return new PhoneCallDetails(number, numberText,
-                    mPhoneNumberHelper.parsePhoneNumber(number, countryIso),
+            return new PhoneCallDetails(number, numberText, countryIso,
                     new int[]{ callType }, date, duration,
                     nameText, numberType, numberLabel, personId, photoUri);
         } finally {
@@ -554,4 +575,48 @@
             ContactsSearchManager.startSearch(this, initialQuery);
         }
     }
+
+    protected void updateVoicemailStatusMessage(Cursor statusCursor) {
+        if (statusCursor == null) {
+            mStatusMessageView.setVisibility(View.GONE);
+            return;
+        }
+        final StatusMessage message = getStatusMessage(statusCursor);
+        if (message == null || !message.showInCallDetails()) {
+            mStatusMessageView.setVisibility(View.GONE);
+            return;
+        }
+
+        mStatusMessageView.setVisibility(View.VISIBLE);
+        mStatusMessageText.setText(message.callDetailsMessageId);
+        if (message.actionMessageId != -1) {
+            mStatusMessageAction.setText(message.actionMessageId);
+        }
+        if (message.actionUri != null) {
+            mStatusMessageAction.setClickable(true);
+            mStatusMessageAction.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    startActivity(new Intent(Intent.ACTION_VIEW, message.actionUri));
+                }
+            });
+        } else {
+            mStatusMessageAction.setClickable(false);
+        }
+    }
+
+    private StatusMessage getStatusMessage(Cursor statusCursor) {
+        List<StatusMessage> messages = mVoicemailStatusHelper.getStatusMessages(statusCursor);
+        Log.d(TAG, "Num status messages: " + messages.size());
+        if (messages.size() == 0) {
+            return null;
+        }
+        // There can only be a single status message per source package, so num of messages can
+        // at most be 1.
+        if (messages.size() > 1) {
+            Log.w(TAG, String.format("Expected 1, found (%d) num of status messages." +
+                    " Will use the first one.", messages.size()));
+        }
+        return messages.get(0);
+    }
 }
diff --git a/src/com/android/contacts/CallDetailActivityQueryHandler.java b/src/com/android/contacts/CallDetailActivityQueryHandler.java
new file mode 100644
index 0000000..c1d87b2
--- /dev/null
+++ b/src/com/android/contacts/CallDetailActivityQueryHandler.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 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.contacts;
+
+import com.android.common.io.MoreCloseables;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+
+import android.content.AsyncQueryHandler;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.VoicemailContract.Status;
+import android.provider.VoicemailContract.Voicemails;
+import android.util.Log;
+
+/**
+ * Class used by {@link CallDetailActivity} to fire async content resolver queries.
+ */
+public class CallDetailActivityQueryHandler extends AsyncQueryHandler {
+    private static final String TAG = "CallDetail";
+    private static final int QUERY_VOICEMAIL_CONTENT_TOKEN = 101;
+    private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 102;
+
+    private final String[] VOICEMAIL_CONTENT_PROJECTION = new String[] {
+        Voicemails.SOURCE_PACKAGE,
+        Voicemails.HAS_CONTENT
+    };
+    private static final int SOURCE_PACKAGE_COLUMN_INDEX = 0;
+    private static final int HAS_CONTENT_COLUMN_INDEX = 1;
+
+    private final CallDetailActivity mCallDetailActivity;
+
+    public CallDetailActivityQueryHandler(CallDetailActivity callDetailActivity) {
+        super(callDetailActivity.getContentResolver());
+        mCallDetailActivity = callDetailActivity;
+    }
+
+    /**
+     * Fires a query to update voicemail status for the given voicemail record. On completion of the
+     * query a call to {@link CallDetailActivity#updateVoicemailStatusMessage(Cursor)} is made.
+     * <p>
+     * if this is a voicemail record then it makes up to two asynchronous content resolver queries.
+     * The first one to fetch voicemail content details and check if the voicemail record has audio.
+     * If the voicemail record does not have an audio yet then it fires the second query to get the
+     * voicemail status of the associated source.
+     */
+    public void startVoicemailStatusQuery(Uri voicemaiUri) {
+        startQuery(QUERY_VOICEMAIL_CONTENT_TOKEN, null, voicemaiUri, VOICEMAIL_CONTENT_PROJECTION,
+                null, null, null);
+    }
+
+    @Override
+    protected synchronized void onQueryComplete(int token, Object cookie, Cursor cursor) {
+        try {
+            if (token == QUERY_VOICEMAIL_CONTENT_TOKEN) {
+                // Query voicemail status only if this voicemail record does not have audio.
+                if (cursor.moveToFirst() && hasNoAudio(cursor)) {
+                    startQuery(QUERY_VOICEMAIL_STATUS_TOKEN, null,
+                            Status.buildSourceUri(getSourcePackage(cursor)),
+                            VoicemailStatusHelperImpl.PROJECTION, null, null, null);
+                } else {
+                    mCallDetailActivity.updateVoicemailStatusMessage(null);
+                }
+            } else if (token == QUERY_VOICEMAIL_STATUS_TOKEN) {
+                mCallDetailActivity.updateVoicemailStatusMessage(cursor);
+            } else {
+                Log.w(TAG, "Unknown query completed: ignoring: " + token);
+            }
+        } finally {
+            MoreCloseables.closeQuietly(cursor);
+        }
+    }
+
+    private boolean hasNoAudio(Cursor voicemailCursor) {
+        return voicemailCursor.getInt(HAS_CONTENT_COLUMN_INDEX) == 0;
+    }
+
+    private String getSourcePackage(Cursor voicemailCursor) {
+        return voicemailCursor.getString(SOURCE_PACKAGE_COLUMN_INDEX);
+    }
+}
diff --git a/src/com/android/contacts/PhoneCallDetails.java b/src/com/android/contacts/PhoneCallDetails.java
index 0672673..347a303 100644
--- a/src/com/android/contacts/PhoneCallDetails.java
+++ b/src/com/android/contacts/PhoneCallDetails.java
@@ -16,8 +16,6 @@
 
 package com.android.contacts;
 
-import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
-
 import android.net.Uri;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -30,8 +28,8 @@
     public final CharSequence number;
     /** The formatted version of {@link #number}. */
     public final CharSequence formattedNumber;
-    /** The structured phone number corresponding to {@link #number}. */
-    public final PhoneNumber structuredPhoneNumber;
+    /** The country corresponding with the phone number. */
+    public final String countryIso;
     /**
      * The type of calls, as defined in the call log table, e.g., {@link Calls#INCOMING_TYPE}.
      * <p>
@@ -58,19 +56,18 @@
 
     /** Create the details for a call with a number not associated with a contact. */
     public PhoneCallDetails(CharSequence number, CharSequence formattedNumber,
-            PhoneNumber structuredPhoneNumber, int[] callTypes, long date, long duration) {
-        this(number, formattedNumber, structuredPhoneNumber, callTypes, date, duration,
-                "", 0, "", -1L, null);
+            String countryIso, int[] callTypes, long date, long duration) {
+        this(number, formattedNumber, countryIso, callTypes, date, duration, "", 0, "", -1L, null);
     }
 
     /** Create the details for a call with a number associated with a contact. */
     public PhoneCallDetails(CharSequence number, CharSequence formattedNumber,
-            PhoneNumber structuredPhoneNumber, int[] callTypes, long date, long duration,
+            String countryIso, int[] callTypes, long date, long duration,
             CharSequence name, int numberType, CharSequence numberLabel, long personId,
             Uri photoUri) {
         this.number = number;
         this.formattedNumber = formattedNumber;
-        this.structuredPhoneNumber = structuredPhoneNumber;
+        this.countryIso = countryIso;
         this.callTypes = callTypes;
         this.date = date;
         this.duration = duration;
diff --git a/src/com/android/contacts/PhoneCallDetailsHelper.java b/src/com/android/contacts/PhoneCallDetailsHelper.java
index db3928e..2c36cec 100644
--- a/src/com/android/contacts/PhoneCallDetailsHelper.java
+++ b/src/com/android/contacts/PhoneCallDetailsHelper.java
@@ -118,7 +118,9 @@
             mPhoneNumberHelper.getDisplayNumber(details.number, details.formattedNumber);
         if (TextUtils.isEmpty(details.name)) {
             nameText = displayNumber;
-            numberText = mPhoneNumberHelper.getGeocodeForNumber(details.structuredPhoneNumber);
+            numberText = mPhoneNumberHelper.getGeocodeForNumber(
+                    mPhoneNumberHelper.parsePhoneNumber(
+                            details.number.toString(), details.countryIso));
         } else {
             nameText = details.name;
             if (numberFormattedLabel != null) {
diff --git a/src/com/android/contacts/activities/CallLogActivity.java b/src/com/android/contacts/activities/CallLogActivity.java
index 4ddf4d0..4f1c8d9 100644
--- a/src/com/android/contacts/activities/CallLogActivity.java
+++ b/src/com/android/contacts/activities/CallLogActivity.java
@@ -29,7 +29,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.util.Log;
 import android.view.KeyEvent;
 import android.view.ViewConfiguration;
 
@@ -61,28 +60,6 @@
     }
 
     @Override
-    public void onWindowFocusChanged(boolean hasFocus) {
-        super.onWindowFocusChanged(hasFocus);
-
-        // Clear notifications only when window gains focus.  This activity won't
-        // immediately receive focus if the keyguard screen is above it.
-        if (hasFocus) {
-            try {
-                ITelephony telephony =
-                        ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
-                if (telephony != null) {
-                    telephony.cancelMissedCallsNotification();
-                } else {
-                    Log.w(TAG, "Telephony service is null, can't call " +
-                            "cancelMissedCallsNotification");
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to clear missed calls notification due to remote exception");
-            }
-        }
-    }
-
-    @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         switch (keyCode) {
             case KeyEvent.KEYCODE_CALL: {
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 2e49883..14378d9 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -298,6 +298,7 @@
         @Override
         public void onEditRequested(Uri contactLookupUri) {
             startActivity(new Intent(Intent.ACTION_EDIT, contactLookupUri));
+            finish();
         }
 
         @Override
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 6655c81..28bc3a3 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -148,9 +148,11 @@
         }
 
         @Override
-        public void onSaveFinished(int resultCode, Intent resultIntent, boolean navigateHome) {
-            setResult(resultCode, resultIntent);
-            if (navigateHome) {
+        public void onSaveFinished(Intent resultIntent) {
+            if (resultIntent != null) {
+                startActivity(resultIntent);
+            } else {
+                // Navigate home
                 Intent intent = new Intent(ContactEditorActivity.this, PeopleActivity.class);
                 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                 startActivity(intent);
@@ -165,7 +167,6 @@
 
         @Override
         public void onContactNotFound() {
-            setResult(Activity.RESULT_CANCELED, null);
             finish();
         }
 
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index ae61813..0b403cb 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -106,12 +106,10 @@
     private static final String TAG = "PeopleActivity";
     private static final Boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE
 
-    private static final int SUBACTIVITY_NEW_CONTACT = 2;
-    private static final int SUBACTIVITY_EDIT_CONTACT = 3;
-    private static final int SUBACTIVITY_NEW_GROUP = 4;
-    private static final int SUBACTIVITY_EDIT_GROUP = 5;
-    private static final int SUBACTIVITY_ACCOUNT_FILTER = 6;
-    private static final int SUBACTIVITY_CUSTOMIZE_FILTER = 7;
+    private static final int SUBACTIVITY_NEW_GROUP = 2;
+    private static final int SUBACTIVITY_EDIT_GROUP = 3;
+    private static final int SUBACTIVITY_ACCOUNT_FILTER = 4;
+    private static final int SUBACTIVITY_CUSTOMIZE_FILTER = 5;
 
     private static final String KEY_SEARCH_MODE = "searchMode";
 
@@ -926,7 +924,7 @@
             if (extras != null) {
                 intent.putExtras(extras);
             }
-            startActivityForResult(intent, SUBACTIVITY_EDIT_CONTACT);
+            startActivity(intent);
         }
 
         @Override
@@ -1012,8 +1010,7 @@
 
         @Override
         public void onEditRequested(Uri contactLookupUri) {
-            startActivityForResult(
-                    new Intent(Intent.ACTION_EDIT, contactLookupUri), SUBACTIVITY_EDIT_CONTACT);
+            startActivity(new Intent(Intent.ACTION_EDIT, contactLookupUri));
         }
 
         @Override
@@ -1297,7 +1294,7 @@
             }
             case R.id.menu_add_contact: {
                 final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
-                startActivityForResult(intent, SUBACTIVITY_NEW_CONTACT);
+                startActivity(intent);
                 return true;
             }
             case R.id.menu_add_group: {
@@ -1387,14 +1384,6 @@
                 }
                 break;
             }
-            case SUBACTIVITY_EDIT_CONTACT:
-            case SUBACTIVITY_NEW_CONTACT: {
-                if (resultCode == RESULT_OK && PhoneCapabilityTester.isUsingTwoPanes(this)) {
-                    mRequest.setActionCode(ContactsRequest.ACTION_VIEW_CONTACT);
-                    mAllFragment.reloadDataAndSetSelectedUri(data.getData());
-                }
-                break;
-            }
 
             case SUBACTIVITY_NEW_GROUP:
             case SUBACTIVITY_EDIT_GROUP: {
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 1aa4d3d..c59cbf9 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -25,11 +25,13 @@
 import com.android.contacts.R;
 import com.android.contacts.activities.DialtactsActivity;
 import com.android.contacts.activities.DialtactsActivity.ViewPagerVisibilityListener;
-import com.android.contacts.calllog.VoicemailStatusHelper.StatusMessage;
 import com.android.contacts.util.ExpirableCache;
+import com.android.contacts.voicemail.VoicemailStatusHelper;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
 import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.ITelephony;
 import com.google.common.annotations.VisibleForTesting;
-import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
 
 import android.app.ListFragment;
 import android.content.ContentUris;
@@ -42,6 +44,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.Contacts;
@@ -669,13 +673,11 @@
             final String lookupKey = info.lookupKey;
             final int[] callTypes = getCallTypes(c, count);
             final PhoneCallDetails details;
-            PhoneNumber structuredPhoneNumber =
-                    mPhoneNumberHelper.parsePhoneNumber(number, countryIso);
             if (TextUtils.isEmpty(name)) {
-                details = new PhoneCallDetails(number, formattedNumber, structuredPhoneNumber,
+                details = new PhoneCallDetails(number, formattedNumber, countryIso,
                         callTypes, date, duration);
             } else {
-                details = new PhoneCallDetails(number, formattedNumber, structuredPhoneNumber,
+                details = new PhoneCallDetails(number, formattedNumber, countryIso,
                         callTypes, date, duration, name, ntype, label, personId, thumbnailUri);
             }
 
@@ -1066,5 +1068,26 @@
         resetNewCallsFlag();
         startVoicemailStatusQuery();
         mAdapter.mPreDrawListener = null; // Let it restart the thread after next draw
+        // Clear notifications only when window gains focus.  This activity won't
+        // immediately receive focus if the keyguard screen is above it.
+        if (getActivity().hasWindowFocus()) {
+            removeMissedCallNotifications();
+        }
+    }
+
+    /** Removes the missed call notifications. */
+    private void removeMissedCallNotifications() {
+        try {
+            ITelephony telephony =
+                    ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
+            if (telephony != null) {
+                telephony.cancelMissedCallsNotification();
+            } else {
+                Log.w(TAG, "Telephony service is null, can't call " +
+                        "cancelMissedCallsNotification");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to clear missed calls notification due to remote exception");
+        }
     }
 }
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index 62e308c..8569190 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -18,6 +18,7 @@
 
 import com.android.common.io.MoreCloseables;
 import com.android.contacts.calllog.CallLogFragment.CallLogQuery;
+import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
 
 import android.content.AsyncQueryHandler;
 import android.content.ContentValues;
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 9b89f84..6afe8b9 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -970,7 +970,6 @@
             case SaveMode.CLOSE:
             case SaveMode.HOME:
                 final Intent resultIntent;
-                final int resultCode;
                 if (success && contactLookupUri != null) {
                     final String requestAuthority =
                             mLookupUri == null ? null : mLookupUri.getAuthority();
@@ -978,6 +977,7 @@
                     final String legacyAuthority = "contacts";
 
                     resultIntent = new Intent();
+                    resultIntent.setAction(Intent.ACTION_VIEW);
                     if (legacyAuthority.equals(requestAuthority)) {
                         // Build legacy Uri when requested by caller
                         final long contactId = ContentUris.parseId(Contacts.lookupContact(
@@ -991,15 +991,12 @@
                         resultIntent.setData(contactLookupUri);
                     }
 
-                    resultCode = Activity.RESULT_OK;
                 } else {
-                    resultCode = Activity.RESULT_CANCELED;
                     resultIntent = null;
                 }
                 // It is already saved, so prevent that it is saved again
                 mStatus = Status.CLOSING;
-                if (mListener != null) mListener.onSaveFinished(resultCode, resultIntent,
-                        saveMode == SaveMode.HOME);
+                if (mListener != null) mListener.onSaveFinished(resultIntent);
                 break;
 
             case SaveMode.RELOAD:
@@ -1101,7 +1098,7 @@
         /**
          * Contact was saved and the Fragment can now be closed safely.
          */
-        void onSaveFinished(int resultCode, Intent resultIntent, boolean navigateHome);
+        void onSaveFinished(Intent resultIntent);
 
         /**
          * User decided to delete the contact.
diff --git a/src/com/android/contacts/calllog/VoicemailStatusHelper.java b/src/com/android/contacts/voicemail/VoicemailStatusHelper.java
similarity index 98%
rename from src/com/android/contacts/calllog/VoicemailStatusHelper.java
rename to src/com/android/contacts/voicemail/VoicemailStatusHelper.java
index f6def45..1eab749 100644
--- a/src/com/android/contacts/calllog/VoicemailStatusHelper.java
+++ b/src/com/android/contacts/voicemail/VoicemailStatusHelper.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.contacts.calllog;
+package com.android.contacts.voicemail;
 
 import android.database.Cursor;
 import android.net.Uri;
diff --git a/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java b/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
similarity index 98%
rename from src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
rename to src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
index 972fbd5..7332e89 100644
--- a/src/com/android/contacts/calllog/VoicemailStatusHelperImpl.java
+++ b/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.contacts.calllog;
+package com.android.contacts.voicemail;
 
 import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE_CAN_BE_CONFIGURED;
 import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE_OK;
@@ -46,7 +46,7 @@
     private static final int VOICEMAIL_ACCESS_URI_INDEX = 5;
     private static final int NUM_COLUMNS = 6;
     /** Projection on the voicemail_status table used by this class. */
-    protected static final String[] PROJECTION = new String[NUM_COLUMNS];
+    public static final String[] PROJECTION = new String[NUM_COLUMNS];
     static {
         PROJECTION[SOURCE_PACKAGE_INDEX] = Status.SOURCE_PACKAGE;
         PROJECTION[CONFIGURATION_STATE_INDEX] = Status.CONFIGURATION_STATE;
diff --git a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
index e228c3b..f02e7b0 100644
--- a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
@@ -20,7 +20,6 @@
 import com.android.contacts.calllog.PhoneNumberHelper;
 import com.android.contacts.util.LocaleTestUtils;
 import com.android.internal.telephony.CallerInfo;
-import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -231,20 +230,16 @@
 
     /** Sets the phone call details with default values and the given number. */
     private void setPhoneCallDetailsWithNumber(String number, String formattedNumber) {
-        PhoneNumber structuredPhoneNumber =
-                mPhoneNumberHelper.parsePhoneNumber(number, TEST_COUNTRY_ISO);
         mHelper.setPhoneCallDetails(mViews,
-                new PhoneCallDetails(number, formattedNumber, structuredPhoneNumber,
+                new PhoneCallDetails(number, formattedNumber, TEST_COUNTRY_ISO,
                         new int[]{ Calls.INCOMING_TYPE }, TEST_DATE, TEST_DURATION),
                 false, false);
     }
 
     /** Sets the phone call details with default values and the given date. */
     private void setPhoneCallDetailsWithDate(long date) {
-        PhoneNumber structuredPhoneNumber =
-                mPhoneNumberHelper.parsePhoneNumber(TEST_NUMBER, TEST_COUNTRY_ISO);
         mHelper.setPhoneCallDetails(mViews,
-                new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, structuredPhoneNumber,
+                new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO,
                         new int[]{ Calls.INCOMING_TYPE }, date, TEST_DURATION),
                 false, false);
     }
@@ -260,10 +255,8 @@
     }
 
     private void setPhoneCallDetailsWithCallTypes(boolean useIcons, int... callTypes) {
-        PhoneNumber structuredPhoneNumber =
-                mPhoneNumberHelper.parsePhoneNumber(TEST_NUMBER, TEST_COUNTRY_ISO);
         mHelper.setPhoneCallDetails(mViews,
-                new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, structuredPhoneNumber,
+                new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO,
                         callTypes, TEST_DATE, TEST_DURATION),
                 useIcons, false);
     }
diff --git a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
index 08d1e03..c56041e 100644
--- a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
@@ -21,7 +21,6 @@
 import com.android.contacts.PhoneCallDetailsViews;
 import com.android.contacts.R;
 import com.android.internal.telephony.CallerInfo;
-import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -124,20 +123,16 @@
 
     /** Sets the details of a phone call using the specified phone number. */
     private void setPhoneCallDetailsWithNumber(String number, String formattedNumber) {
-        PhoneNumber structuredPhoneNumber =
-                mPhoneNumberHelper.parsePhoneNumber(number, TEST_COUNTRY_ISO);
         mHelper.setPhoneCallDetails(mViews,
-                new PhoneCallDetails(number, formattedNumber, structuredPhoneNumber,
+                new PhoneCallDetails(number, formattedNumber, TEST_COUNTRY_ISO,
                         new int[]{ Calls.INCOMING_TYPE }, TEST_DATE, TEST_DURATION),
                 true, false);
     }
 
     /** Sets the details of a phone call using the specified call type. */
     private void setPhoneCallDetailsWithTypes(int... types) {
-        PhoneNumber structuredPhoneNumber =
-                mPhoneNumberHelper.parsePhoneNumber(TEST_NUMBER, TEST_COUNTRY_ISO);
         mHelper.setPhoneCallDetails(mViews,
-                new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, structuredPhoneNumber,
+                new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO,
                         types, TEST_DATE, TEST_DURATION),
                 true, false);
     }
diff --git a/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java b/tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
similarity index 77%
rename from tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
rename to tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
index 9b293c4..b1a0175 100644
--- a/tests/src/com/android/contacts/calllog/VoicemailStatusHelperImplTest.java
+++ b/tests/src/com/android/contacts/voicemail/VoicemailStatusHelperImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.contacts.calllog;
+package com.android.contacts.voicemail;
 
 import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE;
 import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE_CAN_BE_CONFIGURED;
@@ -28,7 +28,7 @@
 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK;
 
 import com.android.contacts.R;
-import com.android.contacts.calllog.VoicemailStatusHelper.StatusMessage;
+import com.android.contacts.voicemail.VoicemailStatusHelper.StatusMessage;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -37,16 +37,16 @@
 import android.provider.VoicemailContract.Status;
 import android.test.AndroidTestCase;
 
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 /**
  * Unit tests for {@link VoicemailStatusHelperImpl}.
  */
 public class VoicemailStatusHelperImplTest extends AndroidTestCase {
-    private static final String TEST_PACKAGE_1 = "com.test.package1";
-    private static final String TEST_PACKAGE_2 = "com.test.package2";
+    private static final String[] TEST_PACKAGES = new String[] {
+        "com.test.package1",
+        "com.test.package2"
+    };
 
     private static final Uri TEST_SETTINGS_URI = Uri.parse("http://www.visual.voicemail.setup");
     private static final Uri TEST_VOICEMAIL_URI = Uri.parse("tel:901");
@@ -64,9 +64,6 @@
     private static final int STATUS_MSG_INVITE_FOR_CONFIGURATION =
             R.string.voicemail_status_configure_voicemail;
 
-    // The packages whose status entries have been added during the test and needs to be cleaned
-    // up in teardown.
-    private Set<String> mPackagesToCleanup = new HashSet<String>();
     // Object under test.
     private VoicemailStatusHelper mStatusHelper;
 
@@ -78,14 +75,12 @@
 
     @Override
     protected void tearDown() throws Exception {
-        for (String sourcePackage : mPackagesToCleanup) {
+        for (String sourcePackage : TEST_PACKAGES) {
             deleteEntryForPackage(sourcePackage);
         }
-        mPackagesToCleanup.clear();
         // Set member variables to null so that they are garbage collected across different runs
         // of the tests.
         mStatusHelper = null;
-        mPackagesToCleanup = null;
         super.tearDown();
     }
 
@@ -95,14 +90,14 @@
     }
 
     public void testAllOK() {
-        insertEntryForPackage(TEST_PACKAGE_1, getAllOkStatusValues());
-        insertEntryForPackage(TEST_PACKAGE_2, getAllOkStatusValues());
+        insertEntryForPackage(TEST_PACKAGES[0], getAllOkStatusValues());
+        insertEntryForPackage(TEST_PACKAGES[1], getAllOkStatusValues());
         assertEquals(0, getStatusMessages().size());
     }
 
     public void testNotAllOKForOnePackage() {
-        insertEntryForPackage(TEST_PACKAGE_1, getAllOkStatusValues());
-        insertEntryForPackage(TEST_PACKAGE_2, getAllOkStatusValues());
+        insertEntryForPackage(TEST_PACKAGES[0], getAllOkStatusValues());
+        insertEntryForPackage(TEST_PACKAGES[1], getAllOkStatusValues());
 
         ContentValues values = new ContentValues();
         // Good data channel + no notification
@@ -110,23 +105,23 @@
         // msg: voicemail not available in call log page & none in call details page.
         values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_NO_CONNECTION);
         values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_OK);
-        updateEntryForPackage(TEST_PACKAGE_2, values);
-        checkExpectedMessage(TEST_PACKAGE_2, values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE,
+        updateEntryForPackage(TEST_PACKAGES[1], values);
+        checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE,
                 STATUS_MSG_NONE, ACTION_MSG_CALL_VOICEMAIL);
 
         // Message waiting + good data channel - no action.
         values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING);
         values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_OK);
-        updateEntryForPackage(TEST_PACKAGE_2, values);
-        checkNoMessages(TEST_PACKAGE_2, values);
+        updateEntryForPackage(TEST_PACKAGES[1], values);
+        checkNoMessages(TEST_PACKAGES[1], values);
 
         // No data channel + no notification
         // action: call voicemail
         // msg: voicemail not available in call log page & audio not available in call details page.
         values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_OK);
         values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_NO_CONNECTION);
-        updateEntryForPackage(TEST_PACKAGE_2, values);
-        checkExpectedMessage(TEST_PACKAGE_2, values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE,
+        updateEntryForPackage(TEST_PACKAGES[1], values);
+        checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE,
                 STATUS_MSG_AUDIO_NOT_AVAIALABLE, ACTION_MSG_CALL_VOICEMAIL);
 
         // No data channel + Notification OK
@@ -134,8 +129,8 @@
         // msg: voicemail not available in call log page & audio not available in call details page.
         values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_NO_CONNECTION);
         values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_NO_CONNECTION);
-        updateEntryForPackage(TEST_PACKAGE_2, values);
-        checkExpectedMessage(TEST_PACKAGE_2, values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE,
+        updateEntryForPackage(TEST_PACKAGES[1], values);
+        checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE,
                 STATUS_MSG_AUDIO_NOT_AVAIALABLE, ACTION_MSG_CALL_VOICEMAIL);
 
         // No data channel + Notification OK
@@ -143,26 +138,26 @@
         // msg: message waiting in call log page & audio not available in call details page.
         values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING);
         values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_NO_CONNECTION);
-        updateEntryForPackage(TEST_PACKAGE_2, values);
-        checkExpectedMessage(TEST_PACKAGE_2, values, STATUS_MSG_MESSAGE_WAITING,
+        updateEntryForPackage(TEST_PACKAGES[1], values);
+        checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_MESSAGE_WAITING,
                 STATUS_MSG_AUDIO_NOT_AVAIALABLE, ACTION_MSG_CALL_VOICEMAIL);
 
         // Not configured. No user action, so no message.
         values.put(CONFIGURATION_STATE, CONFIGURATION_STATE_NOT_CONFIGURED);
-        updateEntryForPackage(TEST_PACKAGE_2, values);
-        checkNoMessages(TEST_PACKAGE_2, values);
+        updateEntryForPackage(TEST_PACKAGES[1], values);
+        checkNoMessages(TEST_PACKAGES[1], values);
 
         // Can be configured - invite user for configure voicemail.
         values.put(CONFIGURATION_STATE, CONFIGURATION_STATE_CAN_BE_CONFIGURED);
-        updateEntryForPackage(TEST_PACKAGE_2, values);
-        checkExpectedMessage(TEST_PACKAGE_2, values, STATUS_MSG_INVITE_FOR_CONFIGURATION,
+        updateEntryForPackage(TEST_PACKAGES[1], values);
+        checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_INVITE_FOR_CONFIGURATION,
                 STATUS_MSG_NONE, ACTION_MSG_CONFIGURE, TEST_SETTINGS_URI);
     }
 
     // Test that priority of messages are handled well.
     public void testMessageOrdering() {
-        insertEntryForPackage(TEST_PACKAGE_1, getAllOkStatusValues());
-        insertEntryForPackage(TEST_PACKAGE_2, getAllOkStatusValues());
+        insertEntryForPackage(TEST_PACKAGES[0], getAllOkStatusValues());
+        insertEntryForPackage(TEST_PACKAGES[1], getAllOkStatusValues());
 
         final ContentValues valuesNoNotificationGoodDataChannel = new ContentValues();
         valuesNoNotificationGoodDataChannel.put(NOTIFICATION_CHANNEL_STATE,
@@ -176,20 +171,20 @@
 
         // Package1 with valuesNoNotificationGoodDataChannel and
         // package2 with  valuesNoNotificationNoDataChannel. Package2 should be above.
-        updateEntryForPackage(TEST_PACKAGE_1, valuesNoNotificationGoodDataChannel);
-        updateEntryForPackage(TEST_PACKAGE_2, valuesNoNotificationNoDataChannel);
+        updateEntryForPackage(TEST_PACKAGES[0], valuesNoNotificationGoodDataChannel);
+        updateEntryForPackage(TEST_PACKAGES[1], valuesNoNotificationNoDataChannel);
         List<StatusMessage> messages = getStatusMessages();
         assertEquals(2, messages.size());
-        assertEquals(TEST_PACKAGE_1, messages.get(1).sourcePackage);
-        assertEquals(TEST_PACKAGE_2, messages.get(0).sourcePackage);
+        assertEquals(TEST_PACKAGES[0], messages.get(1).sourcePackage);
+        assertEquals(TEST_PACKAGES[1], messages.get(0).sourcePackage);
 
         // Now reverse the values - ordering should be reversed as well.
-        updateEntryForPackage(TEST_PACKAGE_1, valuesNoNotificationNoDataChannel);
-        updateEntryForPackage(TEST_PACKAGE_2, valuesNoNotificationGoodDataChannel);
+        updateEntryForPackage(TEST_PACKAGES[0], valuesNoNotificationNoDataChannel);
+        updateEntryForPackage(TEST_PACKAGES[1], valuesNoNotificationGoodDataChannel);
         messages = getStatusMessages();
         assertEquals(2, messages.size());
-        assertEquals(TEST_PACKAGE_1, messages.get(0).sourcePackage);
-        assertEquals(TEST_PACKAGE_2, messages.get(1).sourcePackage);
+        assertEquals(TEST_PACKAGES[0], messages.get(0).sourcePackage);
+        assertEquals(TEST_PACKAGES[1], messages.get(1).sourcePackage);
     }
 
     /** Checks that the expected source status message is returned by VoicemailStatusHelper. */
@@ -243,7 +238,6 @@
         if (getContentResolver().insert(Status.buildSourceUri(sourcePackage), values) == null) {
             updateEntryForPackage(sourcePackage, values);
         }
-        mPackagesToCleanup.add(sourcePackage);
     }
 
     private void deleteEntryForPackage(String sourcePackage) {
@@ -256,11 +250,24 @@
     }
 
     private List<StatusMessage> getStatusMessages() {
+        // Restrict the cursor to only the the test packages to eliminate any side effects if there
+        // are other status messages already stored on the device.
         Cursor cursor = getContentResolver().query(Status.CONTENT_URI,
-                VoicemailStatusHelperImpl.PROJECTION, null, null, null);
+                VoicemailStatusHelperImpl.PROJECTION, getTestPackageSelection(), null, null);
         return mStatusHelper.getStatusMessages(cursor);
     }
 
+    private String getTestPackageSelection() {
+        StringBuilder sb = new StringBuilder();
+        for (String sourcePackage : TEST_PACKAGES) {
+            if (sb.length() > 0) {
+                sb.append(" OR ");
+            }
+            sb.append(String.format("(source_package='%s')", sourcePackage));
+        }
+        return sb.toString();
+    }
+
     private ContentResolver getContentResolver() {
         return getContext().getContentResolver();
     }