summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/dialer/PhoneCallDetailsHelper.java7
-rw-r--r--src/com/android/dialer/PhoneCallDetailsViews.java7
-rw-r--r--src/com/android/dialer/calllog/CallLogActivity.java14
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapter.java9
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java172
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemHelper.java13
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemViews.java8
-rw-r--r--src/com/android/dialer/calllog/NewCallLogAdapter.java782
-rw-r--r--src/com/android/dialer/calllog/NewCallLogFragment.java535
-rw-r--r--src/com/android/dialer/calllog/NewCallLogListItemHelper.java111
-rw-r--r--src/com/android/dialer/list/NewPhoneFavoriteFragment.java8
-rw-r--r--src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java8
12 files changed, 76 insertions, 1598 deletions
diff --git a/src/com/android/dialer/PhoneCallDetailsHelper.java b/src/com/android/dialer/PhoneCallDetailsHelper.java
index 0da0d0c39..6f13b2e9d 100644
--- a/src/com/android/dialer/PhoneCallDetailsHelper.java
+++ b/src/com/android/dialer/PhoneCallDetailsHelper.java
@@ -123,16 +123,9 @@ public class PhoneCallDetailsHelper {
numberText = displayNumber;
labelText = TextUtils.isEmpty(numberFormattedLabel) ? numberText :
numberFormattedLabel;
- // We have a real phone number as "numberView" so make it always LTR
- if (views.numberView != null) {
- views.numberView.setTextDirection(View.TEXT_DIRECTION_LTR);
- }
}
views.nameView.setText(nameText);
- if (views.numberView != null) {
- views.numberView.setText(numberText);
- }
views.labelView.setText(labelText);
views.labelView.setVisibility(TextUtils.isEmpty(labelText) ? View.GONE : View.VISIBLE);
diff --git a/src/com/android/dialer/PhoneCallDetailsViews.java b/src/com/android/dialer/PhoneCallDetailsViews.java
index 09f50fbe3..4e482109b 100644
--- a/src/com/android/dialer/PhoneCallDetailsViews.java
+++ b/src/com/android/dialer/PhoneCallDetailsViews.java
@@ -30,17 +30,14 @@ public final class PhoneCallDetailsViews {
public final View callTypeView;
public final CallTypeIconsView callTypeIcons;
public final TextView callTypeAndDate;
- public final TextView numberView;
public final TextView labelView;
private PhoneCallDetailsViews(TextView nameView, View callTypeView,
- CallTypeIconsView callTypeIcons, TextView callTypeAndDate, TextView numberView,
- TextView labelView) {
+ CallTypeIconsView callTypeIcons, TextView callTypeAndDate, TextView labelView) {
this.nameView = nameView;
this.callTypeView = callTypeView;
this.callTypeIcons = callTypeIcons;
this.callTypeAndDate = callTypeAndDate;
- this.numberView = numberView;
this.labelView = labelView;
}
@@ -56,7 +53,6 @@ public final class PhoneCallDetailsViews {
view.findViewById(R.id.call_type),
(CallTypeIconsView) view.findViewById(R.id.call_type_icons),
(TextView) view.findViewById(R.id.call_count_and_date),
- (TextView) view.findViewById(R.id.number),
(TextView) view.findViewById(R.id.label));
}
@@ -66,7 +62,6 @@ public final class PhoneCallDetailsViews {
new View(context),
new CallTypeIconsView(context),
new TextView(context),
- new TextView(context),
new TextView(context));
}
}
diff --git a/src/com/android/dialer/calllog/CallLogActivity.java b/src/com/android/dialer/calllog/CallLogActivity.java
index 03ccef7ab..2d976a929 100644
--- a/src/com/android/dialer/calllog/CallLogActivity.java
+++ b/src/com/android/dialer/calllog/CallLogActivity.java
@@ -38,14 +38,14 @@ import android.view.MenuItem;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.R;
-import com.android.dialer.calllog.NewCallLogFragment;
+import com.android.dialer.calllog.CallLogFragment;
public class CallLogActivity extends Activity {
private ViewPager mViewPager;
private ViewPagerAdapter mViewPagerAdapter;
- private NewCallLogFragment mAllCallsFragment;
- private NewCallLogFragment mMissedCallsFragment;
+ private CallLogFragment mAllCallsFragment;
+ private CallLogFragment mMissedCallsFragment;
private static final int TAB_INDEX_ALL = 0;
private static final int TAB_INDEX_MISSED = 1;
@@ -61,10 +61,10 @@ public class CallLogActivity extends Activity {
public Fragment getItem(int position) {
switch (position) {
case TAB_INDEX_ALL:
- mAllCallsFragment = new NewCallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL);
+ mAllCallsFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL);
return mAllCallsFragment;
case TAB_INDEX_MISSED:
- mMissedCallsFragment = new NewCallLogFragment(Calls.MISSED_TYPE);
+ mMissedCallsFragment = new CallLogFragment(Calls.MISSED_TYPE);
return mMissedCallsFragment;
}
throw new IllegalStateException("No fragment at position " + position);
@@ -114,7 +114,7 @@ public class CallLogActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.call_log_activity_new);
+ setContentView(R.layout.call_log_activity);
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
@@ -159,7 +159,7 @@ public class CallLogActivity extends Activity {
public boolean onPrepareOptionsMenu(Menu menu) {
final MenuItem itemDeleteAll = menu.findItem(R.id.delete_all);
- final NewCallLogAdapter adapter = mAllCallsFragment.getAdapter();
+ final CallLogAdapter adapter = mAllCallsFragment.getAdapter();
// Check if all the menu items are inflated correctly. As a shortcut, we assume all
// menu items are ready if the first item is non-null.
if (itemDeleteAll != null) {
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 46bb4fd28..2c81f46fe 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -46,7 +46,7 @@ import java.util.LinkedList;
/**
* Adapter class to fill in data for the Call Log.
*/
-/*package*/ class CallLogAdapter extends GroupingListAdapter
+public class CallLogAdapter extends GroupingListAdapter
implements ViewTreeObserver.OnPreDrawListener, CallLogGroupBuilder.GroupCreator {
/** Interface used to initiate a refresh of the content. */
public interface CallFetcher {
@@ -227,7 +227,7 @@ import java.util.LinkedList;
}
};
- CallLogAdapter(Context context, CallFetcher callFetcher,
+ public CallLogAdapter(Context context, CallFetcher callFetcher,
ContactInfoHelper contactInfoHelper) {
super(context);
@@ -259,7 +259,7 @@ import java.util.LinkedList;
mCallFetcher.fetchCalls();
}
- void setLoading(boolean loading) {
+ public void setLoading(boolean loading) {
mLoading = loading;
}
@@ -518,6 +518,7 @@ import java.util.LinkedList;
views.primaryActionView.setTag(
IntentProvider.getCallDetailIntentProvider(
getCursor(), c.getPosition(), c.getLong(CallLogQuery.ID), count));
+
// Store away the voicemail information so we can play it directly.
if (callType == Calls.VOICEMAIL_TYPE) {
String voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
@@ -715,7 +716,7 @@ import java.util.LinkedList;
private void setPhoto(CallLogListItemViews views, long photoId, Uri contactUri) {
views.quickContactView.assignContactUri(contactUri);
- mContactPhotoManager.loadThumbnail(views.quickContactView, photoId, true);
+ mContactPhotoManager.loadThumbnail(views.quickContactView, photoId, false /* darkTheme */);
}
/**
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index bc0856f75..5d750044f 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -34,7 +34,6 @@ import android.provider.ContactsContract;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -59,7 +58,8 @@ import com.google.common.annotations.VisibleForTesting;
import java.util.List;
/**
- * Displays a list of call log entries.
+ * Displays a list of call log entries. To filter for a particular kind of call
+ * (all, missed or voicemails), specify it in the constructor.
*/
public class CallLogFragment extends ListFragment
implements CallLogQueryHandler.Listener, CallLogAdapter.CallFetcher {
@@ -81,7 +81,6 @@ public class CallLogFragment extends ListFragment
private View mStatusMessageView;
private TextView mStatusMessageText;
private TextView mStatusMessageAction;
- private TextView mFilterStatusView;
private KeyguardManager mKeyguardManager;
private boolean mEmptyLoaderRunning;
@@ -114,11 +113,30 @@ public class CallLogFragment extends ListFragment
// Default to all calls.
private int mCallTypeFilter = CallLogQueryHandler.CALL_TYPE_ALL;
+ // Log limit - if no limit is specified, then the default in {@link CallLogQueryHandler}
+ // will be used.
+ private int mLogLimit = -1;
+
+ public CallLogFragment() {
+ this(CallLogQueryHandler.CALL_TYPE_ALL, -1);
+ }
+
+ public CallLogFragment(int filterType) {
+ this(filterType, -1);
+ }
+
+ public CallLogFragment(int filterType, int logLimit) {
+ super();
+ mCallTypeFilter = filterType;
+ mLogLimit = logLimit;
+ }
+
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
- mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), this);
+ mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(),
+ this, mLogLimit);
mKeyguardManager =
(KeyguardManager) getActivity().getSystemService(Context.KEYGUARD_SERVICE);
getActivity().getContentResolver().registerContentObserver(
@@ -126,6 +144,7 @@ public class CallLogFragment extends ListFragment
getActivity().getContentResolver().registerContentObserver(
ContactsContract.Contacts.CONTENT_URI, true, mContactsObserver);
setHasOptionsMenu(true);
+ updateCallList(mCallTypeFilter);
}
/** Called by the CallLogQueryHandler when the list of calls has been fetched or updated. */
@@ -210,13 +229,13 @@ public class CallLogFragment extends ListFragment
mStatusMessageView = view.findViewById(R.id.voicemail_status);
mStatusMessageText = (TextView) view.findViewById(R.id.voicemail_status_message);
mStatusMessageAction = (TextView) view.findViewById(R.id.voicemail_status_action);
- mFilterStatusView = (TextView) view.findViewById(R.id.filter_status);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+ updateEmptyMessage(mCallTypeFilter);
String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
mAdapter = new CallLogAdapter(getActivity(), this,
new ContactInfoHelper(getActivity(), currentCountryIso));
@@ -320,132 +339,30 @@ public class CallLogFragment extends ListFragment
mCallLogQueryHandler.fetchVoicemailStatus();
}
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- inflater.inflate(R.menu.call_log_options, menu);
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- final MenuItem itemDeleteAll = menu.findItem(R.id.delete_all);
- // Check if all the menu items are inflated correctly. As a shortcut, we assume all
- // menu items are ready if the first item is non-null.
- if (itemDeleteAll != null) {
- itemDeleteAll.setEnabled(mAdapter != null && !mAdapter.isEmpty());
-
- showAllFilterMenuOptions(menu);
- hideCurrentFilterMenuOption(menu);
-
- // Only hide if not available. Let the above calls handle showing.
- if (!mVoicemailSourcesAvailable) {
- menu.findItem(R.id.show_voicemails_only).setVisible(false);
- }
- }
- }
-
- private void hideCurrentFilterMenuOption(Menu menu) {
- MenuItem item = null;
- switch (mCallTypeFilter) {
- case CallLogQueryHandler.CALL_TYPE_ALL:
- item = menu.findItem(R.id.show_all_calls);
- break;
- case Calls.INCOMING_TYPE:
- item = menu.findItem(R.id.show_incoming_only);
- break;
- case Calls.OUTGOING_TYPE:
- item = menu.findItem(R.id.show_outgoing_only);
- break;
- case Calls.MISSED_TYPE:
- item = menu.findItem(R.id.show_missed_only);
- break;
- case Calls.VOICEMAIL_TYPE:
- menu.findItem(R.id.show_voicemails_only);
- break;
- }
- if (item != null) {
- item.setVisible(false);
- }
- }
-
- private void showAllFilterMenuOptions(Menu menu) {
- menu.findItem(R.id.show_all_calls).setVisible(true);
- menu.findItem(R.id.show_incoming_only).setVisible(true);
- menu.findItem(R.id.show_outgoing_only).setVisible(true);
- menu.findItem(R.id.show_missed_only).setVisible(true);
- menu.findItem(R.id.show_voicemails_only).setVisible(true);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.delete_all:
- ClearCallLogDialog.show(getFragmentManager());
- return true;
-
- case R.id.show_outgoing_only:
- // We only need the phone call receiver when there is an active call type filter.
- // Not many people may use the filters so don't register the receiver until now .
- registerPhoneCallReceiver();
- mCallLogQueryHandler.fetchCalls(Calls.OUTGOING_TYPE);
- updateFilterTypeAndHeader(Calls.OUTGOING_TYPE);
- return true;
-
- case R.id.show_incoming_only:
- registerPhoneCallReceiver();
- mCallLogQueryHandler.fetchCalls(Calls.INCOMING_TYPE);
- updateFilterTypeAndHeader(Calls.INCOMING_TYPE);
- return true;
-
- case R.id.show_missed_only:
- registerPhoneCallReceiver();
- mCallLogQueryHandler.fetchCalls(Calls.MISSED_TYPE);
- updateFilterTypeAndHeader(Calls.MISSED_TYPE);
- return true;
-
- case R.id.show_voicemails_only:
- registerPhoneCallReceiver();
- mCallLogQueryHandler.fetchCalls(Calls.VOICEMAIL_TYPE);
- updateFilterTypeAndHeader(Calls.VOICEMAIL_TYPE);
- return true;
-
- case R.id.show_all_calls:
- // Filter is being turned off, receiver no longer needed.
- unregisterPhoneCallReceiver();
- mCallLogQueryHandler.fetchCalls(CallLogQueryHandler.CALL_TYPE_ALL);
- updateFilterTypeAndHeader(CallLogQueryHandler.CALL_TYPE_ALL);
- return true;
-
- default:
- return false;
+ private void updateCallList(int filterType) {
+ if (filterType == CallLogQueryHandler.CALL_TYPE_ALL) {
+ unregisterPhoneCallReceiver();
+ } else {
+ // TODO krelease: Make this work
+ //registerPhoneCallReceiver();
}
+ mCallLogQueryHandler.fetchCalls(filterType);
}
- private void updateFilterTypeAndHeader(int filterType) {
- mCallTypeFilter = filterType;
-
+ private void updateEmptyMessage(int filterType) {
+ final String message;
switch (filterType) {
- case CallLogQueryHandler.CALL_TYPE_ALL:
- mFilterStatusView.setVisibility(View.GONE);
- break;
- case Calls.INCOMING_TYPE:
- showFilterStatus(R.string.call_log_incoming_header);
- break;
- case Calls.OUTGOING_TYPE:
- showFilterStatus(R.string.call_log_outgoing_header);
- break;
case Calls.MISSED_TYPE:
- showFilterStatus(R.string.call_log_missed_header);
+ message = getString(R.string.recentMissed_empty);
break;
- case Calls.VOICEMAIL_TYPE:
- showFilterStatus(R.string.call_log_voicemail_header);
+ case CallLogQueryHandler.CALL_TYPE_ALL:
+ message = getString(R.string.recentCalls_empty);
break;
+ default:
+ throw new IllegalArgumentException("Unexpected filter type in CallLogFragment: "
+ + filterType);
}
- }
-
- private void showFilterStatus(int resId) {
- mFilterStatusView.setText(resId);
- mFilterStatusView.setVisibility(View.VISIBLE);
+ ((TextView) getListView().getEmptyView()).setText(message);
}
public void callSelectedEntry() {
@@ -489,7 +406,6 @@ public class CallLogFragment extends ListFragment
}
}
- @VisibleForTesting
CallLogAdapter getAdapter() {
return mAdapter;
}
@@ -547,6 +463,8 @@ public class CallLogFragment extends ListFragment
updateOnTransition(true);
}
+ // TODO krelease: Figure out if we still need this. If so, it should be probably be moved to
+ // the call log activity instead, or done only in a single call log fragment.
private void updateOnTransition(boolean onEntry) {
// We don't want to update any call data when keyguard is on because the user has likely not
// seen the new calls yet.
@@ -570,9 +488,13 @@ public class CallLogFragment extends ListFragment
getActivity().startService(serviceIntent);
}
+ // TODO krelease: Make the ViewPager switch to the correct tab (All) when a phone call is
+ // placed.
+ // This should probably be moved to the call log activity.
/**
* Register a phone call filter to reset the call type when a phone call is place.
*/
+ /*
private void registerPhoneCallReceiver() {
if (mPhoneStateListener != null) {
return; // Already registered.
@@ -592,13 +514,13 @@ public class CallLogFragment extends ListFragment
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
- updateFilterTypeAndHeader(CallLogQueryHandler.CALL_TYPE_ALL);
}
});
}
};
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
+ */
/**
* Un-registers the phone call receiver.
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index bccd4f45b..fdebeb166 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -27,8 +27,12 @@ import com.android.dialer.R;
/**
* Helper class to fill in the views of a call log entry.
+ * TODO krelease: The only difference between this and the original is that we don't touch
+ * divider views, which are not present in the new dialer. Once the new dialer replaces
+ * the old one, we can replace it entirely. Otherwise we would have redundant divider=null
+ * checks all over the place.
*/
-/*package*/ class CallLogListItemHelper {
+/* package */class CallLogListItemHelper {
/** Helper for populating the details of a phone call. */
private final PhoneCallDetailsHelper mPhoneCallDetailsHelper;
/** Helper for handling phone numbers. */
@@ -67,15 +71,12 @@ import com.android.dialer.R;
if (canPlay) {
// Playback action takes preference.
configurePlaySecondaryAction(views, isHighlighted);
- views.dividerView.setVisibility(View.VISIBLE);
} else if (canCall) {
// Call is the secondary action.
configureCallSecondaryAction(views, details);
- views.dividerView.setVisibility(View.VISIBLE);
} else {
// No action available.
views.secondaryActionView.setVisibility(View.GONE);
- views.dividerView.setVisibility(View.GONE);
}
}
@@ -83,7 +84,7 @@ import com.android.dialer.R;
private void configureCallSecondaryAction(CallLogListItemViews views,
PhoneCallDetails details) {
views.secondaryActionView.setVisibility(View.VISIBLE);
- views.secondaryActionView.setImageResource(R.drawable.ic_ab_dialer_holo_dark);
+ views.secondaryActionView.setImageResource(R.drawable.ic_ab_dialer_holo_light);
views.secondaryActionView.setContentDescription(getCallActionDescription(details));
}
@@ -103,7 +104,7 @@ import com.android.dialer.R;
private void configurePlaySecondaryAction(CallLogListItemViews views, boolean isHighlighted) {
views.secondaryActionView.setVisibility(View.VISIBLE);
views.secondaryActionView.setImageResource(
- isHighlighted ? R.drawable.ic_play_active_holo_dark : R.drawable.ic_play_holo_dark);
+ isHighlighted ? R.drawable.ic_play_active_holo_dark : R.drawable.ic_play_holo_light);
views.secondaryActionView.setContentDescription(
mResources.getString(R.string.description_call_log_play_button));
}
diff --git a/src/com/android/dialer/calllog/CallLogListItemViews.java b/src/com/android/dialer/calllog/CallLogListItemViews.java
index 86f531365..0dd4f6344 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViews.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViews.java
@@ -36,8 +36,6 @@ public final class CallLogListItemViews {
public final View primaryActionView;
/** The secondary action button on the entry. */
public final ImageView secondaryActionView;
- /** The divider between the primary and secondary actions. */
- public final View dividerView;
/** The details of the phone call. */
public final PhoneCallDetailsViews phoneCallDetailsViews;
/** The text of the header of a section. */
@@ -46,13 +44,11 @@ public final class CallLogListItemViews {
public final View bottomDivider;
private CallLogListItemViews(QuickContactBadge quickContactView, View primaryActionView,
- ImageView secondaryActionView, View dividerView,
- PhoneCallDetailsViews phoneCallDetailsViews,
+ ImageView secondaryActionView, PhoneCallDetailsViews phoneCallDetailsViews,
TextView listHeaderTextView, View bottomDivider) {
this.quickContactView = quickContactView;
this.primaryActionView = primaryActionView;
this.secondaryActionView = secondaryActionView;
- this.dividerView = dividerView;
this.phoneCallDetailsViews = phoneCallDetailsViews;
this.listHeaderTextView = listHeaderTextView;
this.bottomDivider = bottomDivider;
@@ -63,7 +59,6 @@ public final class CallLogListItemViews {
(QuickContactBadge) view.findViewById(R.id.quick_contact_photo),
view.findViewById(R.id.primary_action_view),
(ImageView) view.findViewById(R.id.secondary_action_icon),
- view.findViewById(R.id.divider),
PhoneCallDetailsViews.fromView(view),
(TextView) view.findViewById(R.id.call_log_header),
view.findViewById(R.id.call_log_divider));
@@ -75,7 +70,6 @@ public final class CallLogListItemViews {
new QuickContactBadge(context),
new View(context),
new ImageView(context),
- new View(context),
PhoneCallDetailsViews.createForTest(context),
new TextView(context),
new View(context));
diff --git a/src/com/android/dialer/calllog/NewCallLogAdapter.java b/src/com/android/dialer/calllog/NewCallLogAdapter.java
deleted file mode 100644
index c2f7c71e6..000000000
--- a/src/com/android/dialer/calllog/NewCallLogAdapter.java
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.dialer.calllog;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.CallLog.Calls;
-import android.provider.ContactsContract.PhoneLookup;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-
-import com.android.common.widget.GroupingListAdapter;
-import com.android.contacts.common.ContactPhotoManager;
-import com.android.contacts.common.util.UriUtils;
-import com.android.dialer.PhoneCallDetails;
-import com.android.dialer.PhoneCallDetailsHelper;
-import com.android.dialer.R;
-import com.android.dialer.util.ExpirableCache;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-
-import java.util.LinkedList;
-
-/**
- * Adapter class to fill in data for the Call Log.
- */
-public class NewCallLogAdapter extends GroupingListAdapter
- implements ViewTreeObserver.OnPreDrawListener, CallLogGroupBuilder.GroupCreator {
- /** Interface used to initiate a refresh of the content. */
- public interface CallFetcher {
- public void fetchCalls();
- }
-
- /**
- * Stores a phone number of a call with the country code where it originally occurred.
- * <p>
- * Note the country does not necessarily specifies the country of the phone number itself, but
- * it is the country in which the user was in when the call was placed or received.
- */
- private static final class NumberWithCountryIso {
- public final String number;
- public final String countryIso;
-
- public NumberWithCountryIso(String number, String countryIso) {
- this.number = number;
- this.countryIso = countryIso;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == null) return false;
- if (!(o instanceof NumberWithCountryIso)) return false;
- NumberWithCountryIso other = (NumberWithCountryIso) o;
- return TextUtils.equals(number, other.number)
- && TextUtils.equals(countryIso, other.countryIso);
- }
-
- @Override
- public int hashCode() {
- return (number == null ? 0 : number.hashCode())
- ^ (countryIso == null ? 0 : countryIso.hashCode());
- }
- }
-
- /** The time in millis to delay starting the thread processing requests. */
- private static final int START_PROCESSING_REQUESTS_DELAY_MILLIS = 1000;
-
- /** The size of the cache of contact info. */
- private static final int CONTACT_INFO_CACHE_SIZE = 100;
-
- private final Context mContext;
- private final ContactInfoHelper mContactInfoHelper;
- private final CallFetcher mCallFetcher;
- private ViewTreeObserver mViewTreeObserver = null;
-
- /**
- * A cache of the contact details for the phone numbers in the call log.
- * <p>
- * The content of the cache is expired (but not purged) whenever the application comes to
- * the foreground.
- * <p>
- * The key is number with the country in which the call was placed or received.
- */
- private ExpirableCache<NumberWithCountryIso, ContactInfo> mContactInfoCache;
-
- /**
- * A request for contact details for the given number.
- */
- private static final class ContactInfoRequest {
- /** The number to look-up. */
- public final String number;
- /** The country in which a call to or from this number was placed or received. */
- public final String countryIso;
- /** The cached contact information stored in the call log. */
- public final ContactInfo callLogInfo;
-
- public ContactInfoRequest(String number, String countryIso, ContactInfo callLogInfo) {
- this.number = number;
- this.countryIso = countryIso;
- this.callLogInfo = callLogInfo;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (!(obj instanceof ContactInfoRequest)) return false;
-
- ContactInfoRequest other = (ContactInfoRequest) obj;
-
- if (!TextUtils.equals(number, other.number)) return false;
- if (!TextUtils.equals(countryIso, other.countryIso)) return false;
- if (!Objects.equal(callLogInfo, other.callLogInfo)) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((callLogInfo == null) ? 0 : callLogInfo.hashCode());
- result = prime * result + ((countryIso == null) ? 0 : countryIso.hashCode());
- result = prime * result + ((number == null) ? 0 : number.hashCode());
- return result;
- }
- }
-
- /**
- * List of requests to update contact details.
- * <p>
- * Each request is made of a phone number to look up, and the contact info currently stored in
- * the call log for this number.
- * <p>
- * The requests are added when displaying the contacts and are processed by a background
- * thread.
- */
- private final LinkedList<ContactInfoRequest> mRequests;
-
- private boolean mLoading = true;
- private static final int REDRAW = 1;
- private static final int START_THREAD = 2;
-
- private QueryThread mCallerIdThread;
-
- /** Instance of helper class for managing views. */
- private final NewCallLogListItemHelper mCallLogViewsHelper;
-
- /** Helper to set up contact photos. */
- private final ContactPhotoManager mContactPhotoManager;
- /** Helper to parse and process phone numbers. */
- private PhoneNumberHelper mPhoneNumberHelper;
- /** Helper to group call log entries. */
- private final CallLogGroupBuilder mCallLogGroupBuilder;
-
- /** Can be set to true by tests to disable processing of requests. */
- private volatile boolean mRequestProcessingDisabled = false;
-
- /** Listener for the primary action in the list, opens the call details. */
- private final View.OnClickListener mPrimaryActionListener = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- IntentProvider intentProvider = (IntentProvider) view.getTag();
- if (intentProvider != null) {
- mContext.startActivity(intentProvider.getIntent(mContext));
- }
- }
- };
- /** Listener for the secondary action in the list, either call or play. */
- private final View.OnClickListener mSecondaryActionListener = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- IntentProvider intentProvider = (IntentProvider) view.getTag();
- if (intentProvider != null) {
- mContext.startActivity(intentProvider.getIntent(mContext));
- }
- }
- };
-
- @Override
- public boolean onPreDraw() {
- // We only wanted to listen for the first draw (and this is it).
- unregisterPreDrawListener();
-
- // Only schedule a thread-creation message if the thread hasn't been
- // created yet. This is purely an optimization, to queue fewer messages.
- if (mCallerIdThread == null) {
- mHandler.sendEmptyMessageDelayed(START_THREAD, START_PROCESSING_REQUESTS_DELAY_MILLIS);
- }
-
- return true;
- }
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case REDRAW:
- notifyDataSetChanged();
- break;
- case START_THREAD:
- startRequestProcessing();
- break;
- }
- }
- };
-
- public NewCallLogAdapter(Context context, CallFetcher callFetcher,
- ContactInfoHelper contactInfoHelper) {
- super(context);
-
- mContext = context;
- mCallFetcher = callFetcher;
- mContactInfoHelper = contactInfoHelper;
-
- mContactInfoCache = ExpirableCache.create(CONTACT_INFO_CACHE_SIZE);
- mRequests = new LinkedList<ContactInfoRequest>();
-
- Resources resources = mContext.getResources();
- CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
-
- mContactPhotoManager = ContactPhotoManager.getInstance(mContext);
- mPhoneNumberHelper = new PhoneNumberHelper(resources);
- PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
- resources, callTypeHelper, mPhoneNumberHelper);
- mCallLogViewsHelper =
- new NewCallLogListItemHelper(
- phoneCallDetailsHelper, mPhoneNumberHelper, resources);
- mCallLogGroupBuilder = new CallLogGroupBuilder(this);
- }
-
- /**
- * Requery on background thread when {@link Cursor} changes.
- */
- @Override
- protected void onContentChanged() {
- mCallFetcher.fetchCalls();
- }
-
- public void setLoading(boolean loading) {
- mLoading = loading;
- }
-
- @Override
- public boolean isEmpty() {
- if (mLoading) {
- // We don't want the empty state to show when loading.
- return false;
- } else {
- return super.isEmpty();
- }
- }
-
- /**
- * Starts a background thread to process contact-lookup requests, unless one
- * has already been started.
- */
- private synchronized void startRequestProcessing() {
- // For unit-testing.
- if (mRequestProcessingDisabled) return;
-
- // Idempotence... if a thread is already started, don't start another.
- if (mCallerIdThread != null) return;
-
- mCallerIdThread = new QueryThread();
- mCallerIdThread.setPriority(Thread.MIN_PRIORITY);
- mCallerIdThread.start();
- }
-
- /**
- * Stops the background thread that processes updates and cancels any
- * pending requests to start it.
- */
- public synchronized void stopRequestProcessing() {
- // Remove any pending requests to start the processing thread.
- mHandler.removeMessages(START_THREAD);
- if (mCallerIdThread != null) {
- // Stop the thread; we are finished with it.
- mCallerIdThread.stopProcessing();
- mCallerIdThread.interrupt();
- mCallerIdThread = null;
- }
- }
-
- /**
- * Stop receiving onPreDraw() notifications.
- */
- private void unregisterPreDrawListener() {
- if (mViewTreeObserver != null && mViewTreeObserver.isAlive()) {
- mViewTreeObserver.removeOnPreDrawListener(this);
- }
- mViewTreeObserver = null;
- }
-
- public void invalidateCache() {
- mContactInfoCache.expireAll();
-
- // Restart the request-processing thread after the next draw.
- stopRequestProcessing();
- unregisterPreDrawListener();
- }
-
- /**
- * Enqueues a request to look up the contact details for the given phone number.
- * <p>
- * It also provides the current contact info stored in the call log for this number.
- * <p>
- * If the {@code immediate} parameter is true, it will start immediately the thread that looks
- * up the contact information (if it has not been already started). Otherwise, it will be
- * started with a delay. See {@link #START_PROCESSING_REQUESTS_DELAY_MILLIS}.
- */
- @VisibleForTesting
- void enqueueRequest(String number, String countryIso, ContactInfo callLogInfo,
- boolean immediate) {
- ContactInfoRequest request = new ContactInfoRequest(number, countryIso, callLogInfo);
- synchronized (mRequests) {
- if (!mRequests.contains(request)) {
- mRequests.add(request);
- mRequests.notifyAll();
- }
- }
- if (immediate) startRequestProcessing();
- }
-
- /**
- * Queries the appropriate content provider for the contact associated with the number.
- * <p>
- * Upon completion it also updates the cache in the call log, if it is different from
- * {@code callLogInfo}.
- * <p>
- * The number might be either a SIP address or a phone number.
- * <p>
- * It returns true if it updated the content of the cache and we should therefore tell the
- * view to update its content.
- */
- private boolean queryContactInfo(String number, String countryIso, ContactInfo callLogInfo) {
- final ContactInfo info = mContactInfoHelper.lookupNumber(number, countryIso);
-
- if (info == null) {
- // The lookup failed, just return without requesting to update the view.
- return false;
- }
-
- // Check the existing entry in the cache: only if it has changed we should update the
- // view.
- NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso);
- ContactInfo existingInfo = mContactInfoCache.getPossiblyExpired(numberCountryIso);
- boolean updated = (existingInfo != ContactInfo.EMPTY) && !info.equals(existingInfo);
-
- // Store the data in the cache so that the UI thread can use to display it. Store it
- // even if it has not changed so that it is marked as not expired.
- mContactInfoCache.put(numberCountryIso, info);
- // Update the call log even if the cache it is up-to-date: it is possible that the cache
- // contains the value from a different call log entry.
- updateCallLogContactInfoCache(number, countryIso, info, callLogInfo);
- return updated;
- }
-
- /*
- * Handles requests for contact name and number type.
- */
- private class QueryThread extends Thread {
- private volatile boolean mDone = false;
-
- public QueryThread() {
- super("CallLogAdapter.QueryThread");
- }
-
- public void stopProcessing() {
- mDone = true;
- }
-
- @Override
- public void run() {
- boolean needRedraw = false;
- while (true) {
- // Check if thread is finished, and if so return immediately.
- if (mDone) return;
-
- // Obtain next request, if any is available.
- // Keep synchronized section small.
- ContactInfoRequest req = null;
- synchronized (mRequests) {
- if (!mRequests.isEmpty()) {
- req = mRequests.removeFirst();
- }
- }
-
- if (req != null) {
- // Process the request. If the lookup succeeds, schedule a
- // redraw.
- needRedraw |= queryContactInfo(req.number, req.countryIso, req.callLogInfo);
- } else {
- // Throttle redraw rate by only sending them when there are
- // more requests.
- if (needRedraw) {
- needRedraw = false;
- mHandler.sendEmptyMessage(REDRAW);
- }
-
- // Wait until another request is available, or until this
- // thread is no longer needed (as indicated by being
- // interrupted).
- try {
- synchronized (mRequests) {
- mRequests.wait(1000);
- }
- } catch (InterruptedException ie) {
- // Ignore, and attempt to continue processing requests.
- }
- }
- }
- }
- }
-
- @Override
- protected void addGroups(Cursor cursor) {
- mCallLogGroupBuilder.addGroups(cursor);
- }
-
- @Override
- protected View newStandAloneView(Context context, ViewGroup parent) {
- LayoutInflater inflater =
- (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.new_call_log_list_item, parent, false);
- findAndCacheViews(view);
- return view;
- }
-
- @Override
- protected void bindStandAloneView(View view, Context context, Cursor cursor) {
- bindView(view, cursor, 1);
- }
-
- @Override
- protected View newChildView(Context context, ViewGroup parent) {
- LayoutInflater inflater =
- (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.new_call_log_list_item, parent, false);
- findAndCacheViews(view);
- return view;
- }
-
- @Override
- protected void bindChildView(View view, Context context, Cursor cursor) {
- bindView(view, cursor, 1);
- }
-
- @Override
- protected View newGroupView(Context context, ViewGroup parent) {
- LayoutInflater inflater =
- (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.new_call_log_list_item, parent, false);
- findAndCacheViews(view);
- return view;
- }
-
- @Override
- protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
- boolean expanded) {
- bindView(view, cursor, groupSize);
- }
-
- private void findAndCacheViews(View view) {
- // Get the views to bind to.
- CallLogListItemViews views = CallLogListItemViews.fromView(view);
- views.primaryActionView.setOnClickListener(mPrimaryActionListener);
- views.secondaryActionView.setOnClickListener(mSecondaryActionListener);
- view.setTag(views);
- }
-
- /**
- * Binds the views in the entry to the data in the call log.
- *
- * @param view the view corresponding to this entry
- * @param c the cursor pointing to the entry in the call log
- * @param count the number of entries in the current item, greater than 1 if it is a group
- */
- private void bindView(View view, Cursor c, int count) {
- final CallLogListItemViews views = (CallLogListItemViews) view.getTag();
-
- // Default case: an item in the call log.
- views.primaryActionView.setVisibility(View.VISIBLE);
- views.bottomDivider.setVisibility(View.VISIBLE);
- views.listHeaderTextView.setVisibility(View.GONE);
-
- final String number = c.getString(CallLogQuery.NUMBER);
- final int numberPresentation = c.getInt(CallLogQuery.NUMBER_PRESENTATION);
- final long date = c.getLong(CallLogQuery.DATE);
- final long duration = c.getLong(CallLogQuery.DURATION);
- final int callType = c.getInt(CallLogQuery.CALL_TYPE);
- final String countryIso = c.getString(CallLogQuery.COUNTRY_ISO);
-
- final ContactInfo cachedContactInfo = getContactInfoFromCallLog(c);
-
- views.primaryActionView.setTag(
- IntentProvider.getCallDetailIntentProvider(
- getCursor(), c.getPosition(), c.getLong(CallLogQuery.ID), count));
-
- // Store away the voicemail information so we can play it directly.
- if (callType == Calls.VOICEMAIL_TYPE) {
- String voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
- final long rowId = c.getLong(CallLogQuery.ID);
- views.secondaryActionView.setTag(
- IntentProvider.getPlayVoicemailIntentProvider(rowId, voicemailUri));
- } else if (!TextUtils.isEmpty(number)) {
- // Store away the number so we can call it directly if you click on the call icon.
- views.secondaryActionView.setTag(
- IntentProvider.getReturnCallIntentProvider(number));
- } else {
- // No action enabled.
- views.secondaryActionView.setTag(null);
- }
-
- // Lookup contacts with this number
- NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso);
- ExpirableCache.CachedValue<ContactInfo> cachedInfo =
- mContactInfoCache.getCachedValue(numberCountryIso);
- ContactInfo info = cachedInfo == null ? null : cachedInfo.getValue();
- if (!PhoneNumberHelper.canPlaceCallsTo(number, numberPresentation)
- || mPhoneNumberHelper.isVoicemailNumber(number)) {
- // If this is a number that cannot be dialed, there is no point in looking up a contact
- // for it.
- info = ContactInfo.EMPTY;
- } else if (cachedInfo == null) {
- mContactInfoCache.put(numberCountryIso, ContactInfo.EMPTY);
- // Use the cached contact info from the call log.
- info = cachedContactInfo;
- // The db request should happen on a non-UI thread.
- // Request the contact details immediately since they are currently missing.
- enqueueRequest(number, countryIso, cachedContactInfo, true);
- // We will format the phone number when we make the background request.
- } else {
- if (cachedInfo.isExpired()) {
- // The contact info is no longer up to date, we should request it. However, we
- // do not need to request them immediately.
- enqueueRequest(number, countryIso, cachedContactInfo, false);
- } else if (!callLogInfoMatches(cachedContactInfo, info)) {
- // The call log information does not match the one we have, look it up again.
- // We could simply update the call log directly, but that needs to be done in a
- // background thread, so it is easier to simply request a new lookup, which will, as
- // a side-effect, update the call log.
- enqueueRequest(number, countryIso, cachedContactInfo, false);
- }
-
- if (info == ContactInfo.EMPTY) {
- // Use the cached contact info from the call log.
- info = cachedContactInfo;
- }
- }
-
- final Uri lookupUri = info.lookupUri;
- final String name = info.name;
- final int ntype = info.type;
- final String label = info.label;
- final long photoId = info.photoId;
- CharSequence formattedNumber = info.formattedNumber;
- final int[] callTypes = getCallTypes(c, count);
- final String geocode = c.getString(CallLogQuery.GEOCODED_LOCATION);
- final PhoneCallDetails details;
- if (TextUtils.isEmpty(name)) {
- details = new PhoneCallDetails(number, numberPresentation,
- formattedNumber, countryIso, geocode, callTypes, date,
- duration);
- } else {
- // We do not pass a photo id since we do not need the high-res picture.
- details = new PhoneCallDetails(number, numberPresentation,
- formattedNumber, countryIso, geocode, callTypes, date,
- duration, name, ntype, label, lookupUri, null);
- }
-
- final boolean isNew = c.getInt(CallLogQuery.IS_READ) == 0;
- // New items also use the highlighted version of the text.
- final boolean isHighlighted = isNew;
- mCallLogViewsHelper.setPhoneCallDetails(views, details, isHighlighted);
- setPhoto(views, photoId, lookupUri);
-
- // Listen for the first draw
- if (mViewTreeObserver == null) {
- mViewTreeObserver = view.getViewTreeObserver();
- mViewTreeObserver.addOnPreDrawListener(this);
- }
- }
-
- /** Checks whether the contact info from the call log matches the one from the contacts db. */
- private boolean callLogInfoMatches(ContactInfo callLogInfo, ContactInfo info) {
- // The call log only contains a subset of the fields in the contacts db.
- // Only check those.
- return TextUtils.equals(callLogInfo.name, info.name)
- && callLogInfo.type == info.type
- && TextUtils.equals(callLogInfo.label, info.label);
- }
-
- /** Stores the updated contact info in the call log if it is different from the current one. */
- private void updateCallLogContactInfoCache(String number, String countryIso,
- ContactInfo updatedInfo, ContactInfo callLogInfo) {
- final ContentValues values = new ContentValues();
- boolean needsUpdate = false;
-
- if (callLogInfo != null) {
- if (!TextUtils.equals(updatedInfo.name, callLogInfo.name)) {
- values.put(Calls.CACHED_NAME, updatedInfo.name);
- needsUpdate = true;
- }
-
- if (updatedInfo.type != callLogInfo.type) {
- values.put(Calls.CACHED_NUMBER_TYPE, updatedInfo.type);
- needsUpdate = true;
- }
-
- if (!TextUtils.equals(updatedInfo.label, callLogInfo.label)) {
- values.put(Calls.CACHED_NUMBER_LABEL, updatedInfo.label);
- needsUpdate = true;
- }
- if (!UriUtils.areEqual(updatedInfo.lookupUri, callLogInfo.lookupUri)) {
- values.put(Calls.CACHED_LOOKUP_URI, UriUtils.uriToString(updatedInfo.lookupUri));
- needsUpdate = true;
- }
- if (!TextUtils.equals(updatedInfo.normalizedNumber, callLogInfo.normalizedNumber)) {
- values.put(Calls.CACHED_NORMALIZED_NUMBER, updatedInfo.normalizedNumber);
- needsUpdate = true;
- }
- if (!TextUtils.equals(updatedInfo.number, callLogInfo.number)) {
- values.put(Calls.CACHED_MATCHED_NUMBER, updatedInfo.number);
- needsUpdate = true;
- }
- if (updatedInfo.photoId != callLogInfo.photoId) {
- values.put(Calls.CACHED_PHOTO_ID, updatedInfo.photoId);
- needsUpdate = true;
- }
- if (!TextUtils.equals(updatedInfo.formattedNumber, callLogInfo.formattedNumber)) {
- values.put(Calls.CACHED_FORMATTED_NUMBER, updatedInfo.formattedNumber);
- needsUpdate = true;
- }
- } else {
- // No previous values, store all of them.
- values.put(Calls.CACHED_NAME, updatedInfo.name);
- values.put(Calls.CACHED_NUMBER_TYPE, updatedInfo.type);
- values.put(Calls.CACHED_NUMBER_LABEL, updatedInfo.label);
- values.put(Calls.CACHED_LOOKUP_URI, UriUtils.uriToString(updatedInfo.lookupUri));
- values.put(Calls.CACHED_MATCHED_NUMBER, updatedInfo.number);
- values.put(Calls.CACHED_NORMALIZED_NUMBER, updatedInfo.normalizedNumber);
- values.put(Calls.CACHED_PHOTO_ID, updatedInfo.photoId);
- values.put(Calls.CACHED_FORMATTED_NUMBER, updatedInfo.formattedNumber);
- needsUpdate = true;
- }
-
- 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 });
- }
- }
-
- /** Returns the contact information as stored in the call log. */
- private ContactInfo getContactInfoFromCallLog(Cursor c) {
- ContactInfo info = new ContactInfo();
- info.lookupUri = UriUtils.parseUriOrNull(c.getString(CallLogQuery.CACHED_LOOKUP_URI));
- info.name = c.getString(CallLogQuery.CACHED_NAME);
- info.type = c.getInt(CallLogQuery.CACHED_NUMBER_TYPE);
- info.label = c.getString(CallLogQuery.CACHED_NUMBER_LABEL);
- String matchedNumber = c.getString(CallLogQuery.CACHED_MATCHED_NUMBER);
- info.number = matchedNumber == null ? c.getString(CallLogQuery.NUMBER) : matchedNumber;
- info.normalizedNumber = c.getString(CallLogQuery.CACHED_NORMALIZED_NUMBER);
- info.photoId = c.getLong(CallLogQuery.CACHED_PHOTO_ID);
- info.photoUri = null; // We do not cache the photo URI.
- info.formattedNumber = c.getString(CallLogQuery.CACHED_FORMATTED_NUMBER);
- return info;
- }
-
- /**
- * Returns the call types for the given number of items in the cursor.
- * <p>
- * It uses the next {@code count} rows in the cursor to extract the types.
- * <p>
- * It position in the cursor is unchanged by this function.
- */
- private int[] getCallTypes(Cursor cursor, int count) {
- int position = cursor.getPosition();
- int[] callTypes = new int[count];
- for (int index = 0; index < count; ++index) {
- callTypes[index] = cursor.getInt(CallLogQuery.CALL_TYPE);
- cursor.moveToNext();
- }
- cursor.moveToPosition(position);
- return callTypes;
- }
-
- private void setPhoto(CallLogListItemViews views, long photoId, Uri contactUri) {
- views.quickContactView.assignContactUri(contactUri);
- mContactPhotoManager.loadThumbnail(views.quickContactView, photoId, false /* darkTheme */);
- }
-
- /**
- * Sets whether processing of requests for contact details should be enabled.
- * <p>
- * This method should be called in tests to disable such processing of requests when not
- * needed.
- */
- @VisibleForTesting
- void disableRequestProcessingForTest() {
- mRequestProcessingDisabled = true;
- }
-
- @VisibleForTesting
- void injectContactInfoForTest(String number, String countryIso, ContactInfo contactInfo) {
- NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso);
- mContactInfoCache.put(numberCountryIso, contactInfo);
- }
-
- @Override
- public void addGroup(int cursorPosition, int size, boolean expanded) {
- super.addGroup(cursorPosition, size, expanded);
- }
-
- /*
- * Get the number from the Contacts, if available, since sometimes
- * the number provided by caller id may not be formatted properly
- * depending on the carrier (roaming) in use at the time of the
- * incoming call.
- * Logic : If the caller-id number starts with a "+", use it
- * Else if the number in the contacts starts with a "+", use that one
- * Else if the number in the contacts is longer, use that one
- */
- public String getBetterNumberFromContacts(String number, String countryIso) {
- String matchingNumber = null;
- // Look in the cache first. If it's not found then query the Phones db
- NumberWithCountryIso numberCountryIso = new NumberWithCountryIso(number, countryIso);
- ContactInfo ci = mContactInfoCache.getPossiblyExpired(numberCountryIso);
- if (ci != null && ci != ContactInfo.EMPTY) {
- matchingNumber = ci.number;
- } else {
- try {
- Cursor phonesCursor = mContext.getContentResolver().query(
- Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number),
- PhoneQuery._PROJECTION, null, null, null);
- if (phonesCursor != null) {
- if (phonesCursor.moveToFirst()) {
- matchingNumber = phonesCursor.getString(PhoneQuery.MATCHED_NUMBER);
- }
- phonesCursor.close();
- }
- } catch (Exception e) {
- // Use the number from the call log
- }
- }
- if (!TextUtils.isEmpty(matchingNumber) &&
- (matchingNumber.startsWith("+")
- || matchingNumber.length() > number.length())) {
- number = matchingNumber;
- }
- return number;
- }
-}
diff --git a/src/com/android/dialer/calllog/NewCallLogFragment.java b/src/com/android/dialer/calllog/NewCallLogFragment.java
deleted file mode 100644
index c470c55d4..000000000
--- a/src/com/android/dialer/calllog/NewCallLogFragment.java
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.dialer.calllog;
-
-import android.app.Activity;
-import android.app.KeyguardManager;
-import android.app.ListFragment;
-import android.content.Context;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.CallLog;
-import android.provider.CallLog.Calls;
-import android.provider.ContactsContract;
-import android.telephony.PhoneNumberUtils;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import com.android.common.io.MoreCloseables;
-import com.android.contacts.common.CallUtil;
-import com.android.contacts.common.GeoUtil;
-import com.android.dialer.R;
-import com.android.dialer.util.EmptyLoader;
-import com.android.dialer.voicemail.VoicemailStatusHelper;
-import com.android.dialer.voicemail.VoicemailStatusHelper.StatusMessage;
-import com.android.dialer.voicemail.VoicemailStatusHelperImpl;
-import com.android.internal.telephony.ITelephony;
-import com.google.common.annotations.VisibleForTesting;
-
-import java.util.List;
-
-/**
- * Displays a list of call log entries. To filter for a particular kind of call
- * (all, missed or voicemails), specify it in the constructor.
- */
-public class NewCallLogFragment extends ListFragment
- implements CallLogQueryHandler.Listener, NewCallLogAdapter.CallFetcher {
- private static final String TAG = "CallLogFragment";
-
- /**
- * ID of the empty loader to defer other fragments.
- */
- private static final int EMPTY_LOADER_ID = 0;
-
- private NewCallLogAdapter mAdapter;
- private CallLogQueryHandler mCallLogQueryHandler;
- private boolean mScrollToTop;
-
- /** Whether there is at least one voicemail source installed. */
- private boolean mVoicemailSourcesAvailable = false;
-
- private VoicemailStatusHelper mVoicemailStatusHelper;
- private View mStatusMessageView;
- private TextView mStatusMessageText;
- private TextView mStatusMessageAction;
- private KeyguardManager mKeyguardManager;
-
- private boolean mEmptyLoaderRunning;
- private boolean mCallLogFetched;
- private boolean mVoicemailStatusFetched;
-
- private final Handler mHandler = new Handler();
-
- private TelephonyManager mTelephonyManager;
- private PhoneStateListener mPhoneStateListener;
-
- private class CustomContentObserver extends ContentObserver {
- public CustomContentObserver() {
- super(mHandler);
- }
- @Override
- public void onChange(boolean selfChange) {
- mRefreshDataRequired = true;
- }
- }
-
- // See issue 6363009
- private final ContentObserver mCallLogObserver = new CustomContentObserver();
- private final ContentObserver mContactsObserver = new CustomContentObserver();
- private boolean mRefreshDataRequired = true;
-
- // Exactly same variable is in Fragment as a package private.
- private boolean mMenuVisible = true;
-
- // Default to all calls.
- private int mCallTypeFilter = CallLogQueryHandler.CALL_TYPE_ALL;
-
- // Log limit - if no limit is specified, then the default in {@link NewCallLogQueryHandler}
- // will be used.
- private int mLogLimit = -1;
-
- public NewCallLogFragment() {
- this(CallLogQueryHandler.CALL_TYPE_ALL, -1);
- }
-
- public NewCallLogFragment(int filterType) {
- this(filterType, -1);
- }
-
- public NewCallLogFragment(int filterType, int logLimit) {
- super();
- mCallTypeFilter = filterType;
- mLogLimit = logLimit;
- }
-
- @Override
- public void onCreate(Bundle state) {
- super.onCreate(state);
-
- mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(),
- this, mLogLimit);
- mKeyguardManager =
- (KeyguardManager) getActivity().getSystemService(Context.KEYGUARD_SERVICE);
- getActivity().getContentResolver().registerContentObserver(
- CallLog.CONTENT_URI, true, mCallLogObserver);
- getActivity().getContentResolver().registerContentObserver(
- ContactsContract.Contacts.CONTENT_URI, true, mContactsObserver);
- setHasOptionsMenu(true);
- updateCallList(mCallTypeFilter);
- }
-
- /** Called by the CallLogQueryHandler when the list of calls has been fetched or updated. */
- @Override
- public void onCallsFetched(Cursor cursor) {
- if (getActivity() == null || getActivity().isFinishing()) {
- return;
- }
- mAdapter.setLoading(false);
- mAdapter.changeCursor(cursor);
- // This will update the state of the "Clear call log" menu item.
- getActivity().invalidateOptionsMenu();
- if (mScrollToTop) {
- final ListView listView = getListView();
- // The smooth-scroll animation happens over a fixed time period.
- // As a result, if it scrolls through a large portion of the list,
- // each frame will jump so far from the previous one that the user
- // will not experience the illusion of downward motion. Instead,
- // if we're not already near the top of the list, we instantly jump
- // near the top, and animate from there.
- if (listView.getFirstVisiblePosition() > 5) {
- listView.setSelection(5);
- }
- // Workaround for framework issue: the smooth-scroll doesn't
- // occur if setSelection() is called immediately before.
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (getActivity() == null || getActivity().isFinishing()) {
- return;
- }
- listView.smoothScrollToPosition(0);
- }
- });
-
- mScrollToTop = false;
- }
- mCallLogFetched = true;
- destroyEmptyLoaderIfAllDataFetched();
- }
-
- /**
- * Called by {@link CallLogQueryHandler} after a successful query to voicemail status provider.
- */
- @Override
- public void onVoicemailStatusFetched(Cursor statusCursor) {
- if (getActivity() == null || getActivity().isFinishing()) {
- return;
- }
- updateVoicemailStatusMessage(statusCursor);
-
- int activeSources = mVoicemailStatusHelper.getNumberActivityVoicemailSources(statusCursor);
- setVoicemailSourcesAvailable(activeSources != 0);
- MoreCloseables.closeQuietly(statusCursor);
- mVoicemailStatusFetched = true;
- destroyEmptyLoaderIfAllDataFetched();
- }
-
- private void destroyEmptyLoaderIfAllDataFetched() {
- if (mCallLogFetched && mVoicemailStatusFetched && mEmptyLoaderRunning) {
- mEmptyLoaderRunning = false;
- getLoaderManager().destroyLoader(EMPTY_LOADER_ID);
- }
- }
-
- /** Sets whether there are any voicemail sources available in the platform. */
- private void setVoicemailSourcesAvailable(boolean voicemailSourcesAvailable) {
- if (mVoicemailSourcesAvailable == voicemailSourcesAvailable) return;
- mVoicemailSourcesAvailable = voicemailSourcesAvailable;
-
- Activity activity = getActivity();
- if (activity != null) {
- // This is so that the options menu content is updated.
- activity.invalidateOptionsMenu();
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- View view = inflater.inflate(R.layout.new_call_log_fragment, container, false);
- mVoicemailStatusHelper = new VoicemailStatusHelperImpl();
- mStatusMessageView = view.findViewById(R.id.voicemail_status);
- mStatusMessageText = (TextView) view.findViewById(R.id.voicemail_status_message);
- mStatusMessageAction = (TextView) view.findViewById(R.id.voicemail_status_action);
- return view;
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- updateEmptyMessage(mCallTypeFilter);
- String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
- mAdapter = new NewCallLogAdapter(getActivity(), this,
- new ContactInfoHelper(getActivity(), currentCountryIso));
- setListAdapter(mAdapter);
- getListView().setItemsCanFocus(true);
- }
-
- /**
- * Based on the new intent, decide whether the list should be configured
- * to scroll up to display the first item.
- */
- public void configureScreenFromIntent(Intent newIntent) {
- // Typically, when switching to the call-log we want to show the user
- // the same section of the list that they were most recently looking
- // at. However, under some circumstances, we want to automatically
- // scroll to the top of the list to present the newest call items.
- // For example, immediately after a call is finished, we want to
- // display information about that call.
- mScrollToTop = Calls.CONTENT_TYPE.equals(newIntent.getType());
- }
-
- @Override
- public void onStart() {
- // Start the empty loader now to defer other fragments. We destroy it when both calllog
- // and the voicemail status are fetched.
- getLoaderManager().initLoader(EMPTY_LOADER_ID, null,
- new EmptyLoader.Callback(getActivity()));
- mEmptyLoaderRunning = true;
- super.onStart();
- }
-
- @Override
- public void onResume() {
- Log.d(TAG, "Call Log Fragment resume");
- super.onResume();
- refreshData();
- }
-
- private void updateVoicemailStatusMessage(Cursor statusCursor) {
- List<StatusMessage> messages = mVoicemailStatusHelper.getStatusMessages(statusCursor);
- if (messages.size() == 0) {
- mStatusMessageView.setVisibility(View.GONE);
- } else {
- mStatusMessageView.setVisibility(View.VISIBLE);
- // TODO: Change the code to show all messages. For now just pick the first message.
- final StatusMessage message = messages.get(0);
- if (message.showInCallLog()) {
- mStatusMessageText.setText(message.callLogMessageId);
- }
- if (message.actionMessageId != -1) {
- mStatusMessageAction.setText(message.actionMessageId);
- }
- if (message.actionUri != null) {
- mStatusMessageAction.setVisibility(View.VISIBLE);
- mStatusMessageAction.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getActivity().startActivity(
- new Intent(Intent.ACTION_VIEW, message.actionUri));
- }
- });
- } else {
- mStatusMessageAction.setVisibility(View.GONE);
- }
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- // Kill the requests thread
- mAdapter.stopRequestProcessing();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- updateOnExit();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mAdapter.stopRequestProcessing();
- mAdapter.changeCursor(null);
- getActivity().getContentResolver().unregisterContentObserver(mCallLogObserver);
- getActivity().getContentResolver().unregisterContentObserver(mContactsObserver);
- unregisterPhoneCallReceiver();
- }
-
- @Override
- public void fetchCalls() {
- mCallLogQueryHandler.fetchCalls(mCallTypeFilter);
- }
-
- public void startCallsQuery() {
- mAdapter.setLoading(true);
- mCallLogQueryHandler.fetchCalls(mCallTypeFilter);
- }
-
- private void startVoicemailStatusQuery() {
- mCallLogQueryHandler.fetchVoicemailStatus();
- }
-
- private void updateCallList(int filterType) {
- if (filterType == CallLogQueryHandler.CALL_TYPE_ALL) {
- unregisterPhoneCallReceiver();
- } else {
- // TODO krelease: Make this work
- //registerPhoneCallReceiver();
- }
- mCallLogQueryHandler.fetchCalls(filterType);
- }
-
- private void updateEmptyMessage(int filterType) {
- final String message;
- switch (filterType) {
- case Calls.MISSED_TYPE:
- message = getString(R.string.recentMissed_empty);
- break;
- case Calls.VOICEMAIL_TYPE:
- message = getString(R.string.recentVoicemails_empty);
- break;
- default:
- message = getString(R.string.recentCalls_empty);
- break;
- }
- ((TextView) getListView().getEmptyView()).setText(message);
- }
-
- public void callSelectedEntry() {
- int position = getListView().getSelectedItemPosition();
- if (position < 0) {
- // In touch mode you may often not have something selected, so
- // just call the first entry to make sure that [send] [send] calls the
- // most recent entry.
- position = 0;
- }
- final Cursor cursor = (Cursor)mAdapter.getItem(position);
- if (cursor != null) {
- String number = cursor.getString(CallLogQuery.NUMBER);
- int numberPresentation = cursor.getInt(CallLogQuery.NUMBER_PRESENTATION);
- if (!PhoneNumberHelper.canPlaceCallsTo(number, numberPresentation)) {
- // This number can't be called, do nothing
- return;
- }
- Intent intent;
- // If "number" is really a SIP address, construct a sip: URI.
- if (PhoneNumberUtils.isUriNumber(number)) {
- intent = CallUtil.getCallIntent(
- Uri.fromParts(CallUtil.SCHEME_SIP, number, null));
- } else {
- // We're calling a regular PSTN phone number.
- // Construct a tel: URI, but do some other possible cleanup first.
- int callType = cursor.getInt(CallLogQuery.CALL_TYPE);
- if (!number.startsWith("+") &&
- (callType == Calls.INCOMING_TYPE
- || callType == Calls.MISSED_TYPE)) {
- // If the caller-id matches a contact with a better qualified number, use it
- String countryIso = cursor.getString(CallLogQuery.COUNTRY_ISO);
- number = mAdapter.getBetterNumberFromContacts(number, countryIso);
- }
- intent = CallUtil.getCallIntent(
- Uri.fromParts(CallUtil.SCHEME_TEL, number, null));
- }
- intent.setFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- startActivity(intent);
- }
- }
-
- NewCallLogAdapter getAdapter() {
- return mAdapter;
- }
-
- @Override
- public void setMenuVisibility(boolean menuVisible) {
- super.setMenuVisibility(menuVisible);
- if (mMenuVisible != menuVisible) {
- mMenuVisible = menuVisible;
- if (!menuVisible) {
- updateOnExit();
- } else if (isResumed()) {
- refreshData();
- }
- }
- }
-
- /** Requests updates to the data to be shown. */
- private void refreshData() {
- // Prevent unnecessary refresh.
- if (mRefreshDataRequired) {
- // Mark all entries in the contact info cache as out of date, so they will be looked up
- // again once being shown.
- mAdapter.invalidateCache();
- startCallsQuery();
- startVoicemailStatusQuery();
- updateOnEntry();
- mRefreshDataRequired = false;
- }
- }
-
- /** Removes the missed call notifications. */
- private void removeMissedCallNotifications() {
- try {
- ITelephony telephony =
- ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
- if (telephony != null) {
- telephony.cancelMissedCallsNotification();
- } else {
- Log.w(TAG, "Telephony service is null, can't call " +
- "cancelMissedCallsNotification");
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to clear missed calls notification due to remote exception");
- }
- }
-
- /** Updates call data and notification state while leaving the call log tab. */
- private void updateOnExit() {
- updateOnTransition(false);
- }
-
- /** Updates call data and notification state while entering the call log tab. */
- private void updateOnEntry() {
- updateOnTransition(true);
- }
-
- // TODO krelease: Figure out if we still need this. If so, it should be probably be moved to
- // the call log activity instead, or done only in a single call log fragment.
- private void updateOnTransition(boolean onEntry) {
- // We don't want to update any call data when keyguard is on because the user has likely not
- // seen the new calls yet.
- // This might be called before onCreate() and thus we need to check null explicitly.
- if (mKeyguardManager != null && !mKeyguardManager.inKeyguardRestrictedInputMode()) {
- // On either of the transitions we reset the new flag and update the notifications.
- // While exiting we additionally consume all missed calls (by marking them as read).
- // This will ensure that they no more appear in the "new" section when we return back.
- mCallLogQueryHandler.markNewCallsAsOld();
- if (!onEntry) {
- mCallLogQueryHandler.markMissedCallsAsRead();
- }
- removeMissedCallNotifications();
- updateVoicemailNotifications();
- }
- }
-
- private void updateVoicemailNotifications() {
- Intent serviceIntent = new Intent(getActivity(), CallLogNotificationsService.class);
- serviceIntent.setAction(CallLogNotificationsService.ACTION_UPDATE_NOTIFICATIONS);
- getActivity().startService(serviceIntent);
- }
-
- // TODO krelease: Make the ViewPager switch to the correct tab (All) when a phone call is
- // placed.
- // This should probably be moved to the call log activity.
- /**
- * Register a phone call filter to reset the call type when a phone call is place.
- */
- /*
- private void registerPhoneCallReceiver() {
- if (mPhoneStateListener != null) {
- return; // Already registered.
- }
- mTelephonyManager = (TelephonyManager) getActivity().getSystemService(
- Context.TELEPHONY_SERVICE);
- mPhoneStateListener = new PhoneStateListener() {
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- if (state != TelephonyManager.CALL_STATE_OFFHOOK &&
- state != TelephonyManager.CALL_STATE_RINGING) {
- return;
- }
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (getActivity() == null || getActivity().isFinishing()) {
- return;
- }
- }
- });
- }
- };
- mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
- }
- */
-
- /**
- * Un-registers the phone call receiver.
- */
- private void unregisterPhoneCallReceiver() {
- if (mPhoneStateListener != null) {
- mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
- mPhoneStateListener = null;
- }
- }
-}
diff --git a/src/com/android/dialer/calllog/NewCallLogListItemHelper.java b/src/com/android/dialer/calllog/NewCallLogListItemHelper.java
deleted file mode 100644
index 6b4f10151..000000000
--- a/src/com/android/dialer/calllog/NewCallLogListItemHelper.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.dialer.calllog;
-
-import android.content.res.Resources;
-import android.provider.CallLog.Calls;
-import android.text.TextUtils;
-import android.view.View;
-
-import com.android.dialer.PhoneCallDetails;
-import com.android.dialer.PhoneCallDetailsHelper;
-import com.android.dialer.R;
-
-/**
- * Helper class to fill in the views of a call log entry.
- * TODO krelease: The only difference between this and the original is that we don't touch
- * divider views, which are not present in the new dialer. Once the new dialer replaces
- * the old one, we can replace it entirely. Otherwise we would have redundant divider=null
- * checks all over the place.
- */
-/* package */class NewCallLogListItemHelper {
- /** Helper for populating the details of a phone call. */
- private final PhoneCallDetailsHelper mPhoneCallDetailsHelper;
- /** Helper for handling phone numbers. */
- private final PhoneNumberHelper mPhoneNumberHelper;
- /** Resources to look up strings. */
- private final Resources mResources;
-
- /**
- * Creates a new helper instance.
- *
- * @param phoneCallDetailsHelper used to set the details of a phone call
- * @param phoneNumberHelper used to process phone number
- */
- public NewCallLogListItemHelper(PhoneCallDetailsHelper phoneCallDetailsHelper,
- PhoneNumberHelper phoneNumberHelper, Resources resources) {
- mPhoneCallDetailsHelper = phoneCallDetailsHelper;
- mPhoneNumberHelper = phoneNumberHelper;
- mResources = resources;
- }
-
- /**
- * Sets the name, label, and number for a contact.
- *
- * @param views the views to populate
- * @param details the details of a phone call needed to fill in the data
- * @param isHighlighted whether to use the highlight text for the call
- */
- public void setPhoneCallDetails(CallLogListItemViews views, PhoneCallDetails details,
- boolean isHighlighted) {
- mPhoneCallDetailsHelper.setPhoneCallDetails(views.phoneCallDetailsViews, details,
- isHighlighted);
- boolean canCall = PhoneNumberHelper.canPlaceCallsTo(details.number,
- details.numberPresentation);
- boolean canPlay = details.callTypes[0] == Calls.VOICEMAIL_TYPE;
-
- if (canPlay) {
- // Playback action takes preference.
- configurePlaySecondaryAction(views, isHighlighted);
- } else if (canCall) {
- // Call is the secondary action.
- configureCallSecondaryAction(views, details);
- } else {
- // No action available.
- views.secondaryActionView.setVisibility(View.GONE);
- }
- }
-
- /** Sets the secondary action to correspond to the call button. */
- private void configureCallSecondaryAction(CallLogListItemViews views,
- PhoneCallDetails details) {
- views.secondaryActionView.setVisibility(View.VISIBLE);
- views.secondaryActionView.setImageResource(R.drawable.ic_ab_dialer_holo_light);
- views.secondaryActionView.setContentDescription(getCallActionDescription(details));
- }
-
- /** Returns the description used by the call action for this phone call. */
- private CharSequence getCallActionDescription(PhoneCallDetails details) {
- final CharSequence recipient;
- if (!TextUtils.isEmpty(details.name)) {
- recipient = details.name;
- } else {
- recipient = mPhoneNumberHelper.getDisplayNumber(
- details.number, details.numberPresentation, details.formattedNumber);
- }
- return mResources.getString(R.string.description_call, recipient);
- }
-
- /** Sets the secondary action to correspond to the play button. */
- private void configurePlaySecondaryAction(CallLogListItemViews views, boolean isHighlighted) {
- views.secondaryActionView.setVisibility(View.VISIBLE);
- views.secondaryActionView.setImageResource(
- isHighlighted ? R.drawable.ic_play_active_holo_dark : R.drawable.ic_play_holo_light);
- views.secondaryActionView.setContentDescription(
- mResources.getString(R.string.description_call_log_play_button));
- }
-}
diff --git a/src/com/android/dialer/list/NewPhoneFavoriteFragment.java b/src/com/android/dialer/list/NewPhoneFavoriteFragment.java
index 283c7dba0..58dac2fb6 100644
--- a/src/com/android/dialer/list/NewPhoneFavoriteFragment.java
+++ b/src/com/android/dialer/list/NewPhoneFavoriteFragment.java
@@ -45,7 +45,7 @@ import com.android.contacts.common.list.PhoneNumberListAdapter;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.R;
import com.android.dialer.calllog.ContactInfoHelper;
-import com.android.dialer.calllog.NewCallLogAdapter;
+import com.android.dialer.calllog.CallLogAdapter;
import com.android.dialer.calllog.CallLogQueryHandler;
/**
@@ -57,7 +57,7 @@ import com.android.dialer.calllog.CallLogQueryHandler;
* A contact filter header is also inserted between those adapters' results.
*/
public class NewPhoneFavoriteFragment extends Fragment implements OnItemClickListener,
- CallLogQueryHandler.Listener, NewCallLogAdapter.CallFetcher {
+ CallLogQueryHandler.Listener, CallLogAdapter.CallFetcher {
private static final String TAG = NewPhoneFavoriteFragment.class.getSimpleName();
private static final boolean DEBUG = false;
@@ -138,7 +138,7 @@ public class NewPhoneFavoriteFragment extends Fragment implements OnItemClickLis
private PhoneFavoritesTileAdapter mContactTileAdapter;
private PhoneNumberListAdapter mAllContactsAdapter;
- private NewCallLogAdapter mCallLogAdapter;
+ private CallLogAdapter mCallLogAdapter;
private CallLogQueryHandler mCallLogQueryHandler;
private TextView mEmptyView;
@@ -187,7 +187,7 @@ public class NewPhoneFavoriteFragment extends Fragment implements OnItemClickLis
mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(),
this, 1);
final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
- mCallLogAdapter = new NewCallLogAdapter(getActivity(), this,
+ mCallLogAdapter = new CallLogAdapter(getActivity(), this,
new ContactInfoHelper(getActivity(), currentCountryIso));
setHasOptionsMenu(true);
}
diff --git a/src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java b/src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java
index 28604b963..3c3200407 100644
--- a/src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java
+++ b/src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java
@@ -25,11 +25,11 @@ import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import com.android.dialer.R;
-import com.android.dialer.calllog.NewCallLogAdapter;
+import com.android.dialer.calllog.CallLogAdapter;
/**
* An adapter that combines items from {@link com.android.contacts.common.list.ContactTileAdapter}
- * and {@link com.android.dialer.calllog.NewCallLogAdapter} into a single list.
+ * and {@link com.android.dialer.calllog.CallLogAdapter} into a single list.
*/
public class NewPhoneFavoriteMergedAdapter extends BaseAdapter {
@@ -43,7 +43,7 @@ public class NewPhoneFavoriteMergedAdapter extends BaseAdapter {
private static final String TAG = NewPhoneFavoriteMergedAdapter.class.getSimpleName();
private final PhoneFavoritesTileAdapter mContactTileAdapter;
- private final NewCallLogAdapter mCallLogAdapter;
+ private final CallLogAdapter mCallLogAdapter;
private final View mLoadingView;
private final View mShowAllContactsButton;
@@ -56,7 +56,7 @@ public class NewPhoneFavoriteMergedAdapter extends BaseAdapter {
public NewPhoneFavoriteMergedAdapter(Context context,
PhoneFavoritesTileAdapter contactTileAdapter,
View accountFilterHeaderContainer,
- NewCallLogAdapter callLogAdapter,
+ CallLogAdapter callLogAdapter,
View loadingView,
View showAllContactsButton) {
final Resources resources = context.getResources();