summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Garnes <matt@cyngn.com>2015-04-30 11:17:19 -0700
committerMatt Garnes <matt@cyngn.com>2015-04-30 11:17:19 -0700
commitaaa411b7f1294089da76732cb5b21da467e48422 (patch)
treeb51f4f45c46917dfb631186538901ca13f940a54
parent61899450eb05c33835d3df99e6c75b3115c559ea (diff)
parent77e9bb4ba4b9b49b95a26d80ead59aa37d016232 (diff)
downloadandroid_packages_apps_Dialer-caf/cm-12.1.tar.gz
android_packages_apps_Dialer-caf/cm-12.1.tar.bz2
android_packages_apps_Dialer-caf/cm-12.1.zip
Merge remote-tracking branch 'caf/LA.BR.1.2.3_1' into caf/cm-12.1caf/cm-12.1
-rw-r--r--res/layout/call_log_list_item.xml1
-rw-r--r--res/values-zh-rCN/strings.xml1
-rw-r--r--res/values/styles.xml3
-rwxr-xr-x[-rw-r--r--]src/com/android/dialer/DialtactsActivity.java66
-rwxr-xr-x[-rw-r--r--]src/com/android/dialer/PhoneCallDetailsHelper.java23
-rwxr-xr-xsrc/com/android/dialer/SpeedDialListActivity.java3
-rwxr-xr-xsrc/com/android/dialer/calllog/CallLogActivity.java22
-rwxr-xr-xsrc/com/android/dialer/calllog/CallLogAdapter.java153
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapterHelper.java13
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java3
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemHelper.java19
-rw-r--r--src/com/android/dialer/calllog/ClearCallLogDialog.java12
-rw-r--r--src/com/android/dialer/calllog/PhoneAccountUtils.java8
-rwxr-xr-xsrc/com/android/dialer/dialpad/DialpadFragment.java77
-rw-r--r--src/com/android/dialer/list/ListsFragment.java7
-rw-r--r--src/com/android/dialer/list/PhoneFavoritesTileAdapter.java5
-rw-r--r--src/com/android/dialer/list/SearchFragment.java23
-rw-r--r--src/com/android/dialer/list/ShortcutCardsAdapter.java1
-rw-r--r--src/com/android/dialer/list/SpeedDialFragment.java22
-rw-r--r--src/com/android/dialer/util/DialerUtils.java2
-rw-r--r--src/com/android/dialer/widget/OverlappingPaneLayout.java17
-rw-r--r--src/com/android/dialer/widget/ViewDragHelper.java14
-rwxr-xr-x[-rw-r--r--]tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java2
-rwxr-xr-x[-rw-r--r--]tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java2
-rw-r--r--tests/src/com/android/dialer/widget/ActionBarControllerTest.java39
25 files changed, 421 insertions, 117 deletions
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index 12376271c..3841dcd39 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -119,7 +119,6 @@
android:layout_height="@dimen/call_provider_small_icon_size"
android:layout_marginEnd="@dimen/call_log_icon_margin"
android:layout_gravity="center_vertical"
- android:tint="?attr/call_log_secondary_text_color"
android:scaleType="centerInside"
android:visibility="gone"
/>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index afc95ccf3..d9c9e635f 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -50,6 +50,7 @@
<string name="call_log_incoming_header" msgid="2787722299753674684">"只显示来电"</string>
<string name="call_log_outgoing_header" msgid="761009180766735769">"只显示外拨电话"</string>
<string name="call_log_missed_header" msgid="8017148056610855956">"只显示未接来电"</string>
+ <string name="call_log_blacklist_header">只显示黑名单来电</string>
<string name="voicemail_status_voicemail_not_available" msgid="3021980206152528883">"无法连接到语音信箱服务器。"</string>
<string name="voicemail_status_messages_waiting" msgid="7113421459602803605">"无法连接到语音信箱服务器。新的语音邮件正在等待接收。"</string>
<string name="voicemail_status_configure_voicemail" msgid="3738537770636895689">"设置您的语音信箱。"</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c17bea9bb..d895b7a91 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -103,7 +103,7 @@
<style name="DialtactsActivityTheme" parent="DialtactsTheme">
<item name="android:actionBarStyle">@style/DialtactsActionBarWithoutTitleStyle</item>
<item name="android:fastScrollThumbDrawable">@drawable/fastscroll_thumb</item>
-
+ <item name="android:fastScrollTrackDrawable">@null</item>
</style>
<!-- A theme for inflation of spinners in the dialtacts action bar -->
<style name="DialtactsSpinnerTheme" parent="DialtactsTheme">
@@ -154,6 +154,7 @@
<item name="android:height">@dimen/action_bar_height_large</item>
<!-- Override ActionBar title offset to keep search box aligned left -->
<item name="android:contentInsetStart">0px</item>
+ <item name="android:contentInsetEnd">0px</item>
</style>
<!-- Text in the action bar at the top of the screen -->
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index b5645d5e9..475d398ae 100644..100755
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -187,6 +187,11 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
*/
private ListsFragment mListsFragment;
+ /**
+ * Tracks whether onSaveInstanceState has been called. If true, no fragment transactions can
+ * be commited.
+ */
+ private boolean mStateSaved;
private boolean mInDialpadSearch;
private boolean mInRegularSearch;
private boolean mClearSearchOnPause;
@@ -236,6 +241,12 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
private int mActionBarHeight;
+ /**
+ * The text returned from a voice search query. Set in {@link #onActivityResult} and used in
+ * {@link #onResume()} to populate the search box.
+ */
+ private String mVoiceSearchQuery;
+
private class OptionsPopupMenu extends PopupMenu {
public OptionsPopupMenu(Context context, View anchor) {
super(context, anchor, Gravity.END);
@@ -483,6 +494,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
@Override
protected void onResume() {
super.onResume();
+ mStateSaved = false;
if (mFirstLaunch) {
displayFragment(getIntent());
} else if (!phoneIsInUse() && mInCallDialpadUp) {
@@ -492,6 +504,16 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
showDialpadFragment(false);
mShowDialpadOnResume = false;
}
+
+ // If there was a voice query result returned in the {@link #onActivityResult} callback, it
+ // will have been stashed in mVoiceSearchQuery since the search results fragment cannot be
+ // shown until onResume has completed. Active the search UI and set the search term now.
+ if (!TextUtils.isEmpty(mVoiceSearchQuery)) {
+ mActionBarController.onSearchBoxTapped();
+ mSearchView.setText(mVoiceSearchQuery);
+ mVoiceSearchQuery = null;
+ }
+
mFirstLaunch = false;
prepareVoiceSearchButton();
mDialerDatabaseHelper.startSmartDialUpdateThread();
@@ -506,6 +528,9 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
hideDialpadAndSearchUi();
mClearSearchOnPause = false;
}
+ if (mSlideOut.hasStarted() && !mSlideOut.hasEnded()) {
+ commitDialpadFragmentHide();
+ }
super.onPause();
}
@@ -518,6 +543,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
outState.putBoolean(KEY_FIRST_LAUNCH, mFirstLaunch);
outState.putBoolean(KEY_IS_DIALPAD_SHOWN, mIsDialpadShown);
mActionBarController.saveInstanceState(outState);
+ mStateSaved = true;
}
@Override
@@ -645,7 +671,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
RecognizerIntent.EXTRA_RESULTS);
if (matches.size() > 0) {
final String match = matches.get(0);
- mSearchView.setText(match);
+ mVoiceSearchQuery = match;
} else {
Log.e(TAG, "Voice search - nothing heard");
}
@@ -732,7 +758,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
* @see #onDialpadShown
*/
private void showDialpadFragment(boolean animate) {
- if (mIsDialpadShown) {
+ if (mIsDialpadShown || mStateSaved) {
return;
}
mIsDialpadShown = true;
@@ -818,10 +844,11 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
* Finishes hiding the dialpad fragment after any animations are completed.
*/
public void commitDialpadFragmentHide() {
- final FragmentTransaction ft = getFragmentManager().beginTransaction();
- ft.hide(mDialpadFragment);
- ft.commit();
-
+ if (!mStateSaved && !mDialpadFragment.isHidden()) {
+ final FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.hide(mDialpadFragment);
+ ft.commit();
+ }
mFloatingActionButtonController.scaleIn(AnimUtils.NO_DELAY);
}
@@ -940,6 +967,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
@Override
public void onNewIntent(Intent newIntent) {
setIntent(newIntent);
+ mStateSaved = false;
displayFragment(newIntent);
invalidateOptionsMenu();
@@ -974,7 +1002,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
* Shows the search fragment
*/
private void enterSearchUi(boolean smartDialSearch, String query) {
- if (getFragmentManager().isDestroyed()) {
+ if (mStateSaved || getFragmentManager().isDestroyed()) {
// Weird race condition where fragment is doing work after the activity is destroyed
// due to talkback being on (b/10209937). Just return since we can't do any
// constructive here.
@@ -1027,7 +1055,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
*/
private void exitSearchUi() {
// See related bug in enterSearchUI();
- if (getFragmentManager().isDestroyed() || !isSafeToCommitTransactions()) {
+ if (getFragmentManager().isDestroyed() || mStateSaved) {
return;
}
@@ -1064,6 +1092,10 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
mDialpadFragment.hideAndClearDialConference();
}
+ if (mStateSaved) {
+ return;
+ }
+
if (mIsDialpadShown || mIsRecipientsShown) {
if (TextUtils.isEmpty(mSearchQuery) ||
(mSmartDialSearchFragment != null && mSmartDialSearchFragment.isVisible()
@@ -1162,8 +1194,22 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
}
public static Intent getAddNumberToContactIntent(CharSequence text) {
- final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.putExtra(Intents.Insert.PHONE, text);
+ return getAddToContactIntent(null /* name */, text /* phoneNumber */,
+ -1 /* phoneNumberType */);
+ }
+
+ public static Intent getAddToContactIntent(CharSequence name, CharSequence phoneNumber,
+ int phoneNumberType) {
+ Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ intent.putExtra(Intents.Insert.PHONE, phoneNumber);
+ // Only include the name and phone type extras if they are specified (the method
+ // getAddNumberToContactIntent does not use them).
+ if (name != null) {
+ intent.putExtra(Intents.Insert.NAME, name);
+ }
+ if (phoneNumberType != -1) {
+ intent.putExtra(Intents.Insert.PHONE_TYPE, phoneNumberType);
+ }
intent.setType(Contacts.CONTENT_ITEM_TYPE);
return intent;
}
diff --git a/src/com/android/dialer/PhoneCallDetailsHelper.java b/src/com/android/dialer/PhoneCallDetailsHelper.java
index f6ae7da41..1956085c5 100644..100755
--- a/src/com/android/dialer/PhoneCallDetailsHelper.java
+++ b/src/com/android/dialer/PhoneCallDetailsHelper.java
@@ -16,6 +16,7 @@
package com.android.dialer;
+import android.content.Context;
import android.content.res.Resources;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
@@ -50,6 +51,7 @@ public class PhoneCallDetailsHelper {
/** The maximum number of icons will be shown to represent the call types in a group. */
private static final int MAX_CALL_TYPE_ICONS = 3;
+ private final Context mContext;
private final Resources mResources;
/** The injected current time in milliseconds since the epoch. Used only by tests. */
private Long mCurrentTimeMillisForTest;
@@ -69,8 +71,9 @@ public class PhoneCallDetailsHelper {
*
* @param resources used to look up strings
*/
- public PhoneCallDetailsHelper(Resources resources, CallTypeHelper callTypeHelper,
+ public PhoneCallDetailsHelper(Context context, Resources resources,
PhoneNumberUtilsWrapper phoneUtils) {
+ mContext = context;
mResources = resources;
mPhoneNumberUtilsWrapper = phoneUtils;
mPhoneNumberHelper = new PhoneNumberDisplayHelper(mPhoneNumberUtilsWrapper, resources);
@@ -129,6 +132,24 @@ public class PhoneCallDetailsHelper {
views.callAccountIcon.setVisibility(View.GONE);
}
+ /*
+ // Set the account label if it exists.
+ String accountLabel = details.accountLabel;
+ if (accountLabel != null) {
+ views.callAccountLabel.setVisibility(View.VISIBLE);
+ views.callAccountLabel.setText(accountLabel);
+ int color = PhoneAccountUtils.getAccountColor(mContext, details.accountHandle);
+ if (color == PhoneAccount.NO_HIGHLIGHT_COLOR) {
+ int defaultColor = R.color.dialtacts_secondary_text_color;
+ views.callAccountLabel.setTextColor(mContext.getResources().getColor(defaultColor));
+ } else {
+ views.callAccountLabel.setTextColor(color);
+ }
+ } else {
+ views.callAccountLabel.setVisibility(View.GONE);
+ }
+ */
+
CharSequence nameText;
CharSequence displayNumber =
mPhoneNumberHelper.getDisplayNumber(details.accountId, details.number,
diff --git a/src/com/android/dialer/SpeedDialListActivity.java b/src/com/android/dialer/SpeedDialListActivity.java
index d481bbab9..7ab8deecf 100755
--- a/src/com/android/dialer/SpeedDialListActivity.java
+++ b/src/com/android/dialer/SpeedDialListActivity.java
@@ -62,6 +62,7 @@ import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.QuickContactBadge;
import android.widget.TextView;
+import android.view.Gravity;
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
@@ -306,7 +307,7 @@ public class SpeedDialListActivity extends ListActivity implements
if (record == null) {
showAddSpeedDialDialog(number);
} else {
- PopupMenu pm = new PopupMenu(this, view);
+ PopupMenu pm = new PopupMenu(this, view, Gravity.START);
pm.getMenu().add(number, MENU_REPLACE, 0, R.string.speed_dial_replace);
pm.getMenu().add(number, MENU_DELETE, 0, R.string.speed_dial_delete);
pm.setOnMenuItemClickListener(this);
diff --git a/src/com/android/dialer/calllog/CallLogActivity.java b/src/com/android/dialer/calllog/CallLogActivity.java
index 78bd2e29b..2e55974fb 100755
--- a/src/com/android/dialer/calllog/CallLogActivity.java
+++ b/src/com/android/dialer/calllog/CallLogActivity.java
@@ -33,6 +33,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
+import android.view.ViewGroup;
import android.widget.SearchView;
import android.widget.SearchView.OnCloseListener;
import android.widget.SearchView.OnQueryTextListener;
@@ -76,17 +77,28 @@ public class CallLogActivity extends AnalyticsActivity implements
public Fragment getItem(int position) {
switch (position) {
case TAB_INDEX_MSIM:
- mMSimCallsFragment = new MSimCallLogFragment();
- mMSimCallsFragment.setHasOptionsMenu(true);
- return mMSimCallsFragment;
+ return new MSimCallLogFragment();
case TAB_INDEX_MSIM_STATS:
- mStatsFragment = new CallStatsFragment();
- return mStatsFragment;
+ return new CallStatsFragment();
}
throw new IllegalStateException("No fragment at position " + position);
}
@Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ final Object fragment = super.instantiateItem(container, position);
+ switch (position) {
+ case TAB_INDEX_MSIM:
+ mMSimCallsFragment = (MSimCallLogFragment)fragment;
+ break;
+ case TAB_INDEX_MSIM_STATS:
+ mStatsFragment = (CallStatsFragment)fragment;
+ break;
+ }
+ return fragment;
+ }
+
+ @Override
public CharSequence getPageTitle(int position) {
return mTabTitles[position];
}
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 65e149a47..01b07b68f 100755
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -20,16 +20,20 @@ import android.accounts.Account;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.Loader;
import android.content.res.Resources;
import android.database.Cursor;
+import android.database.sqlite.SQLiteFullException;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.CallLog.Calls;
+import android.provider.ContactsContract;
import android.provider.ContactsContract.PhoneLookup;
import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneNumberUtils;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.AccessibilityDelegate;
@@ -37,6 +41,8 @@ import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
@@ -45,6 +51,8 @@ import com.android.common.widget.GroupingListAdapter;
import com.android.contacts.common.CallUtil;
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
import com.android.contacts.common.util.UriUtils;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.PhoneCallDetails;
@@ -57,6 +65,7 @@ import com.android.dialer.calllog.CallLogAdapterHelper.NumberWithCountryIso;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -64,8 +73,10 @@ import java.util.LinkedList;
* Adapter class to fill in data for the Call Log.
*/
public class CallLogAdapter extends GroupingListAdapter
- implements CallLogAdapterHelper.Callback, CallLogGroupBuilder.GroupCreator {
+ implements CallLogAdapterHelper.Callback, CallLogGroupBuilder.GroupCreator,
+ OnScrollListener {
+ private static final String TAG = CallLogAdapter.class.getSimpleName();
private static final int VOICEMAIL_TRANSCRIPTION_MAX_LINES = 10;
/** The enumeration of {@link android.os.AsyncTask} objects used in this class. */
@@ -225,7 +236,6 @@ public class CallLogAdapter extends GroupingListAdapter
Toast.LENGTH_SHORT);
Resources resources = mContext.getResources();
- CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
mCallLogBackgroundColor = resources.getColor(R.color.background_dialer_list_items);
mExpandedBackgroundColor = resources.getColor(R.color.call_log_expanded_background_color);
mExpandedTranslationZ = resources.getDimension(R.dimen.call_log_expanded_translation_z);
@@ -235,7 +245,7 @@ public class CallLogAdapter extends GroupingListAdapter
mAdapterHelper = new CallLogAdapterHelper(context, this,
contactInfoHelper, mPhoneNumberHelper);
PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
- resources, callTypeHelper, new PhoneNumberUtilsWrapper());
+ mContext, resources, new PhoneNumberUtilsWrapper());
mCallLogViewsHelper =
new CallLogListItemHelper(
phoneCallDetailsHelper, mPhoneNumberHelper, resources);
@@ -463,7 +473,10 @@ public class CallLogAdapter extends GroupingListAdapter
Calls.DURATION_TYPE_ACTIVE, subId, operator);
}
- mCallLogViewsHelper.setPhoneCallDetails(mContext, views, details);
+ if (!mAdapterHelper.isBusy()) {
+ // Only update views when ListView's scroll state is not SCROLL_STATE_FLING.
+ mCallLogViewsHelper.setPhoneCallDetails(mContext, views, details);
+ }
int contactType = ContactPhotoManager.TYPE_DEFAULT;
@@ -529,10 +542,8 @@ public class CallLogAdapter extends GroupingListAdapter
* @return The day group for the call.
*/
private int getDayGroupForCall(long callId) {
- if (mDayGroups.containsKey(callId)) {
- return mDayGroups.get(callId);
- }
- return CallLogGroupBuilder.DAY_GROUP_NONE;
+ Integer result = mDayGroups.get(callId);
+ return result == null ? CallLogGroupBuilder.DAY_GROUP_NONE : result.intValue();
}
/**
* Determines if a call log row with the given Id is expanded.
@@ -736,7 +747,7 @@ public class CallLogAdapter extends GroupingListAdapter
}
protected void bindBadge(
- View view, ContactInfo info, final PhoneCallDetails details, int callType) {
+ View view, final ContactInfo info, final PhoneCallDetails details, int callType) {
// Do not show badge in call log.
if (!mIsCallLog) {
final ViewStub stub = (ViewStub) view.findViewById(R.id.link_stub);
@@ -749,14 +760,30 @@ public class CallLogAdapter extends GroupingListAdapter
mBadgeText = (TextView) inflated.findViewById(R.id.badge_text);
}
- mBadgeContainer.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- final Intent intent =
- DialtactsActivity.getAddNumberToContactIntent(details.number);
- mContext.startActivity(intent);
- }
- });
+ mBadgeContainer.setVisibility(View.VISIBLE);
+ mBadgeImageView = (ImageView) mBadgeContainer.findViewById(R.id.badge_image);
+ mBadgeText = (TextView) mBadgeContainer.findViewById(R.id.badge_text);
+
+ final View clickableArea = mBadgeContainer.findViewById(R.id.badge_link_container);
+ if (clickableArea != null) {
+ clickableArea.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // If no lookup uri is provided, we need to rely on what information
+ // we have available; namely the phone number and name.
+ if (info.lookupUri == null) {
+ final Intent intent =
+ DialtactsActivity.getAddToContactIntent(details.name,
+ details.number,
+ details.numberType);
+ DialerUtils.startActivityWithErrorToast(mContext, intent,
+ R.string.add_contact_not_available);
+ } else {
+ addContactFromLookupUri(info.lookupUri);
+ }
+ }
+ });
+ }
mBadgeImageView.setImageResource(R.drawable.ic_person_add_24dp);
mBadgeText.setText(R.string.recentCalls_addToContact);
} else {
@@ -835,14 +862,18 @@ public class CallLogAdapter extends GroupingListAdapter
if (!needsUpdate) return;
- if (countryIso == null) {
- mContext.getContentResolver().update(Calls.CONTENT_URI_WITH_VOICEMAIL, values,
- Calls.NUMBER + " = ? AND " + Calls.COUNTRY_ISO + " IS NULL",
- new String[]{ number });
- } else {
- mContext.getContentResolver().update(Calls.CONTENT_URI_WITH_VOICEMAIL, values,
- Calls.NUMBER + " = ? AND " + Calls.COUNTRY_ISO + " = ?",
- new String[]{ number, countryIso });
+ try {
+ if (countryIso == null) {
+ mContext.getContentResolver().update(Calls.CONTENT_URI_WITH_VOICEMAIL, values,
+ Calls.NUMBER + " = ? AND " + Calls.COUNTRY_ISO + " IS NULL",
+ new String[]{ number });
+ } else {
+ mContext.getContentResolver().update(Calls.CONTENT_URI_WITH_VOICEMAIL, values,
+ Calls.NUMBER + " = ? AND " + Calls.COUNTRY_ISO + " = ?",
+ new String[]{ number, countryIso });
+ }
+ } catch (SQLiteFullException e) {
+ Log.e(TAG, "Unable to update contact info in call log db", e);
}
}
@@ -1079,4 +1110,76 @@ public class CallLogAdapter extends GroupingListAdapter
public void setQueryString(String filter) {
mFilterString = filter;
}
+
+ /**
+ * Invokes the "add contact" activity given the expanded contact information stored in a
+ * lookup URI. This can include, for example, address and website information.
+ *
+ * @param lookupUri The lookup URI.
+ */
+ private void addContactFromLookupUri(Uri lookupUri) {
+ Contact contactToSave = ContactLoader.parseEncodedContactEntity(lookupUri);
+ if (contactToSave == null) {
+ return;
+ }
+
+ // Note: This code mirrors code in Contacts/QuickContactsActivity.
+ final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
+
+ ArrayList<ContentValues> values = contactToSave.getContentValues();
+ // Only pre-fill the name field if the provided display name is an nickname
+ // or better (e.g. structured name, nickname)
+ if (contactToSave.getDisplayNameSource()
+ >= ContactsContract.DisplayNameSources.NICKNAME) {
+ intent.putExtra(ContactsContract.Intents.Insert.NAME,
+ contactToSave.getDisplayName());
+ } else if (contactToSave.getDisplayNameSource()
+ == ContactsContract.DisplayNameSources.ORGANIZATION) {
+ // This is probably an organization. Instead of copying the organization
+ // name into a name entry, copy it into the organization entry. This
+ // way we will still consider the contact an organization.
+ final ContentValues organization = new ContentValues();
+ organization.put(ContactsContract.CommonDataKinds.Organization.COMPANY,
+ contactToSave.getDisplayName());
+ organization.put(ContactsContract.Data.MIMETYPE,
+ ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
+ values.add(organization);
+ }
+
+ // Last time used and times used are aggregated values from the usage stat
+ // table. They need to be removed from data values so the SQL table can insert
+ // properly
+ for (ContentValues value : values) {
+ value.remove(ContactsContract.Data.LAST_TIME_USED);
+ value.remove(ContactsContract.Data.TIMES_USED);
+ }
+ intent.putExtra(ContactsContract.Intents.Insert.DATA, values);
+
+ DialerUtils.startActivityWithErrorToast(mContext, intent,
+ R.string.add_contact_not_available);
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ switch (scrollState) {
+ case OnScrollListener.SCROLL_STATE_IDLE:
+ mAdapterHelper.setBusy(false);
+ dataSetChanged();
+ break;
+ case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
+ mAdapterHelper.setBusy(false);
+ break;
+ case OnScrollListener.SCROLL_STATE_FLING:
+ // Do not update views when scroll state is SCROLL_STATE_FLING
+ mAdapterHelper.setBusy(true);
+ break;
+ }
+ }
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ // no-op
+ }
}
diff --git a/src/com/android/dialer/calllog/CallLogAdapterHelper.java b/src/com/android/dialer/calllog/CallLogAdapterHelper.java
index a16935cfe..90b458442 100644
--- a/src/com/android/dialer/calllog/CallLogAdapterHelper.java
+++ b/src/com/android/dialer/calllog/CallLogAdapterHelper.java
@@ -137,6 +137,9 @@ public class CallLogAdapterHelper implements ViewTreeObserver.OnPreDrawListener
// Check if thread is finished, and if so return immediately.
if (mDone) return;
+ // only update contact info when scroll state is not fling.
+ if (mBusy) continue;
+
// Obtain next request, if any is available.
// Keep synchronized section small.
ContactInfoRequest req = null;
@@ -201,6 +204,8 @@ public class CallLogAdapterHelper implements ViewTreeObserver.OnPreDrawListener
/** Can be set to true by tests to disable processing of requests. */
private volatile boolean mRequestProcessingDisabled = false;
+ private boolean mBusy;
+
/**
* List of requests to update contact details.
* <p>
@@ -228,6 +233,14 @@ public class CallLogAdapterHelper implements ViewTreeObserver.OnPreDrawListener
}
};
+ public void setBusy(boolean isBusy) {
+ mBusy = isBusy;
+ }
+
+ public boolean isBusy(){
+ return mBusy;
+ }
+
/**
* Enqueues a request to look up the contact details for the given phone number.
* <p>
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index de1220dd0..4dc168556 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -312,6 +312,7 @@ public class CallLogFragment extends AnalyticsListFragment
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getListView().setEmptyView(view.findViewById(R.id.empty_list_view));
+ getListView().setOnScrollListener(mAdapter);
getListView().setItemsCanFocus(true);
maybeAddFooterView();
@@ -535,7 +536,7 @@ public class CallLogFragment extends AnalyticsListFragment
if (mFooterView == null) {
mFooterView = getActivity().getLayoutInflater().inflate(
- R.layout.recents_list_footer, (ViewGroup) getView(), false);
+ R.layout.recents_list_footer, getListView(), false);
mFooterView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index f4ea07e84..4e30cfdef 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.provider.CallLog.Calls;
import android.text.TextUtils;
+import android.util.Log;
import com.android.contacts.common.CallUtil;
import com.android.dialer.PhoneCallDetails;
@@ -30,6 +31,8 @@ import com.android.dialer.R;
* Helper class to fill in the views of a call log entry.
*/
/* package */class CallLogListItemHelper {
+ private static final String TAG = "CallLogListItemHelper";
+
/** Helper for populating the details of a phone call. */
private final PhoneCallDetailsHelper mPhoneCallDetailsHelper;
/** Helper for handling phone numbers. */
@@ -78,17 +81,25 @@ import com.android.dialer.R;
* @param views The views associated with the current call log entry.
*/
public void setActionContentDescriptions(CallLogListItemViews views) {
+ if (views.nameOrNumber == null) {
+ Log.e(TAG, "setActionContentDescriptions; name or number is null.");
+ }
+
+ // Calling expandTemplate with a null parameter will cause a NullPointerException.
+ // Although we don't expect a null name or number, it is best to protect against it.
+ CharSequence nameOrNumber = views.nameOrNumber == null ? "" : views.nameOrNumber;
+
views.callBackButtonView.setContentDescription(
- mResources.getString(R.string.description_call_back_action, views.nameOrNumber));
+ mResources.getString(R.string.description_call_back_action, nameOrNumber));
views.videoCallButtonView.setContentDescription(
- mResources.getString(R.string.description_video_call_action, views.nameOrNumber));
+ mResources.getString(R.string.description_video_call_action, nameOrNumber));
views.voicemailButtonView.setContentDescription(
- mResources.getString(R.string.description_voicemail_action, views.nameOrNumber));
+ mResources.getString(R.string.description_voicemail_action, nameOrNumber));
views.detailsButtonView.setContentDescription(
- mResources.getString(R.string.description_details_action, views.nameOrNumber));
+ mResources.getString(R.string.description_details_action, nameOrNumber));
}
/**
diff --git a/src/com/android/dialer/calllog/ClearCallLogDialog.java b/src/com/android/dialer/calllog/ClearCallLogDialog.java
index d6a1a10f9..ec28aec62 100644
--- a/src/com/android/dialer/calllog/ClearCallLogDialog.java
+++ b/src/com/android/dialer/calllog/ClearCallLogDialog.java
@@ -16,6 +16,7 @@
package com.android.dialer.calllog;
+import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
@@ -57,6 +58,7 @@ public class ClearCallLogDialog extends DialogFragment {
final ProgressDialog progressDialog = ProgressDialog.show(getActivity(),
getString(R.string.clearCallLogProgress_title),
"", true, false);
+ progressDialog.setOwnerActivity(getActivity());
final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
@@ -69,7 +71,15 @@ public class ClearCallLogDialog extends DialogFragment {
}
@Override
protected void onPostExecute(Void result) {
- progressDialog.dismiss();
+ final Activity activity = progressDialog.getOwnerActivity();
+
+ if (activity == null || activity.isDestroyed() || activity.isFinishing()) {
+ return;
+ }
+
+ if (progressDialog != null && progressDialog.isShowing()) {
+ progressDialog.dismiss();
+ }
}
};
// TODO: Once we have the API, we should configure this ProgressDialog
diff --git a/src/com/android/dialer/calllog/PhoneAccountUtils.java b/src/com/android/dialer/calllog/PhoneAccountUtils.java
index 11c1b178e..3493ce1d6 100644
--- a/src/com/android/dialer/calllog/PhoneAccountUtils.java
+++ b/src/com/android/dialer/calllog/PhoneAccountUtils.java
@@ -63,6 +63,14 @@ public class PhoneAccountUtils {
}
/**
+ * Extract account color from PhoneAccount object.
+ */
+ public static int getAccountColor(Context context, PhoneAccountHandle accountHandle) {
+ PhoneAccount account = getAccountOrNull(context, accountHandle);
+ return account == null ? PhoneAccount.NO_HIGHLIGHT_COLOR : account.getHighlightColor();
+ }
+
+ /**
* Retrieve the account metadata, but if the account does not exist or the device has only a
* single registered and enabled account, return null.
*/
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index 8c93309d8..d2e8ed0c7 100755
--- a/src/com/android/dialer/dialpad/DialpadFragment.java
+++ b/src/com/android/dialer/dialpad/DialpadFragment.java
@@ -94,6 +94,7 @@ import com.android.phone.common.dialpad.DialpadView;
import com.google.common.annotations.VisibleForTesting;
import java.util.HashSet;
+import java.util.Locale;
import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
@@ -395,6 +396,13 @@ public class DialpadFragment extends AnalyticsFragment
mDelete.setOnLongClickListener(this);
}
+ // Populate the overflow menu in onCreate instead of onResume to avoid PopupMenu's memory leak.
+ mOverflowMenuButton = mDialpadView.getOverflowMenuButton();
+ mOverflowPopupMenu = buildOptionsMenu(mOverflowMenuButton);
+ mOverflowMenuButton.setOnTouchListener(mOverflowPopupMenu.getDragToOpenListener());
+ mOverflowMenuButton.setOnClickListener(this);
+ mOverflowMenuButton.setVisibility(isDigitsEmpty() ? View.INVISIBLE : View.VISIBLE);
+
mSpacer = fragmentView.findViewById(R.id.spacer);
mSpacer.setOnTouchListener(new View.OnTouchListener() {
@Override
@@ -611,6 +619,28 @@ public class DialpadFragment extends AnalyticsFragment
}
@Override
+ public void onStart() {
+ super.onStart();
+ // if the mToneGenerator creation fails, just continue without it. It is
+ // a local audio signal, and is not as important as the dtmf tone itself.
+ final long start = System.currentTimeMillis();
+ synchronized (mToneGeneratorLock) {
+ if (mToneGenerator == null) {
+ try {
+ mToneGenerator = new ToneGenerator(DIAL_TONE_STREAM_TYPE, TONE_RELATIVE_VOLUME);
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Exception caught while creating local tone generator: " + e);
+ mToneGenerator = null;
+ }
+ }
+ }
+ final long total = System.currentTimeMillis() - start;
+ if (total > 50) {
+ Log.i(TAG, "Time for ToneGenerator creation: " + total);
+ }
+ };
+
+ @Override
public void onResume() {
super.onResume();
@@ -638,20 +668,6 @@ public class DialpadFragment extends AnalyticsFragment
stopWatch.lap("hptc");
- // if the mToneGenerator creation fails, just continue without it. It is
- // a local audio signal, and is not as important as the dtmf tone itself.
- synchronized (mToneGeneratorLock) {
- if (mToneGenerator == null) {
- try {
- mToneGenerator = new ToneGenerator(DIAL_TONE_STREAM_TYPE, TONE_RELATIVE_VOLUME);
- } catch (RuntimeException e) {
- Log.w(TAG, "Exception caught while creating local tone generator: " + e);
- mToneGenerator = null;
- }
- }
- }
- stopWatch.lap("tg");
-
mPressedDialpadKeys.clear();
configureScreenFromIntent(getActivity());
@@ -700,15 +716,6 @@ public class DialpadFragment extends AnalyticsFragment
mSmsPackageComponentName = DialerUtils.getSmsComponent(activity);
- // Populate the overflow menu in onResume instead of onCreate, so that if the SMS activity
- // is disabled while Dialer is paused, the "Send a text message" option can be correctly
- // removed when resumed.
- mOverflowMenuButton = mDialpadView.getOverflowMenuButton();
- mOverflowPopupMenu = buildOptionsMenu(mOverflowMenuButton);
- mOverflowMenuButton.setOnTouchListener(mOverflowPopupMenu.getDragToOpenListener());
- mOverflowMenuButton.setOnClickListener(this);
- mOverflowMenuButton.setVisibility(isDigitsEmpty() ? View.INVISIBLE : View.VISIBLE);
-
if (getTelephonyManager().isMultiSimEnabled() &&
MoreContactUtils.shouldShowOperator(mContext)) {
if (SubscriptionManager.isVoicePromptEnabled()) {
@@ -735,12 +742,6 @@ public class DialpadFragment extends AnalyticsFragment
stopTone();
mPressedDialpadKeys.clear();
- synchronized (mToneGeneratorLock) {
- if (mToneGenerator != null) {
- mToneGenerator.release();
- mToneGenerator = null;
- }
- }
// TODO: I wonder if we should not check if the AsyncTask that
// lookup the last dialed number has completed.
mLastNumberDialed = EMPTY_NUMBER; // Since we are going to query again, free stale number.
@@ -752,6 +753,13 @@ public class DialpadFragment extends AnalyticsFragment
public void onStop() {
super.onStop();
+ synchronized (mToneGeneratorLock) {
+ if (mToneGenerator != null) {
+ mToneGenerator.release();
+ mToneGenerator = null;
+ }
+ }
+
if (mClearDigitsOnStop) {
mClearDigitsOnStop = false;
clearDialpad();
@@ -913,6 +921,7 @@ public class DialpadFragment extends AnalyticsFragment
* @param invoker the View that invoked the options menu, to act as an anchor location.
*/
private PopupMenu buildOptionsMenu(View invoker) {
+ invoker.setLayoutDirection(TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()));
final PopupMenu popupMenu = new PopupMenu(getActivity(), invoker) {
@Override
public void show() {
@@ -1335,7 +1344,7 @@ public class DialpadFragment extends AnalyticsFragment
// must be dial conference add extra
intent.putExtra(TelephonyProperties.EXTRA_DIAL_CONFERENCE_URI, true);
}
- intent.putExtra(ADD_PARTICIPANT_KEY, mAddParticipant);
+ intent.putExtra(ADD_PARTICIPANT_KEY, (mAddParticipant && isPhoneInUse()));
DialerUtils.startActivityWithErrorToast(getActivity(), intent);
hideAndClearDialpad(false);
}
@@ -2047,12 +2056,14 @@ public class DialpadFragment extends AnalyticsFragment
PhoneStateListener phoneStateListener = new PhoneStateListener(subId[0]) {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
- if ((state == TelephonyManager.CALL_STATE_IDLE)
+ if ((getActivity() != null) &&
+ (getTelephonyManager().getCallState() == TelephonyManager.CALL_STATE_IDLE)
&& isDialpadChooserVisible()) {
showDialpadChooser(false);
}
- if (state == TelephonyManager.CALL_STATE_IDLE
- && getActivity() != null) {
+ if ((getActivity() != null)
+ && (getTelephonyManager().getCallState()
+ == TelephonyManager.CALL_STATE_IDLE)) {
((HostInterface) getActivity()).setConferenceDialButtonVisibility(true);
}
}
diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java
index 024e3d914..734c0b9ed 100644
--- a/src/com/android/dialer/list/ListsFragment.java
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -90,6 +90,7 @@ public class ListsFragment extends AnalyticsFragment implements CallLogQueryHand
private ShortcutCardsAdapter mMergedAdapter;
private CallLogAdapter mCallLogAdapter;
private CallLogQueryHandler mCallLogQueryHandler;
+ private OverlappingPaneLayout mOverlappingPaneLayout;
private boolean mIsPanelOpen = true;
@@ -303,6 +304,7 @@ public class ListsFragment extends AnalyticsFragment implements CallLogQueryHand
mRemoveViewContent = parentView.findViewById(R.id.remove_view_content);
setupPaneLayout((OverlappingPaneLayout) parentView);
+ mOverlappingPaneLayout = (OverlappingPaneLayout) parentView;
return parentView;
}
@@ -323,6 +325,11 @@ public class ListsFragment extends AnalyticsFragment implements CallLogQueryHand
mCallLogAdapter.changeCursor(cursor);
mMergedAdapter.notifyDataSetChanged();
+
+ // Refresh the overlapping pane to ensure that any changes in the shortcut card height
+ // are appropriately reflected in the overlap position.
+ mOverlappingPaneLayout.refresh();
+
// Return true; took ownership of cursor
return true;
}
diff --git a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
index f58d72faa..62e7dce08 100644
--- a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
+++ b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java
@@ -449,7 +449,7 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
* @param itemIndex Position of the contact in {@link #mContactEntries}.
* @return True if the given index is valid for {@link #mContactEntries}.
*/
- private boolean isIndexInBound(int itemIndex) {
+ public boolean isIndexInBound(int itemIndex) {
return itemIndex >= 0 && itemIndex < mContactEntries.size();
}
@@ -459,7 +459,8 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements
* @param itemIndex Position of the contact in {@link #mContactEntries}.
*/
private void markDropArea(int itemIndex) {
- if (isIndexInBound(mDragEnteredEntryIndex) && isIndexInBound(itemIndex)) {
+ if (mDraggedEntry != null && isIndexInBound(mDragEnteredEntryIndex) &&
+ isIndexInBound(itemIndex)) {
mDataSetChangedListener.cacheOffsetsForDatasetChange();
// Remove the old placeholder item and place the new placeholder item.
final int oldIndex = mDragEnteredEntryIndex;
diff --git a/src/com/android/dialer/list/SearchFragment.java b/src/com/android/dialer/list/SearchFragment.java
index 4603d0359..70141a73a 100644
--- a/src/com/android/dialer/list/SearchFragment.java
+++ b/src/com/android/dialer/list/SearchFragment.java
@@ -142,22 +142,6 @@ public class SearchFragment extends PhoneNumberPickerFragment {
}
/**
- * Adds a plus sign to the query string if original typed number was an international number.
- */
- private String addPlusSignPrefixToNumber(String actualNumber) {
- final StringBuilder number = new StringBuilder();
-
- // Check if actual number had + sign as the first character and query string does not, then
- // return a number with a + sign prefixed to the query string. That will be the dial string.
- if ((actualNumber != null) && actualNumber.startsWith("+") && (getQueryString() != null)
- && !(getQueryString().startsWith("+"))) {
- number.append('+');
- }
- number.append(getQueryString());
- return number.toString();
- }
-
- /**
* Return true if phone number is prohibited by a value -
* (R.string.config_prohibited_phone_number_regexp) in the config files. False otherwise.
*/
@@ -197,8 +181,7 @@ public class SearchFragment extends PhoneNumberPickerFragment {
final int shortcutType = adapter.getShortcutTypeFromPosition(position);
final OnPhoneNumberPickerActionListener listener;
- String dialingNumber = addPlusSignPrefixToNumber(mAddToContactNumber);
- boolean ret = checkForProhibitedPhoneNumber(dialingNumber);
+ boolean ret = checkForProhibitedPhoneNumber(mAddToContactNumber);
switch (shortcutType) {
case DialerPhoneNumberListAdapter.SHORTCUT_INVALID:
@@ -207,7 +190,7 @@ public class SearchFragment extends PhoneNumberPickerFragment {
case DialerPhoneNumberListAdapter.SHORTCUT_DIRECT_CALL:
listener = getOnPhoneNumberPickerListener();
if (listener != null && !ret) {
- listener.onCallNumberDirectly(dialingNumber);
+ listener.onCallNumberDirectly(getQueryString());
}
break;
case DialerPhoneNumberListAdapter.SHORTCUT_ADD_NUMBER_TO_CONTACTS:
@@ -220,7 +203,7 @@ public class SearchFragment extends PhoneNumberPickerFragment {
case DialerPhoneNumberListAdapter.SHORTCUT_MAKE_VIDEO_CALL:
listener = getOnPhoneNumberPickerListener();
if (listener != null && !ret) {
- listener.onCallNumberDirectly(dialingNumber, true /* isVideoCall */);
+ listener.onCallNumberDirectly(mAddToContactNumber, true /* isVideoCall */);
}
break;
}
diff --git a/src/com/android/dialer/list/ShortcutCardsAdapter.java b/src/com/android/dialer/list/ShortcutCardsAdapter.java
index 4fe638ea1..d642418bf 100644
--- a/src/com/android/dialer/list/ShortcutCardsAdapter.java
+++ b/src/com/android/dialer/list/ShortcutCardsAdapter.java
@@ -202,6 +202,7 @@ public class ShortcutCardsAdapter extends BaseAdapter {
wrapper.removeAllViews();
wrapper.prepareChildView(view);
wrapper.addView(view);
+ wrapper.setVisibility(View.VISIBLE);
return wrapper;
}
diff --git a/src/com/android/dialer/list/SpeedDialFragment.java b/src/com/android/dialer/list/SpeedDialFragment.java
index c02c3d7f9..03613d017 100644
--- a/src/com/android/dialer/list/SpeedDialFragment.java
+++ b/src/com/android/dialer/list/SpeedDialFragment.java
@@ -240,14 +240,16 @@ public class SpeedDialFragment extends AnalyticsFragment implements OnItemClickL
/* package */ void setEmptyViewVisibility(final boolean visible) {
final int previousVisibility = mEmptyView.getVisibility();
- final int newVisibility = visible ? View.VISIBLE : View.GONE;
+ final int emptyViewVisibility = visible ? View.VISIBLE : View.GONE;
+ final int listViewVisibility = visible ? View.GONE : View.VISIBLE;
- if (previousVisibility != newVisibility) {
+ if (previousVisibility != emptyViewVisibility) {
final RelativeLayout.LayoutParams params = (LayoutParams) mContactTileFrame
.getLayoutParams();
params.height = visible ? LayoutParams.WRAP_CONTENT : LayoutParams.MATCH_PARENT;
mContactTileFrame.setLayoutParams(params);
- mEmptyView.setVisibility(newVisibility);
+ mEmptyView.setVisibility(emptyViewVisibility);
+ mListView.setVisibility(listViewVisibility);
}
}
@@ -315,6 +317,12 @@ public class SpeedDialFragment extends AnalyticsFragment implements OnItemClickL
for (int i = 0; i < mListView.getChildCount(); i++) {
final View child = mListView.getChildAt(i);
final int position = firstVisiblePosition + i;
+ // Since we are getting the position from mListView and then querying
+ // mContactTileAdapter, its very possible that things are out of sync
+ // and we might index out of bounds. Let's make sure that this doesn't happen.
+ if (!mContactTileAdapter.isIndexInBound(position)) {
+ continue;
+ }
final long itemId = mContactTileAdapter.getItemId(position);
if (DEBUG) {
Log.d(TAG, "Saving itemId: " + itemId + " for listview child " + i + " Top: "
@@ -323,7 +331,6 @@ public class SpeedDialFragment extends AnalyticsFragment implements OnItemClickL
mItemIdTopMap.put(itemId, child.getTop());
mItemIdLeftMap.put(itemId, child.getLeft());
}
-
mItemIdTopMap.put(KEY_REMOVED_ITEM_HEIGHT, removedItemHeight);
}
@@ -351,6 +358,13 @@ public class SpeedDialFragment extends AnalyticsFragment implements OnItemClickL
final View child = mListView.getChildAt(i);
int position = firstVisiblePosition + i;
+ // Since we are getting the position from mListView and then querying
+ // mContactTileAdapter, its very possible that things are out of sync
+ // and we might index out of bounds. Let's make sure that this doesn't happen.
+ if (!mContactTileAdapter.isIndexInBound(position)) {
+ continue;
+ }
+
final long itemId = mContactTileAdapter.getItemId(position);
if (containsId(idsInPlace, itemId)) {
diff --git a/src/com/android/dialer/util/DialerUtils.java b/src/com/android/dialer/util/DialerUtils.java
index a747c74aa..48d969904 100644
--- a/src/com/android/dialer/util/DialerUtils.java
+++ b/src/com/android/dialer/util/DialerUtils.java
@@ -124,7 +124,7 @@ public class DialerUtils {
(ImageView) emptyListView.findViewById(R.id.emptyListViewImage);
emptyListViewImage.setImageDrawable(res.getDrawable(imageResId));
- emptyListViewImage.setContentDescription(res.getString(strResId));
+ emptyListViewImage.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
TextView emptyListViewMessage =
(TextView) emptyListView.findViewById(R.id.emptyListViewMessage);
diff --git a/src/com/android/dialer/widget/OverlappingPaneLayout.java b/src/com/android/dialer/widget/OverlappingPaneLayout.java
index 95a0e43de..167b849f2 100644
--- a/src/com/android/dialer/widget/OverlappingPaneLayout.java
+++ b/src/com/android/dialer/widget/OverlappingPaneLayout.java
@@ -230,7 +230,6 @@ public class OverlappingPaneLayout extends ViewGroup {
setWillNotDraw(false);
ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate());
- ViewCompat.setImportantForAccessibility(this, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
mDragHelper = ViewDragHelper.create(this, 0.5f, new DragHelperCallback());
mDragHelper.setMinVelocity(MIN_FLING_VELOCITY * density);
@@ -718,6 +717,22 @@ public class OverlappingPaneLayout extends ViewGroup {
return wantTouchEvents;
}
+ /**
+ * Refreshes the {@link OverlappingPaneLayout} be attempting to re-open or re-close the pane.
+ * This ensures that the overlapping pane is repositioned based on any changes to the view
+ * which is being overlapped.
+ * <p>
+ * The {@link #openPane()} and {@link #closePane()} methods do not perform any animation if the
+ * pane has already been positioned appropriately.
+ */
+ public void refresh() {
+ if (isOpen()) {
+ openPane();
+ } else {
+ closePane();
+ }
+ }
+
private boolean closePane(View pane, int initialVelocity) {
if (mFirstLayout || smoothSlideTo(0.f, initialVelocity)) {
mPreservedOpenState = false;
diff --git a/src/com/android/dialer/widget/ViewDragHelper.java b/src/com/android/dialer/widget/ViewDragHelper.java
index a0e1d801b..fe3ab8230 100644
--- a/src/com/android/dialer/widget/ViewDragHelper.java
+++ b/src/com/android/dialer/widget/ViewDragHelper.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.VelocityTrackerCompat;
import android.support.v4.view.ViewCompat;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -1176,7 +1177,12 @@ public class ViewDragHelper {
case MotionEvent.ACTION_MOVE: {
if (mDragState == STATE_DRAGGING) {
- final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
+ int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
+ if (index < 0) {
+ Log.e(TAG, "Pointer index for id " + mActivePointerId + " not found."
+ + " Skipping MotionEvent");
+ return;
+ }
final float x = MotionEventCompat.getX(ev, index);
final float y = MotionEventCompat.getY(ev, index);
final int idx = (int) (x - mLastMotionX[mActivePointerId]);
@@ -1548,6 +1554,12 @@ public class ViewDragHelper {
* deltas that it consumed.
*/
public void processNestedScroll(View target, int dx, int dy, int[] consumed) {
+ if (mCapturedView == null) {
+ // This is safe because consumed array is null when called from
+ // onNestedScroll, and pre-initialized to {0, 0} when called from
+ // onNestedPreScroll.
+ return;
+ }
final int targetX = mCapturedView.getLeft() + dx;
final int targetY = mCapturedView.getTop() + dy;
dragTo(targetX, targetY, dx, dy);
diff --git a/tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java b/tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java
index bc7c033b2..1669b5087 100644..100755
--- a/tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/dialer/PhoneCallDetailsHelperTest.java
@@ -69,7 +69,7 @@ public class PhoneCallDetailsHelperTest extends AndroidTestCase {
CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
final TestPhoneNumberUtilsWrapper phoneUtils = new TestPhoneNumberUtilsWrapper(
TEST_VOICEMAIL_NUMBER);
- mHelper = new PhoneCallDetailsHelper(resources, callTypeHelper, phoneUtils);
+ mHelper = new PhoneCallDetailsHelper(context, resources, phoneUtils);
mHelper.setCurrentTimeForTest(
new GregorianCalendar(2011, 5, 4, 13, 0, 0).getTimeInMillis());
mViews = PhoneCallDetailsViews.createForTest(context);
diff --git a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
index 85dbf8c83..feed379e7 100644..100755
--- a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
@@ -64,7 +64,7 @@ public class CallLogListItemHelperTest extends AndroidTestCase {
final TestPhoneNumberUtilsWrapper phoneUtils = new TestPhoneNumberUtilsWrapper(
TEST_VOICEMAIL_NUMBER);
PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
- mResources, callTypeHelper, phoneUtils);
+ context, mResources, phoneUtils);
mPhoneNumberDisplayHelper = new PhoneNumberDisplayHelper(mResources);
mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, mPhoneNumberDisplayHelper,
mResources);
diff --git a/tests/src/com/android/dialer/widget/ActionBarControllerTest.java b/tests/src/com/android/dialer/widget/ActionBarControllerTest.java
index cafa747f2..2e388380f 100644
--- a/tests/src/com/android/dialer/widget/ActionBarControllerTest.java
+++ b/tests/src/com/android/dialer/widget/ActionBarControllerTest.java
@@ -17,25 +17,53 @@
package com.android.dialer.widget;
import android.app.ActionBar;
+import android.app.Activity;
import android.content.Context;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.AndroidTestCase;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import android.view.View;
+import com.android.dialer.DialtactsActivity;
import com.android.dialer.widget.ActionBarController.ActivityUi;
+import com.android.internal.app.WindowDecorActionBar;
@SmallTest
-public class ActionBarControllerTest extends InstrumentationTestCase {
+public class ActionBarControllerTest extends ActivityInstrumentationTestCase2<DialtactsActivity> {
private static final int ACTION_BAR_HEIGHT = 100;
private ActionBarController mActionBarController;
private SearchEditTextLayout mSearchBox;
private MockActivityUi mActivityUi;
+ private class MockActionBar extends WindowDecorActionBar {
+ private int mHideOffset = 0;
+
+ public MockActionBar(Activity activity) {
+ super(activity);
+ }
+
+ @Override
+ public void setHideOffset(int offset) {
+ mHideOffset = offset;
+ }
+
+ @Override
+ public int getHideOffset() {
+ return mHideOffset;
+ }
+ }
+
private class MockActivityUi implements ActivityUi {
boolean isInSearchUi;
boolean hasSearchQuery;
boolean shouldShowActionBar;
- int actionBarHideOffset;
+ private ActionBar mActionBar;
+
+ public MockActivityUi() {
+ mActionBar = new MockActionBar(getActivity());
+ }
@Override
public boolean isInSearchUi() {
@@ -59,7 +87,7 @@ public class ActionBarControllerTest extends InstrumentationTestCase {
@Override
public ActionBar getActionBar() {
- return null;
+ return mActionBar;
}
}
@@ -83,6 +111,11 @@ public class ActionBarControllerTest extends InstrumentationTestCase {
}
}
+ public ActionBarControllerTest() {
+ super(DialtactsActivity.class);
+ }
+
+
@Override
protected void setUp() {
mActivityUi = new MockActivityUi();