Merge "Update the styling of the empty call log."
diff --git a/res/layout/contact_detail_fragment_carousel.xml b/res/layout/contact_detail_fragment_carousel.xml
index 4f65549..2572cc4 100644
--- a/res/layout/contact_detail_fragment_carousel.xml
+++ b/res/layout/contact_detail_fragment_carousel.xml
@@ -30,7 +30,9 @@
         android:id="@+id/about_fragment_container"
         android:layout_width="0dip"
         android:layout_height="match_parent"
-        android:layout_weight="1" />
+        android:layout_weight="1"
+        android:focusable="true"
+        android:focusableInTouchMode="true" />
 
     <!--
       Container for the "Updates" page fragment on the contact card for a contact
@@ -42,6 +44,8 @@
         android:layout_width="0dip"
         android:layout_height="match_parent"
         android:layout_weight="1"
-        android:visibility="gone" />
+        android:visibility="gone"
+        android:focusable="true"
+        android:focusableInTouchMode="true" />
 
 </LinearLayout>
\ No newline at end of file
diff --git a/res/mipmap-hdpi/ic_launcher_contacts.png b/res/mipmap-hdpi/ic_launcher_contacts.png
index 5ebe2e0..fa60a53 100644
--- a/res/mipmap-hdpi/ic_launcher_contacts.png
+++ b/res/mipmap-hdpi/ic_launcher_contacts.png
Binary files differ
diff --git a/res/mipmap-hdpi/ic_launcher_phone.png b/res/mipmap-hdpi/ic_launcher_phone.png
index e56c507..5a3dff1 100644
--- a/res/mipmap-hdpi/ic_launcher_phone.png
+++ b/res/mipmap-hdpi/ic_launcher_phone.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_contacts.png b/res/mipmap-mdpi/ic_launcher_contacts.png
index c79ae14..b50d7dd 100644
--- a/res/mipmap-mdpi/ic_launcher_contacts.png
+++ b/res/mipmap-mdpi/ic_launcher_contacts.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_phone.png b/res/mipmap-mdpi/ic_launcher_phone.png
index 1f40fd0..9ea0d8c 100644
--- a/res/mipmap-mdpi/ic_launcher_phone.png
+++ b/res/mipmap-mdpi/ic_launcher_phone.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_contacts.png b/res/mipmap-xhdpi/ic_launcher_contacts.png
index ca3aa63..4b7eaaa 100644
--- a/res/mipmap-xhdpi/ic_launcher_contacts.png
+++ b/res/mipmap-xhdpi/ic_launcher_contacts.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_phone.png b/res/mipmap-xhdpi/ic_launcher_phone.png
index e23a58c..e97836c 100644
--- a/res/mipmap-xhdpi/ic_launcher_phone.png
+++ b/res/mipmap-xhdpi/ic_launcher_phone.png
Binary files differ
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index 2df2e47..e465772 100644
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -323,10 +323,26 @@
                 if (rawContactId == -1) {
                     throw new IllegalStateException("Could not determine RawContact ID after save");
                 }
-                final Uri rawContactUri = ContentUris.withAppendedId(
-                        isProfile ? Profile.CONTENT_RAW_CONTACTS_URI : RawContacts.CONTENT_URI,
-                                rawContactId);
-                lookupUri = RawContacts.getContactLookupUri(resolver, rawContactUri);
+                if (isProfile) {
+                    // Since the profile supports local raw contacts, which may have been completely
+                    // removed if all information was removed, we need to do a special query to
+                    // get the lookup URI for the profile contact (if it still exists).
+                    Cursor c = resolver.query(Profile.CONTENT_URI,
+                            new String[] {Contacts._ID, Contacts.LOOKUP_KEY},
+                            null, null, null);
+                    try {
+                        c.moveToFirst();
+                        final long contactId = c.getLong(0);
+                        final String lookupKey = c.getString(1);
+                        lookupUri = Contacts.getLookupUri(contactId, lookupKey);
+                    } finally {
+                        c.close();
+                    }
+                } else {
+                    final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI,
+                                    rawContactId);
+                    lookupUri = RawContacts.getContactLookupUri(resolver, rawContactUri);
+                }
                 Log.v(TAG, "Saved contact. New URI: " + lookupUri);
                 break;
 
diff --git a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
index b01316b..756b1c7 100644
--- a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
@@ -19,7 +19,6 @@
 import com.android.contacts.R;
 
 import android.content.Context;
-import android.os.Handler;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -88,8 +87,6 @@
     private View mDetailFragmentView;
     private View mUpdatesFragmentView;
 
-    private boolean mScrollToCurrentPage = false;
-
     public ContactDetailFragmentCarousel(Context context) {
         this(context, null);
     }
@@ -144,31 +141,9 @@
                 resolveSize(screenHeight, heightMeasureSpec));
     }
 
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        super.onLayout(changed, l, t, r, b);
-        if (mScrollToCurrentPage) {
-            mScrollToCurrentPage = false;
-            // Use scrollTo() instead of smoothScrollTo() to prevent a visible flicker to the user
-            scrollTo(mCurrentPage == ABOUT_PAGE ? 0 : mAllowedHorizontalScrollLength, 0);
-            updateTouchInterceptors();
-        }
-    }
-
     /**
-     * Set the current page that should be restored when the view is first laid out.
-     */
-    public void restoreCurrentPage(int pageIndex) {
-        setCurrentPage(pageIndex);
-        // It is only possible to scroll the view after onMeasure() has been called (where the
-        // allowed horizontal scroll length is determined). Hence, set a flag that will be read
-        // in onLayout() after the children and this view have finished being laid out.
-        mScrollToCurrentPage = true;
-    }
-
-    /**
-     * Set the current page. This auto-scrolls the carousel to the current page and dims out
-     * the non-selected page.
+     * Set the current page. This dims out the non-selected page but doesn't do any scrolling of
+     * the carousel.
      */
     public void setCurrentPage(int pageIndex) {
         mCurrentPage = pageIndex;
@@ -176,7 +151,6 @@
         if (mAboutFragment != null && mUpdatesFragment != null) {
             mAboutFragment.setAlphaLayerValue(mCurrentPage == ABOUT_PAGE ? 0 : MAX_ALPHA);
             mUpdatesFragment.setAlphaLayerValue(mCurrentPage == UPDATES_PAGE ? 0 : MAX_ALPHA);
-            snapToEdge();
         }
     }
 
@@ -205,9 +179,12 @@
             mEnableSwipe = enable;
             if (mUpdatesFragmentView != null) {
                 mUpdatesFragmentView.setVisibility(enable ? View.VISIBLE : View.GONE);
-                mScrollToCurrentPage = true;
-                requestLayout();
-                invalidate();
+                if (mCurrentPage == ABOUT_PAGE) {
+                    mDetailFragmentView.requestFocus();
+                } else {
+                    mUpdatesFragmentView.requestFocus();
+                }
+                updateTouchInterceptors();
             }
         }
     }
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
index 7a7f400..4b31a6e 100644
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java
@@ -215,7 +215,7 @@
 
                 mFragmentCarousel.setFragmentViews(mDetailFragmentView, mUpdatesFragmentView);
                 mFragmentCarousel.setFragments(mDetailFragment, mUpdatesFragment);
-                mFragmentCarousel.restoreCurrentPage(currentPageIndex);
+                mFragmentCarousel.setCurrentPage(currentPageIndex);
                 break;
             }
         }
diff --git a/src/com/android/contacts/vcard/ImportVCardActivity.java b/src/com/android/contacts/vcard/ImportVCardActivity.java
index 054e018..18b9cc1 100644
--- a/src/com/android/contacts/vcard/ImportVCardActivity.java
+++ b/src/com/android/contacts/vcard/ImportVCardActivity.java
@@ -45,18 +45,14 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.res.Configuration;
+import android.database.Cursor;
 import android.net.Uri;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.nfc.NfcAdapter;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
 import android.os.PowerManager;
-import android.os.RemoteException;
+import android.provider.OpenableColumns;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.TextUtils;
@@ -72,7 +68,6 @@
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
-import java.nio.charset.Charset;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -285,6 +280,8 @@
                         return;
                     }
                 } else {
+                    final ContentResolver resolver =
+                            ImportVCardActivity.this.getContentResolver();
                     for (Uri sourceUri : mSourceUris) {
                         String filename = null;
                         // Note: caches are removed by VCardService.
@@ -309,10 +306,37 @@
                             Log.w(LOG_TAG, "destUri is null");
                             break;
                         }
+
+                        String displayName = null;
+                        Cursor cursor = null;
+                        // Try to get a display name from the given Uri. If it fails, we just
+                        // pick up the last part of the Uri.
+                        try {
+                            cursor = resolver.query(sourceUri,
+                                    new String[] { OpenableColumns.DISPLAY_NAME },
+                                    null, null, null);
+                            if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
+                                if (cursor.getCount() > 1) {
+                                    Log.w(LOG_TAG, "Unexpected multiple rows: "
+                                            + cursor.getCount());
+                                }
+                                int index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+                                if (index >= 0) {
+                                    displayName = cursor.getString(index);
+                                }
+                            }
+                        } finally {
+                            if (cursor != null) {
+                                cursor.close();
+                            }
+                        }
+                        if (TextUtils.isEmpty(displayName)){
+                            displayName = sourceUri.getLastPathSegment();
+                        }
+
                         final ImportRequest request;
                         try {
-                            request = constructImportRequest(null, localDataUri,
-                                    sourceUri.getLastPathSegment());
+                            request = constructImportRequest(null, localDataUri, displayName);
                         } catch (VCardException e) {
                             Log.e(LOG_TAG, "Maybe the file is in wrong format", e);
                             showFailureNotification(R.string.fail_reason_not_supported);