Merge "Import translations. DO NOT MERGE" into ub-contactsdialer-master-dev
diff --git a/AndroidManifest_common.xml b/AndroidManifest_common.xml
index c616c1e..8fc97ac 100644
--- a/AndroidManifest_common.xml
+++ b/AndroidManifest_common.xml
@@ -351,7 +351,20 @@
</intent-filter>
</activity>
- <activity
+ <!-- Keep support for apps that expect the Compact editor -->
+ <activity-alias android:name="com.android.contacts.activities.CompactContactEditorActivity"
+ android:exported="true"
+ android:targetActivity=".activities.ContactEditorActivity">
+ <intent-filter android:priority="-1">
+ <action android:name="android.intent.action.INSERT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.dir/person" />
+ <data android:mimeType="vnd.android.cursor.dir/contact" />
+ <data android:mimeType="vnd.android.cursor.dir/raw_contact" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity
android:name=".activities.ContactEditorSpringBoardActivity"
android:noHistory="true"
android:theme="@style/TransparentThemeAppCompat">
diff --git a/res/drawable/ic_arrow_drop_down_black_24dp.xml b/res/drawable/ic_arrow_drop_down_black_24dp.xml
new file mode 100644
index 0000000..ebf2123
--- /dev/null
+++ b/res/drawable/ic_arrow_drop_down_black_24dp.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M7,10l5,5 5,-5z"/>
+</vector>
diff --git a/res/drawable/ic_close_24dp.xml b/res/drawable/ic_close_24dp.xml
index 52070d5..bcbb759 100644
--- a/res/drawable/ic_close_24dp.xml
+++ b/res/drawable/ic_close_24dp.xml
@@ -18,7 +18,7 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0" >
<path
android:fillColor="@android:color/white"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
diff --git a/res/layout/fragment_sim_import.xml b/res/layout/fragment_sim_import.xml
index b0eb280..d6d3acf 100644
--- a/res/layout/fragment_sim_import.xml
+++ b/res/layout/fragment_sim_import.xml
@@ -26,14 +26,13 @@
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
- style="@style/ContactsToolbarStyle"
+ style="@style/LightToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary"
- android:elevation="4dp"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ android:elevation="3dp"
+ android:theme="@style/LightToolbarThemeOverlay"
app:navigationContentDescription="@string/sim_import_cancel_content_description"
- app:navigationIcon="@drawable/ic_close_dk"
+ app:navigationIcon="@drawable/ic_close_24dp"
app:title="@string/sim_import_title_none_selected">
<Button
@@ -41,19 +40,56 @@
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="right|center_vertical"
+ android:layout_gravity="end|center_vertical"
android:text="@string/sim_import_button_text"
/>
</android.support.v7.widget.Toolbar>
- <FrameLayout
+
+ <!-- This is managed by AccountHeaderPresenter so the IDs in this section must
+ match the equivalent views in layout/editor_account_header.xml -->
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/account_header_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:colorBackground"
- android:elevation="4dp">
+ android:minHeight="48dp"
+ android:orientation="horizontal"
+ android:paddingEnd="32dp"
+ android:paddingStart="16dp">
- <include layout="@layout/editor_account_header"/>
- </FrameLayout>
+ <ImageView
+ android:id="@+id/account_type_icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="center_vertical"
+ android:layout_marginEnd="32dp"/>
+
+ <TextView
+ android:id="@+id/account_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:ellipsize="end"
+ android:gravity="center_vertical"
+ android:lines="1"
+ android:maxLines="1"
+ android:textColor="@color/secondary_text_color"
+ android:textSize="16sp"/>
+
+ <ImageView
+ android:id="@+id/account_expander_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="9dp"
+ android:layout_gravity="center_vertical"
+ android:scaleType="center"
+ android:src="@drawable/ic_arrow_drop_down_black_24dp"
+ android:tint="?android:textColorSecondary"
+ android:visibility="gone"/>
+ </LinearLayout>
<FrameLayout
android:layout_width="match_parent"
diff --git a/res/layout/join_contact_picker_section_header.xml b/res/layout/join_contact_picker_section_header.xml
index 7dafb49..f39cafd 100644
--- a/res/layout/join_contact_picker_section_header.xml
+++ b/res/layout/join_contact_picker_section_header.xml
@@ -23,8 +23,9 @@
<TextView
android:id="@+id/text"
style="@style/ContactListSeparatorTextViewStyle"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
- android:paddingStart="8dip"
- android:paddingEnd="8dip" />
+ android:textAlignment="viewStart"
+ android:paddingLeft="24dip"
+ android:paddingRight="24dip"
+ android:paddingStart="24dip"
+ android:paddingEnd="24dip"/>
</LinearLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d3431fb..d603973 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -148,8 +148,8 @@
<!-- For join screen. Mainly for tablet. -->
<dimen name="join_header_left_margin">@dimen/contact_browser_list_header_left_margin</dimen>
<dimen name="join_header_right_margin">@dimen/contact_browser_list_header_right_margin</dimen>
- <dimen name="join_header_top_margin">16dip</dimen>
- <dimen name="join_header_bottom_margin">0dip</dimen>
+ <dimen name="join_header_top_margin">12dip</dimen>
+ <dimen name="join_header_bottom_margin">12dip</dimen>
<dimen name="contact_filter_header_min_height">24dip</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index de283bb..70b8d9e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -972,9 +972,9 @@
<string name="permission_explanation_subheader_SMS">Messages</string>
<!-- The header text for hamburger promo [CHAR LIMIT=60]-->
- <string name="hamburger_feature_highlight_header">Organize your list</string>
+ <string name="hamburger_feature_highlight_header">Suggestions</string>
<!-- The body text for hamburger promo [CHAR LIMIT=200]-->
- <string name="hamburger_feature_highlight_body">Clean up duplicates & group contacts by label</string>
+ <string name="hamburger_feature_highlight_body">Keep your contacts organized and useful</string>
<!-- The label for the action shown in a snackbar after an operation that modifies some data is performed.
The user can click on the action to rollback the modification-->
@@ -1850,9 +1850,6 @@
<!-- Toolbar title shown when importing SIM contacts and none are selected -->
<string name="sim_import_title_none_selected">Select contacts</string>
- <!-- Toolbar title shown when importing SIM contacts and some are selected -->
- <string name="sim_import_title_some_selected_fmt"><xliff:g id="count">%d</xliff:g> Selected</string>
-
<!-- Message shown when the SIM import screen is displayed but there are no contacts on the
SIM card -->
<string name="sim_import_empty_message">No contacts on your SIM card</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index ab1a4ba..b762177 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -231,6 +231,21 @@
<item name="titleTextAppearance">@style/ContactsActionBarTitleTextAppCompat</item>
</style>
+ <style name="LightToolbarNavigationButtonStyle" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
+ <item name="android:tint">?android:textColorSecondary</item>
+ </style>
+
+ <style name="LightToolbarThemeOverlay" parent="@style/ThemeOverlay.AppCompat.ActionBar">
+ <item name="toolbarNavigationButtonStyle">@style/LightToolbarNavigationButtonStyle</item>
+ </style>
+
+ <style name="LightToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
+ <item name="android:background">@color/contextual_selection_bar_color</item>
+ <item name="background">@color/contextual_selection_bar_color</item>
+ <item name="android:titleTextAppearance">@style/ContactsActionBarTitleTextBlack</item>
+ <item name="titleTextAppearance">@style/ContactsActionBarTitleTextBlack</item>
+ </style>
+
<!-- Text in the action bar at the top of the screen -->
<style name="ContactsActionBarTitleText"
parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
diff --git a/src/com/android/contacts/ContactsDrawerActivity.java b/src/com/android/contacts/ContactsDrawerActivity.java
index 770298e..b7ae71a 100644
--- a/src/com/android/contacts/ContactsDrawerActivity.java
+++ b/src/com/android/contacts/ContactsDrawerActivity.java
@@ -823,9 +823,9 @@
onAccountChosen(accounts.get(0), /* extraArgs */ null);
return;
}
- SelectAccountDialogFragment.show(getFragmentManager(), null,
- R.string.dialog_new_group_account, AccountListFilter.ACCOUNTS_GROUP_WRITABLE,
- /* extraArgs */ null, TAG_SELECT_ACCOUNT_DIALOG);
+ SelectAccountDialogFragment.show(getFragmentManager(), R.string.dialog_new_group_account,
+ AccountListFilter.ACCOUNTS_GROUP_WRITABLE, /* extraArgs */ null,
+ TAG_SELECT_ACCOUNT_DIALOG);
}
@Override
diff --git a/src/com/android/contacts/SimImportFragment.java b/src/com/android/contacts/SimImportFragment.java
index d9030a8..66be41b 100644
--- a/src/com/android/contacts/SimImportFragment.java
+++ b/src/com/android/contacts/SimImportFragment.java
@@ -27,11 +27,13 @@
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.util.ArrayMap;
+import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ContentLoadingProgressBar;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;
@@ -47,9 +49,11 @@
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.preference.ContactsPreferences;
import com.android.contacts.editor.AccountHeaderPresenter;
+import com.google.common.primitives.Longs;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
@@ -60,22 +64,22 @@
*/
public class SimImportFragment extends DialogFragment
implements LoaderManager.LoaderCallbacks<SimImportFragment.LoaderResult>,
- MultiSelectEntryContactListAdapter.SelectedContactsListener {
+ MultiSelectEntryContactListAdapter.SelectedContactsListener, AbsListView.OnScrollListener {
- private static final String KEY_SELECTED_IDS = "selectedIds";
+ private static final String KEY_SUFFIX_SELECTED_IDS = "_selectedIds";
private static final String ARG_SUBSCRIPTION_ID = "subscriptionId";
private ContactsPreferences mPreferences;
private AccountTypeManager mAccountTypeManager;
private SimContactAdapter mAdapter;
+ private View mAccountHeaderContainer;
private AccountHeaderPresenter mAccountHeaderPresenter;
+ private float mAccountScrolledElevationPixels;
private ContentLoadingProgressBar mLoadingIndicator;
private Toolbar mToolbar;
private ListView mListView;
private View mImportButton;
- private long[] mSelectedContacts;
-
private int mSubscriptionId;
@Override
@@ -96,9 +100,6 @@
final Bundle args = getArguments();
mSubscriptionId = args == null ? SimCard.NO_SUBSCRIPTION_ID :
args.getInt(ARG_SUBSCRIPTION_ID, SimCard.NO_SUBSCRIPTION_ID);
-
- if (savedInstanceState == null) return;
- mSelectedContacts = savedInstanceState.getLongArray(KEY_SELECTED_IDS);
}
@Override
@@ -121,8 +122,11 @@
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_sim_import, container, false);
+ mAccountHeaderContainer = view.findViewById(R.id.account_header_container);
+ mAccountScrolledElevationPixels = getResources()
+ .getDimension(R.dimen.contact_list_header_elevation);
mAccountHeaderPresenter = new AccountHeaderPresenter(
- view.findViewById(R.id.account_header_container));
+ mAccountHeaderContainer);
if (savedInstanceState != null) {
mAccountHeaderPresenter.onRestoreInstanceState(savedInstanceState);
} else {
@@ -137,8 +141,10 @@
}
});
mAdapter.setAccount(mAccountHeaderPresenter.getCurrentAccount());
+ restoreAdapterSelectedStates(savedInstanceState);
mListView = (ListView) view.findViewById(R.id.list);
+ mListView.setOnScrollListener(this);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
@@ -160,7 +166,8 @@
dismiss();
}
});
- mImportButton.setEnabled(mAdapter.getSelectedContactIds().size() > 0);
+ mImportButton.setVisibility(mAdapter.getSelectedContactIds().size() > 0 ?
+ View.VISIBLE : View.GONE);
mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@@ -188,9 +195,7 @@
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mAccountHeaderPresenter.onSaveInstanceState(outState);
- if (mAdapter != null && mAdapter.mContacts != null) {
- outState.putLongArray(KEY_SELECTED_IDS, mAdapter.getSelectedContactIdsArray());
- }
+ saveAdapterSelectedStates(outState);
}
@Override
@@ -207,17 +212,41 @@
return;
}
mAdapter.setData(data);
- if (mSelectedContacts != null) {
- mAdapter.select(mSelectedContacts);
- } else {
- mAdapter.selectAll();
- }
}
@Override
public void onLoaderReset(Loader<LoaderResult> loader) {
}
+ private void restoreAdapterSelectedStates(Bundle savedInstanceState) {
+ if (savedInstanceState == null) {
+ return;
+ }
+
+ final List<AccountWithDataSet> accounts = mAccountTypeManager.getAccounts(true);
+ for (AccountWithDataSet account : accounts) {
+ final long[] selections = savedInstanceState.getLongArray(
+ account.stringify() + KEY_SUFFIX_SELECTED_IDS);
+ if (selections != null) {
+ mAdapter.setSelectionsForAccount(account, selections);
+ }
+ }
+ }
+
+ private void saveAdapterSelectedStates(Bundle outState) {
+ if (mAdapter == null) {
+ return;
+ }
+
+ // Make sure the selections are up-to-date
+ mAdapter.storeCurrentSelections();
+ for (Map.Entry<AccountWithDataSet, TreeSet<Long>> entry :
+ mAdapter.getSelectedIds().entrySet()) {
+ final long[] ids = Longs.toArray(entry.getValue());
+ outState.putLongArray(entry.getKey().stringify() + KEY_SUFFIX_SELECTED_IDS, ids);
+ }
+ }
+
private void importCurrentSelections() {
ContactSaveService.startService(getContext(), ContactSaveService
.createImportFromSimIntent(getContext(), mSubscriptionId,
@@ -240,11 +269,10 @@
if (selectedCount == 0) {
mToolbar.setTitle(R.string.sim_import_title_none_selected);
} else {
- mToolbar.setTitle(getString(R.string.sim_import_title_some_selected_fmt,
- selectedCount));
+ mToolbar.setTitle(String.valueOf(selectedCount));
}
if (mImportButton != null) {
- mImportButton.setEnabled(selectedCount > 0);
+ mImportButton.setVisibility(selectedCount > 0 ? View.VISIBLE : View.GONE);
}
}
@@ -255,6 +283,24 @@
return getActivity();
}
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) { }
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ int firstCompletelyVisibleItem = firstVisibleItem;
+ if (view != null && view.getChildAt(0) != null && view.getChildAt(0).getTop() < 0) {
+ firstCompletelyVisibleItem++;
+ }
+
+ if (firstCompletelyVisibleItem == 0) {
+ ViewCompat.setElevation(mAccountHeaderContainer, 0);
+ } else {
+ ViewCompat.setElevation(mAccountHeaderContainer, mAccountScrolledElevationPixels);
+ }
+ }
+
/**
* Creates a fragment that will display contacts stored on the default SIM card
*/
@@ -306,6 +352,7 @@
mExistingMap = result.accountsMap;
changeCursor(SimContact.convertToContactsCursor(mContacts,
ContactQuery.CONTACT_PROJECTION_PRIMARY));
+ updateDisplayedSelections();
}
public void setAccount(AccountWithDataSet account) {
@@ -315,11 +362,25 @@
}
// Save the checked state for the current account.
+ storeCurrentSelections();
+ mSelectedAccount = account;
+ updateDisplayedSelections();
+ }
+
+ public void storeCurrentSelections() {
if (mSelectedAccount != null) {
mPerAccountCheckedIds.put(mSelectedAccount, getSelectedContactIds());
}
+ }
- mSelectedAccount = account;
+ public Map<AccountWithDataSet, TreeSet<Long>> getSelectedIds() {
+ return mPerAccountCheckedIds;
+ }
+
+ private void updateDisplayedSelections() {
+ if (mContacts == null) {
+ return;
+ }
TreeSet<Long> checked = mPerAccountCheckedIds.get(mSelectedAccount);
if (checked == null) {
@@ -344,24 +405,12 @@
return selected;
}
- public void selectAll() {
- if (mContacts == null) return;
-
- final TreeSet<Long> selected = new TreeSet<>();
- for (SimContact contact : mContacts) {
- if (!existsInCurrentAccount(contact)) {
- selected.add(contact.getId());
- }
+ public void setSelectionsForAccount(AccountWithDataSet account, long[] contacts) {
+ final TreeSet<Long> selected = new TreeSet<>(Longs.asList(contacts));
+ mPerAccountCheckedIds.put(account, selected);
+ if (account.equals(mSelectedAccount)) {
+ updateDisplayedSelections();
}
- setSelectedContactIds(selected);
- }
-
- public void select(long[] contacts) {
- final TreeSet<Long> selected = new TreeSet<>();
- for (long contact : contacts) {
- selected.add(contact);
- }
- setSelectedContactIds(selected);
}
public boolean existsInCurrentAccount(int position) {
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 47fc2a3..0bf7908 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -825,9 +825,13 @@
R.id.contacts_list_container, mMembersFragment, TAG_GROUP_VIEW);
} else if (isAssistantView()) {
Fragment uiFragment = fragmentManager.findFragmentByTag(TAG_ASSISTANT);
+ Fragment unavailableFragment = fragmentManager.findFragmentByTag(TAG_UNAVAILABLE);
if (uiFragment == null) {
uiFragment = ObjectFactory.getAssistantFragment();
}
+ if (unavailableFragment != null) {
+ transaction.remove(unavailableFragment);
+ }
transaction.replace(R.id.contacts_list_container, uiFragment, TAG_ASSISTANT);
resetToolBarStatusBarColor();
}
diff --git a/src/com/android/contacts/common/CallUtil.java b/src/com/android/contacts/common/CallUtil.java
index 88fca92..acfad52 100644
--- a/src/com/android/contacts/common/CallUtil.java
+++ b/src/com/android/contacts/common/CallUtil.java
@@ -20,6 +20,7 @@
import com.android.contacts.common.compat.PhoneAccountSdkCompat;
import com.android.contacts.common.util.PermissionsUtil;
import com.android.contacts.common.util.PhoneNumberHelper;
+import com.android.contactsbind.FeedbackHelper;
import com.android.phone.common.PhoneConstants;
import android.content.Context;
@@ -41,6 +42,8 @@
*/
public class CallUtil {
+ public static final String TAG = "CallUtil";
+
/**
* Indicates that the video calling is not available.
*/
@@ -140,26 +143,32 @@
return VIDEO_CALLING_DISABLED;
}
- List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts();
- for (PhoneAccountHandle accountHandle : accountHandles) {
- PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle);
- if (account != null) {
- if (account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
- // Builds prior to N do not have presence support.
- if (!CompatUtils.isVideoPresenceCompatible()) {
- return VIDEO_CALLING_ENABLED;
- }
+ try {
+ List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts();
+ for (PhoneAccountHandle accountHandle : accountHandles) {
+ PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle);
+ if (account != null) {
+ if (account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
+ // Builds prior to N do not have presence support.
+ if (!CompatUtils.isVideoPresenceCompatible()) {
+ return VIDEO_CALLING_ENABLED;
+ }
- int videoCapabilities = VIDEO_CALLING_ENABLED;
- if (account.hasCapabilities(
- PhoneAccountSdkCompat.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
- videoCapabilities |= VIDEO_CALLING_PRESENCE;
+ int videoCapabilities = VIDEO_CALLING_ENABLED;
+ if (account.hasCapabilities(PhoneAccountSdkCompat
+ .CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
+ videoCapabilities |= VIDEO_CALLING_PRESENCE;
+ }
+ return videoCapabilities;
}
- return videoCapabilities;
}
}
+ return VIDEO_CALLING_DISABLED;
+ } catch (SecurityException e) {
+ FeedbackHelper.sendFeedback(context, TAG,
+ "Security exception when querying intent activities", e);
+ return VIDEO_CALLING_DISABLED;
}
- return VIDEO_CALLING_DISABLED;
}
/**
diff --git a/src/com/android/contacts/common/database/SimContactDao.java b/src/com/android/contacts/common/database/SimContactDao.java
index 8805c52..3175ce4 100644
--- a/src/com/android/contacts/common/database/SimContactDao.java
+++ b/src/com/android/contacts/common/database/SimContactDao.java
@@ -24,7 +24,6 @@
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.RemoteException;
import android.provider.BaseColumns;
@@ -40,14 +39,12 @@
import android.util.SparseArray;
import com.android.contacts.R;
-import com.android.contacts.common.Experiments;
import com.android.contacts.common.compat.CompatUtils;
import com.android.contacts.common.model.SimCard;
import com.android.contacts.common.model.SimContact;
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.util.PermissionsUtil;
import com.android.contacts.util.SharedPreferenceUtil;
-import com.android.contactsbind.experiments.Flags;
import com.google.common.base.Joiner;
import java.util.ArrayList;
@@ -97,17 +94,6 @@
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
- public void warmupSimQueryIfNeeded() {
- if (!canReadSimContacts()) return;
-
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- getSimCardsWithContacts();
- return null;
- }
- }.execute();
- }
public Context getContext() {
return mContext;
@@ -279,13 +265,19 @@
return contacts != null ? contacts : loadContactsForSim(sim);
}
+ // See b/32831092
+ // Sometimes the SIM contacts provider seems to get stuck if read from multiple threads
+ // concurrently. So we just have a global lock around it to prevent potential issues.
+ private static final Object SIM_READ_LOCK = new Object();
private ArrayList<SimContact> loadFrom(Uri uri) {
- final Cursor cursor = mResolver.query(uri, null, null, null, null);
+ synchronized (SIM_READ_LOCK) {
+ final Cursor cursor = mResolver.query(uri, null, null, null, null);
- try {
- return loadFromCursor(cursor);
- } finally {
- cursor.close();
+ try {
+ return loadFromCursor(cursor);
+ } finally {
+ cursor.close();
+ }
}
}
@@ -423,10 +415,6 @@
}
@Override
- public void warmupSimQueryIfNeeded() {
- }
-
- @Override
public List<SimCard> getSimCards() {
return SharedPreferenceUtil.restoreSimStates(getContext(), mSimCards);
}
diff --git a/src/com/android/contacts/common/interactions/ImportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportDialogFragment.java
index db7f621..a748b81 100644
--- a/src/com/android/contacts/common/interactions/ImportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ImportDialogFragment.java
@@ -25,9 +25,6 @@
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;
-import android.support.v4.text.TextUtilsCompat;
-import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -54,12 +51,11 @@
/**
* An dialog invoked to import/export contacts.
*/
-public class ImportDialogFragment extends DialogFragment
- implements SelectAccountDialogFragment.Listener {
+public class ImportDialogFragment extends DialogFragment {
public static final String TAG = "ImportDialogFragment";
- private static final String KEY_RES_ID = "resourceId";
- private static final String KEY_SUBSCRIPTION_ID = "subscriptionId";
+ public static final String KEY_RES_ID = "resourceId";
+ public static final String KEY_SUBSCRIPTION_ID = "subscriptionId";
public static final String EXTRA_SIM_ONLY = "extraSimOnly";
@@ -178,20 +174,16 @@
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- boolean dismissDialog;
final int resId = adapter.getItem(which).mChoiceResourceId;
if (resId == R.string.import_from_sim) {
- dismissDialog = handleSimImportRequest(adapter.getItem(which).mSim);
+ handleSimImportRequest(adapter.getItem(which).mSim);
} else if (resId == R.string.import_from_vcf_file) {
- dismissDialog = handleImportRequest(resId, SimCard.NO_SUBSCRIPTION_ID);
+ handleImportRequest(resId, SimCard.NO_SUBSCRIPTION_ID);
} else {
- dismissDialog = true;
Log.e(TAG, "Unexpected resource: "
+ getActivity().getResources().getResourceEntryName(resId));
}
- if (dismissDialog) {
- dialog.dismiss();
- }
+ dialog.dismiss();
}
};
@@ -238,18 +230,15 @@
}
}
- private boolean handleSimImportRequest(SimCard sim) {
+ private void handleSimImportRequest(SimCard sim) {
SimImportFragment.newInstance(sim.getSubscriptionId()).show(getFragmentManager(),
"SimImport");
- return true;
}
/**
* Handle "import from SD".
- *
- * @return {@code true} if the dialog show be closed. {@code false} otherwise.
*/
- private boolean handleImportRequest(int resId, int subscriptionId) {
+ private void handleImportRequest(int resId, int subscriptionId) {
// There are three possibilities:
// - more than one accounts -> ask the user
// - just one account -> use the account without asking the user
@@ -263,39 +252,13 @@
args.putInt(KEY_RES_ID, resId);
args.putInt(KEY_SUBSCRIPTION_ID, subscriptionId);
SelectAccountDialogFragment.show(
- getFragmentManager(), this,
- R.string.dialog_new_contact_account,
+ getFragmentManager(), R.string.dialog_new_contact_account,
AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, args);
-
- // In this case, because this DialogFragment is used as a target fragment to
- // SelectAccountDialogFragment, we can't close it yet. We close the dialog when
- // we get a callback from it.
- return false;
+ } else {
+ AccountSelectionUtil.doImport(getActivity(), resId,
+ (size == 1 ? accountList.get(0) : null),
+ (CompatUtils.isMSIMCompatible() ? subscriptionId : -1));
}
-
- AccountSelectionUtil.doImport(getActivity(), resId,
- (size == 1 ? accountList.get(0) : null),
- (CompatUtils.isMSIMCompatible() ? subscriptionId : -1));
- return true; // Close the dialog.
- }
-
- /**
- * Called when an account is selected on {@link SelectAccountDialogFragment}.
- */
- @Override
- public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
- AccountSelectionUtil.doImport(getActivity(), extraArgs.getInt(KEY_RES_ID),
- account, extraArgs.getInt(KEY_SUBSCRIPTION_ID));
-
- // At this point the dialog is still showing (which is why we can use getActivity() above)
- // So close it.
- dismiss();
- }
-
- @Override
- public void onAccountSelectorCancelled() {
- // See onAccountChosen() -- at this point the dialog is still showing. Close it.
- dismiss();
}
private CharSequence getSimDescription(SimCard sim, int index) {
diff --git a/src/com/android/contacts/common/model/account/BaseAccountType.java b/src/com/android/contacts/common/model/account/BaseAccountType.java
index 8d8b8e4..400b0e9 100644
--- a/src/com/android/contacts/common/model/account/BaseAccountType.java
+++ b/src/com/android/contacts/common/model/account/BaseAccountType.java
@@ -947,24 +947,24 @@
kinds.add(kn);
kn.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
- FLAGS_PERSON_NAME).setLongForm(true));
+ FLAGS_PERSON_NAME).setOptional(true));
if (!displayOrderPrimary) {
kn.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
FLAGS_PERSON_NAME));
kn.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
- FLAGS_PERSON_NAME).setLongForm(true));
+ FLAGS_PERSON_NAME).setOptional(true));
kn.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
FLAGS_PERSON_NAME));
} else {
kn.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
FLAGS_PERSON_NAME));
kn.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
- FLAGS_PERSON_NAME).setLongForm(true));
+ FLAGS_PERSON_NAME).setOptional(true));
kn.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
FLAGS_PERSON_NAME));
}
kn.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
- FLAGS_PERSON_NAME).setLongForm(true));
+ FLAGS_PERSON_NAME).setOptional(true));
// Phonetic name
final DataKind kp = newDataKind(context, parser, attrs, true,
diff --git a/src/com/android/contacts/common/preference/ContactsPreferenceActivity.java b/src/com/android/contacts/common/preference/ContactsPreferenceActivity.java
index 030575d..4bdb12f 100644
--- a/src/com/android/contacts/common/preference/ContactsPreferenceActivity.java
+++ b/src/com/android/contacts/common/preference/ContactsPreferenceActivity.java
@@ -34,15 +34,19 @@
import android.view.ViewGroup;
import com.android.contacts.common.R;
+import com.android.contacts.common.interactions.ImportDialogFragment;
import com.android.contacts.common.list.ProviderStatusWatcher;
+import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.preference.DisplayOptionsPreferenceFragment.ProfileListener;
import com.android.contacts.common.preference.DisplayOptionsPreferenceFragment.ProfileQuery;
+import com.android.contacts.common.util.AccountSelectionUtil;
+import com.android.contacts.editor.SelectAccountDialogFragment;
/**
* Contacts settings.
*/
-public final class ContactsPreferenceActivity extends PreferenceActivity implements
- ProfileListener {
+public final class ContactsPreferenceActivity extends PreferenceActivity
+ implements ProfileListener, SelectAccountDialogFragment.Listener {
private static final String TAG_ABOUT = "about_contacts";
private static final String TAG_DISPLAY_OPTIONS = "display_options";
@@ -210,4 +214,14 @@
getFragmentManager().findFragmentByTag(TAG_DISPLAY_OPTIONS);
fragment.updateMyInfoPreference(hasProfile, displayName, contactId);
}
+
+ @Override
+ public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
+ AccountSelectionUtil.doImport(this, extraArgs.getInt(ImportDialogFragment
+ .KEY_RES_ID), account, extraArgs.getInt(ImportDialogFragment.KEY_SUBSCRIPTION_ID));
+ }
+
+ @Override
+ public void onAccountSelectorCancelled() {
+ }
}
diff --git a/src/com/android/contacts/editor/AccountHeaderPresenter.java b/src/com/android/contacts/editor/AccountHeaderPresenter.java
index 5323c60..d4f613b 100644
--- a/src/com/android/contacts/editor/AccountHeaderPresenter.java
+++ b/src/com/android/contacts/editor/AccountHeaderPresenter.java
@@ -76,6 +76,8 @@
public AccountHeaderPresenter(View container) {
mContext = container.getContext();
mAccountHeaderContainer = container;
+ // mAccountHeaderType is optional and may not be in the container view in which case
+ // the variable will be null
mAccountHeaderType = (TextView) container.findViewById(R.id.account_type);
mAccountHeaderName = (TextView) container.findViewById(R.id.account_name);
mAccountHeaderIcon = (ImageView) container.findViewById(R.id.account_type_icon);
@@ -144,7 +146,9 @@
// Set the account type
final String selectorTitle = mContext.getResources().getString(mSelectorTitle);
- mAccountHeaderType.setText(selectorTitle);
+ if (mAccountHeaderType != null) {
+ mAccountHeaderType.setText(selectorTitle);
+ }
// Set the icon
final AccountDisplayInfo displayInfo = mAccountDisplayInfoFactory
diff --git a/src/com/android/contacts/editor/SelectAccountDialogFragment.java b/src/com/android/contacts/editor/SelectAccountDialogFragment.java
index 34fac4f..4335239 100644
--- a/src/com/android/contacts/editor/SelectAccountDialogFragment.java
+++ b/src/com/android/contacts/editor/SelectAccountDialogFragment.java
@@ -20,7 +20,6 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
-import android.app.Fragment;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.os.Bundle;
@@ -48,22 +47,18 @@
* Show the dialog.
*
* @param fragmentManager {@link FragmentManager}.
- * @param targetFragment {@link Fragment} that implements {@link Listener}.
* @param titleResourceId resource ID to use as the title.
* @param accountListFilter account filter.
* @param extraArgs Extra arguments, which will later be passed to
* {@link Listener#onAccountChosen}. {@code null} will be converted to
* {@link Bundle#EMPTY}.
*/
- public static <F extends Fragment & Listener> void show(FragmentManager fragmentManager,
- F targetFragment, int titleResourceId,
+ public static void show(FragmentManager fragmentManager, int titleResourceId,
AccountListFilter accountListFilter, Bundle extraArgs) {
- show(fragmentManager, targetFragment, titleResourceId, accountListFilter, extraArgs,
- /* tag */ null);
+ show(fragmentManager, titleResourceId, accountListFilter, extraArgs, /* tag */ null);
}
- public static <F extends Fragment & Listener> void show(FragmentManager fragmentManager,
- F targetFragment, int titleResourceId,
+ public static void show(FragmentManager fragmentManager, int titleResourceId,
AccountListFilter accountListFilter, Bundle extraArgs, String tag) {
final Bundle args = new Bundle();
args.putInt(KEY_TITLE_RES_ID, titleResourceId);
@@ -72,9 +67,6 @@
final SelectAccountDialogFragment instance = new SelectAccountDialogFragment();
instance.setArguments(args);
- if (targetFragment != null) {
- instance.setTargetFragment(targetFragment, 0);
- }
instance.show(fragmentManager, tag);
}
@@ -115,14 +107,8 @@
}
}
- @Override
- public void onSaveInstanceState(Bundle b) {
- setTargetFragment(null, -1);
- super.onSaveInstanceState(b);
- }
-
/**
- * Calls {@link Listener#onAccountChosen} of {@code targetFragment}.
+ * Calls {@link Listener#onAccountChosen}.
*/
private void onAccountSelected(AccountWithDataSet account) {
final Listener listener = getListener();
@@ -133,14 +119,9 @@
private Listener getListener() {
Listener listener = null;
- final Fragment targetFragment = getTargetFragment();
- if (targetFragment == null) {
- final Activity activity = getActivity();
- if (activity != null && activity instanceof Listener) {
- listener = (Listener) activity;
- }
- } else if (targetFragment instanceof Listener) {
- listener = (Listener) targetFragment;
+ final Activity activity = getActivity();
+ if (activity != null && activity instanceof Listener) {
+ listener = (Listener) activity;
}
return listener;
}
diff --git a/src/com/android/contacts/list/JoinContactListFragment.java b/src/com/android/contacts/list/JoinContactListFragment.java
index d961f34..d827eb5 100644
--- a/src/com/android/contacts/list/JoinContactListFragment.java
+++ b/src/com/android/contacts/list/JoinContactListFragment.java
@@ -146,7 +146,7 @@
@Override
public JoinContactListAdapter createListAdapter() {
JoinContactListAdapter adapter = new JoinContactListAdapter(getActivity());
- adapter.setPhotoPosition(ContactListItemView.getDefaultPhotoPosition(true /* opposite */));
+ adapter.setPhotoPosition(ContactListItemView.getDefaultPhotoPosition(false /* opposite */));
return adapter;
}
diff --git a/src/com/android/contacts/list/MultiSelectEmailAddressesListAdapter.java b/src/com/android/contacts/list/MultiSelectEmailAddressesListAdapter.java
index b225ba4..af9ee52 100644
--- a/src/com/android/contacts/list/MultiSelectEmailAddressesListAdapter.java
+++ b/src/com/android/contacts/list/MultiSelectEmailAddressesListAdapter.java
@@ -160,7 +160,6 @@
cursor.moveToPosition(position);
bindViewId(view, cursor, EmailQuery.EMAIL_ID);
- bindSectionHeaderAndDivider(view, position);
if (isFirstEntry) {
bindName(view, cursor);
bindQuickContact(view, partition, cursor, EmailQuery.PHOTO_ID,
@@ -190,16 +189,6 @@
view.showData(cursor, EmailQuery.EMAIL_ADDRESS);
}
- protected void bindSectionHeaderAndDivider(final ContactListItemView view, int position) {
- final int section = getSectionForPosition(position);
- if (getPositionForSection(section) == position) {
- final String title = (String)getSections()[section];
- view.setSectionHeader(title);
- } else {
- view.setSectionHeader(null);
- }
- }
-
protected void bindName(final ContactListItemView view, Cursor cursor) {
view.showDisplayName(cursor, EmailQuery.DISPLAY_NAME, getContactNameDisplayOrder());
}
diff --git a/src/com/android/contacts/list/MultiSelectEmailAddressesListFragment.java b/src/com/android/contacts/list/MultiSelectEmailAddressesListFragment.java
index d14488a..956e473 100644
--- a/src/com/android/contacts/list/MultiSelectEmailAddressesListFragment.java
+++ b/src/com/android/contacts/list/MultiSelectEmailAddressesListFragment.java
@@ -38,7 +38,7 @@
public MultiSelectEmailAddressesListFragment() {
setPhotoLoaderEnabled(true);
- setSectionHeaderDisplayEnabled(true);
+ setSectionHeaderDisplayEnabled(false);
setSearchMode(false);
setHasOptionsMenu(true);
setListType(ListEvent.ListType.PICK_EMAIL);
diff --git a/src/com/android/contacts/list/MultiSelectPhoneNumbersListAdapter.java b/src/com/android/contacts/list/MultiSelectPhoneNumbersListAdapter.java
index b3574ab..985809b 100644
--- a/src/com/android/contacts/list/MultiSelectPhoneNumbersListAdapter.java
+++ b/src/com/android/contacts/list/MultiSelectPhoneNumbersListAdapter.java
@@ -160,7 +160,6 @@
cursor.moveToPosition(position);
bindViewId(view, cursor, PhoneQuery.PHONE_ID);
- bindSectionHeaderAndDivider(view, position);
if (isFirstEntry) {
bindName(view, cursor);
bindQuickContact(view, partition, cursor, PhoneQuery.PHOTO_ID,
@@ -190,15 +189,6 @@
view.showData(cursor, PhoneQuery.PHONE_NUMBER);
}
- protected void bindSectionHeaderAndDivider(final ContactListItemView view, int position) {
- if (isSectionHeaderDisplayEnabled()) {
- Placement placement = getItemPlacementInSection(position);
- view.setSectionHeader(placement.firstInSection ? placement.sectionHeader : null);
- } else {
- view.setSectionHeader(null);
- }
- }
-
protected void bindName(final ContactListItemView view, Cursor cursor) {
view.showDisplayName(cursor, PhoneQuery.DISPLAY_NAME, getContactNameDisplayOrder());
}
diff --git a/src/com/android/contacts/list/MultiSelectPhoneNumbersListFragment.java b/src/com/android/contacts/list/MultiSelectPhoneNumbersListFragment.java
index 5a1a761..751449b 100644
--- a/src/com/android/contacts/list/MultiSelectPhoneNumbersListFragment.java
+++ b/src/com/android/contacts/list/MultiSelectPhoneNumbersListFragment.java
@@ -38,7 +38,7 @@
public MultiSelectPhoneNumbersListFragment() {
setPhotoLoaderEnabled(true);
- setSectionHeaderDisplayEnabled(true);
+ setSectionHeaderDisplayEnabled(false);
setSearchMode(false);
setHasOptionsMenu(true);
setListType(ListEvent.ListType.PICK_PHONE);