diff options
Diffstat (limited to 'java/com/android/dialer/app/calllog')
12 files changed, 292 insertions, 179 deletions
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index 301fc009e..06f48aa20 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -17,6 +17,7 @@ package com.android.dialer.app.calllog; import android.app.Activity; +import android.content.ContentUris; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; @@ -38,7 +39,12 @@ import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.SparseBooleanArray; +import android.view.ActionMode; 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 com.android.contacts.common.ContactsUtils; @@ -58,6 +64,7 @@ import com.android.dialer.calldetails.nano.CallDetailsEntries.CallDetailsEntry; import com.android.dialer.calllogutils.PhoneAccountUtils; import com.android.dialer.calllogutils.PhoneCallDetails; import com.android.dialer.common.Assert; +import com.android.dialer.common.ConfigProviderBindings; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.AsyncTaskExecutor; import com.android.dialer.common.concurrent.AsyncTaskExecutors; @@ -65,6 +72,9 @@ import com.android.dialer.enrichedcall.EnrichedCallCapabilities; import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.enrichedcall.EnrichedCallManager; import com.android.dialer.enrichedcall.historyquery.proto.nano.HistoryResult; +import com.android.dialer.lightbringer.Lightbringer; +import com.android.dialer.lightbringer.LightbringerComponent; +import com.android.dialer.lightbringer.LightbringerListener; import com.android.dialer.logging.Logger; import com.android.dialer.logging.nano.DialerImpression; import com.android.dialer.phonenumbercache.CallLogQuery; @@ -80,7 +90,7 @@ import java.util.Set; /** Adapter class to fill in data for the Call Log. */ public class CallLogAdapter extends GroupingListAdapter - implements GroupCreator, OnVoicemailDeletedListener { + implements GroupCreator, OnVoicemailDeletedListener, LightbringerListener { // Types of activities the call log adapter is used for public static final int ACTIVITY_TYPE_CALL_LOG = 1; @@ -118,6 +128,58 @@ public class CallLogAdapter extends GroupingListAdapter private long mCurrentlyExpandedRowId = NO_EXPANDED_LIST_ITEM; private final CallLogAlertManager mCallLogAlertManager; + + public static ActionMode mActionMode = null; + private final SparseBooleanArray selectedItems = new SparseBooleanArray(); + + private final ActionMode.Callback mActionModeCallback = + new ActionMode.Callback() { + + // Called when the action mode is created; startActionMode() was called + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mActionMode = mode; + // Inflate a menu resource providing context menu items + MenuInflater inflater = mode.getMenuInflater(); + inflater.inflate(R.menu.actionbar_delete, menu); + return true; + } + + // Called each time the action mode is shown. Always called after onCreateActionMode, but + // may be called multiple times if the mode is invalidated. + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; // Return false if nothing is done + } + + // Called when the user selects a contextual menu item + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + return false; + } + + // Called when the user exits the action mode + @Override + public void onDestroyActionMode(ActionMode mode) { + selectedItems.clear(); + mActionMode = null; + notifyDataSetChanged(); + } + }; + + private final View.OnLongClickListener mLongPressListener = + new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (ConfigProviderBindings.get(v.getContext()) + .getBoolean("enable_call_log_multiselect", false)) { + v.startActionMode(mActionModeCallback); + return false; + } + return true; + } + }; + /** The OnClickListener used to expand or collapse the action buttons of a call log entry. */ private final View.OnClickListener mExpandCollapseListener = new View.OnClickListener() { @@ -127,6 +189,20 @@ public class CallLogAdapter extends GroupingListAdapter if (viewHolder == null) { return; } + if (mActionMode != null && viewHolder.voicemailUri != null) { + if (selectedItems.get((int) ContentUris.parseId(Uri.parse(viewHolder.voicemailUri)))) { + selectedItems.delete((int) ContentUris.parseId(Uri.parse(viewHolder.voicemailUri))); + viewHolder.checkBoxView.setVisibility(View.GONE); + viewHolder.quickContactView.setVisibility(View.VISIBLE); + } else { + viewHolder.quickContactView.setVisibility(View.GONE); + viewHolder.checkBoxView.setVisibility(View.VISIBLE); + selectedItems.put( + (int) ContentUris.parseId(Uri.parse(viewHolder.voicemailUri)), true); + } + mActionMode.setTitle(Integer.toString(selectedItems.size())); + return; + } if (mVoicemailPlaybackPresenter != null) { // Always reset the voicemail playback state on expand or collapse. @@ -313,10 +389,12 @@ public class CallLogAdapter extends GroupingListAdapter } mContactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY); mIsSpamEnabled = Spam.get(mActivity).isSpamEnabled(); + getLightbringer().registerListener(this); notifyDataSetChanged(); } public void onPause() { + getLightbringer().unregisterListener(this); pauseCache(); for (Uri uri : mHiddenItemUris) { CallLogAsyncTaskUtil.deleteVoicemail(mActivity, uri, null); @@ -365,6 +443,7 @@ public class CallLogAdapter extends GroupingListAdapter mActivity, mBlockReportSpamListener, mExpandCollapseListener, + mLongPressListener, mCallLogCache, mCallLogListItemHelper, mVoicemailPlaybackPresenter); @@ -471,6 +550,7 @@ public class CallLogAdapter extends GroupingListAdapter setCallDetailsEntriesHistoryResults( views.number, callDetailsEntries, getAllHistoricalData(views.number, callDetailsEntries)); views.setDetailedPhoneDetails(callDetailsEntries); + views.lightbringerReady = getLightbringer().isReachable(mActivity, views.number); final AsyncTask<Void, Void, Boolean> loadDataTask = new AsyncTask<Void, Void, Boolean>() { @Override @@ -741,6 +821,15 @@ public class CallLogAdapter extends GroupingListAdapter views.workIconView.setVisibility( details.contactUserType == ContactsUtils.USER_TYPE_WORK ? View.VISIBLE : View.GONE); + if (views.voicemailUri != null + && selectedItems.get((int) ContentUris.parseId(Uri.parse(views.voicemailUri)))) { + views.checkBoxView.setVisibility(View.VISIBLE); + views.quickContactView.setVisibility(View.GONE); + } else if (views.voicemailUri != null) { + views.checkBoxView.setVisibility(View.GONE); + views.quickContactView.setVisibility(View.VISIBLE); + } + mCallLogListItemHelper.setPhoneCallDetails(views, details); if (mCurrentlyExpandedRowId == views.rowId) { // In case ViewHolders were added/removed, update the expanded position if the rowIds @@ -997,6 +1086,16 @@ public class CallLogAdapter extends GroupingListAdapter return EnrichedCallComponent.get(mActivity).getEnrichedCallManager(); } + @NonNull + private Lightbringer getLightbringer() { + return LightbringerComponent.get(mActivity).getLightbringer(); + } + + @Override + public void onLightbringerStateChanged() { + notifyDataSetChanged(); + } + /** Interface used to initiate a refresh of the content. */ public interface CallFetcher { diff --git a/java/com/android/dialer/app/calllog/CallLogFragment.java b/java/com/android/dialer/app/calllog/CallLogFragment.java index 4abef3430..fcc34ebef 100644 --- a/java/com/android/dialer/app/calllog/CallLogFragment.java +++ b/java/com/android/dialer/app/calllog/CallLogFragment.java @@ -49,11 +49,11 @@ import com.android.dialer.app.contactinfo.ContactInfoCache; import com.android.dialer.app.contactinfo.ContactInfoCache.OnContactInfoChangedListener; import com.android.dialer.app.contactinfo.ExpirableCacheHeadlessFragment; import com.android.dialer.app.list.ListsFragment; -import com.android.dialer.app.list.ListsFragment.ListsPage; import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter; import com.android.dialer.app.widget.EmptyContentView; import com.android.dialer.app.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; +import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.database.CallLogQueryHandler; import com.android.dialer.phonenumbercache.ContactInfoHelper; @@ -64,8 +64,7 @@ import com.android.dialer.util.PermissionsUtil; * voicemails), specify it in the constructor. */ public class CallLogFragment extends Fragment - implements ListsPage, - CallLogQueryHandler.Listener, + implements CallLogQueryHandler.Listener, CallLogAdapter.CallFetcher, OnEmptyViewActionButtonClickedListener, FragmentCompat.OnRequestPermissionsResultCallback, @@ -133,6 +132,8 @@ public class CallLogFragment extends Fragment refreshData(); rescheduleDisplayUpdate(); break; + default: + throw Assert.createAssertionFailException("Invalid message: " + msg); } } }; @@ -541,20 +542,18 @@ public class CallLogFragment extends Fragment mDisplayUpdateHandler.removeMessages(EVENT_UPDATE_DISPLAY); } - @Override @CallSuper - public void onPageResume(@Nullable Activity activity) { - LogUtil.d("CallLogFragment.onPageResume", "frag: %s", this); - if (activity != null) { - ((HostInterface) activity) + public void onVisible() { + LogUtil.enterBlock("CallLogFragment.onPageSelected"); + if (getActivity() != null) { + ((HostInterface) getActivity()) .enableFloatingButton(mModalAlertManager == null || mModalAlertManager.isEmpty()); } } - @Override @CallSuper - public void onPagePause(@Nullable Activity activity) { - LogUtil.d("CallLogFragment.onPagePause", "frag: %s", this); + public void onNotVisible() { + LogUtil.enterBlock("CallLogFragment.onPageUnselected"); } @Override diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java index 6a3187fa8..9adcddb3c 100644 --- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java +++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java @@ -22,19 +22,16 @@ import android.content.Intent; import android.content.res.Resources; import android.net.Uri; import android.os.AsyncTask; -import android.provider.CallLog; import android.provider.CallLog.Calls; import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.support.annotation.NonNull; import android.support.annotation.VisibleForTesting; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.PhoneNumberUtils; -import android.text.BidiFormatter; -import android.text.TextDirectionHeuristics; import android.text.TextUtils; -import android.view.ContextMenu; import android.view.MenuItem; import android.view.View; import android.view.ViewStub; @@ -45,7 +42,6 @@ import android.widget.TextView; import com.android.contacts.common.ClipboardUtils; import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest; -import com.android.contacts.common.compat.PhoneNumberUtilsCompat; import com.android.contacts.common.dialog.CallSubjectDialog; import com.android.contacts.common.util.UriUtils; import com.android.dialer.app.DialtactsActivity; @@ -61,10 +57,13 @@ import com.android.dialer.callcomposer.nano.CallComposerContact; import com.android.dialer.calldetails.nano.CallDetailsEntries; import com.android.dialer.common.LogUtil; import com.android.dialer.compat.CompatUtils; +import com.android.dialer.lightbringer.Lightbringer; +import com.android.dialer.lightbringer.LightbringerComponent; import com.android.dialer.logging.Logger; import com.android.dialer.logging.nano.DialerImpression; -import com.android.dialer.logging.nano.ScreenEvent; +import com.android.dialer.phonenumbercache.CachedNumberLookupService; import com.android.dialer.phonenumbercache.ContactInfo; +import com.android.dialer.phonenumbercache.PhoneNumberCache; import com.android.dialer.phonenumberutil.PhoneNumberHelper; import com.android.dialer.util.CallUtil; import com.android.dialer.util.DialerUtils; @@ -77,9 +76,7 @@ import com.android.dialer.util.DialerUtils; * CallLogAdapter. */ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder - implements View.OnClickListener, - MenuItem.OnMenuItemClickListener, - View.OnCreateContextMenuListener { + implements View.OnClickListener, MenuItem.OnMenuItemClickListener { /** The root view of the call log list item */ public final View rootView; /** The quick contact badge for the contact. */ @@ -98,6 +95,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder private final Context mContext; private final CallLogCache mCallLogCache; private final CallLogListItemHelper mCallLogListItemHelper; + private final CachedNumberLookupService mCachedNumberLookupService; private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; private final OnClickListener mBlockReportListener; private final int mPhotoSize; @@ -122,6 +120,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder public View callComposeButtonView; public View sendVoicemailButtonView; public ImageView workIconView; + public ImageView checkBoxView; /** * The row Id for the first call associated with the call log entry. Used as a key for the map * used to track which call log entries have the action button section expanded. @@ -182,8 +181,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder * voicemail log's call button */ public CharSequence callTypeOrLocation; - /** Whether this row is for a business or not. */ - public boolean isBusiness; /** The contact info for the contact displayed in this list item. */ public volatile ContactInfo info; /** Whether spam feature is enabled, which affects UI. */ @@ -192,8 +189,10 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder public boolean isSpam; public boolean isCallComposerCapable; + public boolean lightbringerReady; private View.OnClickListener mExpandCollapseListener; + private final View.OnLongClickListener longPressListener; private boolean mVoicemailPrimaryActionButtonClicked; public int dayGroupHeaderVisibility; @@ -207,6 +206,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder Context context, OnClickListener blockReportListener, View.OnClickListener expandCollapseListener, + View.OnLongClickListener longClickListener, CallLogCache callLogCache, CallLogListItemHelper callLogListItemHelper, VoicemailPlaybackPresenter voicemailPlaybackPresenter, @@ -221,10 +221,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mContext = context; mExpandCollapseListener = expandCollapseListener; + longPressListener = longClickListener; mCallLogCache = callLogCache; mCallLogListItemHelper = callLogListItemHelper; mVoicemailPlaybackPresenter = voicemailPlaybackPresenter; mBlockReportListener = blockReportListener; + mCachedNumberLookupService = PhoneNumberCache.get(mContext).getCachedNumberLookupService(); this.rootView = rootView; this.quickContactView = quickContactView; @@ -234,6 +236,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder this.dayGroupHeader = dayGroupHeader; this.primaryActionButtonView = primaryActionButtonView; this.workIconView = (ImageView) rootView.findViewById(R.id.work_profile_icon); + this.checkBoxView = (ImageView) rootView.findViewById(R.id.quick_contact_checkbox); mPhotoSize = mContext.getResources().getDimensionPixelSize(R.dimen.contact_photo_size); // Set text height to false on the TextViews so they don't have extra padding. @@ -246,7 +249,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } primaryActionButtonView.setOnClickListener(this); primaryActionView.setOnClickListener(mExpandCollapseListener); - primaryActionView.setOnCreateContextMenuListener(this); + primaryActionView.setOnLongClickListener(longPressListener); } public static CallLogListItemViewHolder create( @@ -254,6 +257,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder Context context, OnClickListener blockReportListener, View.OnClickListener expandCollapseListener, + View.OnLongClickListener longClickListener, CallLogCache callLogCache, CallLogListItemHelper callLogListItemHelper, VoicemailPlaybackPresenter voicemailPlaybackPresenter) { @@ -262,6 +266,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder context, blockReportListener, expandCollapseListener, + longClickListener, callLogCache, callLogListItemHelper, voicemailPlaybackPresenter, @@ -285,6 +290,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder context, null, null /* expandCollapseListener */, + null, callLogCache, new CallLogListItemHelper(phoneCallDetailsHelper, resources, callLogCache), null /* voicemailPlaybackPresenter */, @@ -299,108 +305,11 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder viewHolder.actionsView = new View(context); viewHolder.voicemailPlaybackView = new VoicemailPlaybackLayout(context); viewHolder.workIconView = new ImageButton(context); + viewHolder.checkBoxView = new ImageButton(context); return viewHolder; } @Override - public void onCreateContextMenu( - final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - if (TextUtils.isEmpty(number)) { - return; - } - - if (callType == CallLog.Calls.VOICEMAIL_TYPE) { - menu.setHeaderTitle(mContext.getResources().getText(R.string.voicemail)); - } else { - menu.setHeaderTitle( - PhoneNumberUtilsCompat.createTtsSpannable( - BidiFormatter.getInstance().unicodeWrap(number, TextDirectionHeuristics.LTR))); - } - - menu.add( - ContextMenu.NONE, - R.id.context_menu_copy_to_clipboard, - ContextMenu.NONE, - R.string.action_copy_number_text) - .setOnMenuItemClickListener(this); - - // The edit number before call does not show up if any of the conditions apply: - // 1) Number cannot be called - // 2) Number is the voicemail number - // 3) Number is a SIP address - - if (PhoneNumberHelper.canPlaceCallsTo(number, numberPresentation) - && !mCallLogCache.isVoicemailNumber(accountHandle, number) - && !PhoneNumberHelper.isSipNumber(number)) { - menu.add( - ContextMenu.NONE, - R.id.context_menu_edit_before_call, - ContextMenu.NONE, - R.string.action_edit_number_before_call) - .setOnMenuItemClickListener(this); - } - - if (callType == CallLog.Calls.VOICEMAIL_TYPE - && phoneCallDetailsViews.voicemailTranscriptionView.length() > 0) { - menu.add( - ContextMenu.NONE, - R.id.context_menu_copy_transcript_to_clipboard, - ContextMenu.NONE, - R.string.copy_transcript_text) - .setOnMenuItemClickListener(this); - } - - String e164Number = PhoneNumberUtils.formatNumberToE164(number, countryIso); - boolean isVoicemailNumber = mCallLogCache.isVoicemailNumber(accountHandle, number); - if (!isVoicemailNumber - && FilteredNumbersUtil.canBlockNumber(mContext, e164Number, number) - && FilteredNumberCompat.canAttemptBlockOperations(mContext)) { - boolean isBlocked = blockId != null; - if (isBlocked) { - menu.add( - ContextMenu.NONE, - R.id.context_menu_unblock, - ContextMenu.NONE, - R.string.call_log_action_unblock_number) - .setOnMenuItemClickListener(this); - } else { - if (isSpamFeatureEnabled) { - if (isSpam) { - menu.add( - ContextMenu.NONE, - R.id.context_menu_report_not_spam, - ContextMenu.NONE, - R.string.call_log_action_remove_spam) - .setOnMenuItemClickListener(this); - menu.add( - ContextMenu.NONE, - R.id.context_menu_block, - ContextMenu.NONE, - R.string.call_log_action_block_number) - .setOnMenuItemClickListener(this); - } else { - menu.add( - ContextMenu.NONE, - R.id.context_menu_block_report_spam, - ContextMenu.NONE, - R.string.call_log_action_block_report_number) - .setOnMenuItemClickListener(this); - } - } else { - menu.add( - ContextMenu.NONE, - R.id.context_menu_block, - ContextMenu.NONE, - R.string.call_log_action_block_number) - .setOnMenuItemClickListener(this); - } - } - } - - Logger.get(mContext).logScreenView(ScreenEvent.Type.CALL_LOG_CONTEXT_MENU, (Activity) mContext); - } - - @Override public boolean onMenuItemClick(MenuItem item) { int resId = item.getItemId(); if (resId == R.id.context_menu_copy_to_clipboard) { @@ -518,7 +427,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder if (!TextUtils.isEmpty(voicemailUri)) { // Treat as voicemail list item; show play button if not expanded. if (!isExpanded) { - primaryActionButtonView.setImageResource(R.drawable.ic_play_arrow_24dp); + primaryActionButtonView.setImageResource(R.drawable.quantum_ic_play_arrow_white_24); primaryActionButtonView.setContentDescription( TextUtils.expandTemplate( mContext.getString(R.string.description_voicemail_action), validNameOrNumber)); @@ -541,7 +450,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder primaryActionButtonView.setContentDescription( TextUtils.expandTemplate( mContext.getString(R.string.description_call_action), validNameOrNumber)); - primaryActionButtonView.setImageResource(R.drawable.ic_call_24dp); + primaryActionButtonView.setImageResource(R.drawable.quantum_ic_call_white_24); primaryActionButtonView.setVisibility(View.VISIBLE); } else { primaryActionButtonView.setTag(null); @@ -607,9 +516,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder callButtonView.setVisibility(View.GONE); } - if (shouldShowVideoCallActionButton(canPlaceCallToNumber)) { + if (hasPlacedCarrierVideoCall() || canSupportCarrierVideoCall()) { videoCallButtonView.setTag(IntentProvider.getReturnVideoCallIntentProvider(number)); videoCallButtonView.setVisibility(View.VISIBLE); + } else if (lightbringerReady) { + videoCallButtonView.setTag(IntentProvider.getLightbringerIntentProvider(number)); + videoCallButtonView.setVisibility(View.VISIBLE); } else { videoCallButtonView.setVisibility(View.GONE); } @@ -659,7 +571,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder addToExistingContactButtonView.setVisibility(View.GONE); } - if (canPlaceCallToNumber && !isBlockedOrSpam) { + boolean isVoicemailNumber = mCallLogCache.isVoicemailNumber(accountHandle, number); + if (canPlaceCallToNumber && !isBlockedOrSpam && !isVoicemailNumber) { sendMessageView.setTag(IntentProvider.getSendSmsIntentProvider(number)); sendMessageView.setVisibility(View.VISIBLE); } else { @@ -669,7 +582,6 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mCallLogListItemHelper.setActionContentDescriptions(this); boolean supportsCallSubject = mCallLogCache.doesAccountSupportCallSubject(accountHandle); - boolean isVoicemailNumber = mCallLogCache.isVoicemailNumber(accountHandle, number); callWithNoteButtonView.setVisibility( supportsCallSubject && !isVoicemailNumber && info != null ? View.VISIBLE : View.GONE); @@ -699,15 +611,22 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder return false; } - private boolean shouldShowVideoCallActionButton(boolean canPlaceCallToNumber) { - return canPlaceCallToNumber && (hasPlacedVideoCall() || canSupportVideoCall()); - } - - private boolean hasPlacedVideoCall() { - return phoneCallDetailsViews.callTypeIcons.isVideoShown(); + private boolean hasPlacedCarrierVideoCall() { + if (!phoneCallDetailsViews.callTypeIcons.isVideoShown()) { + return false; + } + if (accountHandle == null) { + return false; + } + if (accountHandle + .getComponentName() + .equals(getLightbringer().getPhoneAccountComponentName(mContext))) { + return false; + } + return true; } - private boolean canSupportVideoCall() { + private boolean canSupportCarrierVideoCall() { return mCallLogCache.canRelyOnVideoPresence() && info != null && (info.carrierPresence & Phone.CARRIER_PRESENCE_VT_CAPABLE) != 0; @@ -800,7 +719,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder int contactType = ContactPhotoManager.TYPE_DEFAULT; if (mCallLogCache.isVoicemailNumber(accountHandle, number)) { contactType = ContactPhotoManager.TYPE_VOICEMAIL; - } else if (isBusiness) { + } else if (mCachedNumberLookupService != null + && mCachedNumberLookupService.isBusiness(info.sourceType)) { contactType = ContactPhotoManager.TYPE_BUSINESS; } else if (numberPresentation == TelecomManager.PRESENTATION_RESTRICTED) { contactType = ContactPhotoManager.TYPE_GENERIC_AVATAR; @@ -810,6 +730,10 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder @Override public void onClick(View view) { + if (view.getId() == R.id.primary_action_button) { + CallLogAsyncTaskUtil.markCallAsRead(mContext, callIds); + } + if (view.getId() == R.id.primary_action_button && !TextUtils.isEmpty(voicemailUri)) { Logger.get(mContext).logImpression(DialerImpression.Type.VOICEMAIL_PLAY_AUDIO_DIRECTLY); mVoicemailPrimaryActionButtonClicked = true; @@ -947,6 +871,11 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder return callDetailsEntries; } + @NonNull + private Lightbringer getLightbringer() { + return LightbringerComponent.get(mContext).getLightbringer(); + } + public interface OnClickListener { void onBlockReportSpam( diff --git a/java/com/android/dialer/app/calllog/CallLogNotificationsActivity.java b/java/com/android/dialer/app/calllog/CallLogNotificationsActivity.java new file mode 100644 index 000000000..c08d2c02b --- /dev/null +++ b/java/com/android/dialer/app/calllog/CallLogNotificationsActivity.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017 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.app.calllog; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import com.android.dialer.common.LogUtil; +import com.android.dialer.util.PermissionsUtil; + +/** + * Provides operations for managing call-related notifications. This is used to forward intent + * that's requiring to unlock screen and it will never be visible to user. + * + * <p>It handles the following actions: + * + * <ul> + * <li>Sending an SMS from a missed call + * </ul> + */ +public class CallLogNotificationsActivity extends AppCompatActivity { + + public static final String ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION = + "com.android.dialer.calllog.SEND_SMS_FROM_MISSED_CALL_NOTIFICATION"; + + /** + * Extra to be included with {@link #ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION} to identify + * the number to text back. + * + * <p>It must be a {@link String}. + */ + public static final String EXTRA_MISSED_CALL_NUMBER = "MISSED_CALL_NUMBER"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Intent intent = getIntent(); + + if (!PermissionsUtil.hasPermission(this, android.Manifest.permission.READ_CALL_LOG)) { + return; + } + + String action = intent.getAction(); + switch (action) { + case ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION: + MissedCallNotifier.getInstance(this) + .sendSmsFromMissedCall( + intent.getStringExtra(EXTRA_MISSED_CALL_NUMBER), intent.getData()); + break; + default: + LogUtil.d("CallLogNotificationsActivity.onCreate", "could not handle: " + intent); + break; + } + finish(); + } +} diff --git a/java/com/android/dialer/app/calllog/CallLogNotificationsService.java b/java/com/android/dialer/app/calllog/CallLogNotificationsService.java index 2f26027f9..f67837f8a 100644 --- a/java/com/android/dialer/app/calllog/CallLogNotificationsService.java +++ b/java/com/android/dialer/app/calllog/CallLogNotificationsService.java @@ -71,11 +71,8 @@ public class CallLogNotificationsService extends IntentService { public static final String ACTION_CALL_BACK_FROM_MISSED_CALL_NOTIFICATION = "com.android.dialer.calllog.CALL_BACK_FROM_MISSED_CALL_NOTIFICATION"; - public static final String ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION = - "com.android.dialer.calllog.SEND_SMS_FROM_MISSED_CALL_NOTIFICATION"; /** - * Extra to be included with {@link #ACTION_UPDATE_MISSED_CALL_NOTIFICATIONS}, {@link - * #ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION} and {@link + * Extra to be included with {@link #ACTION_UPDATE_MISSED_CALL_NOTIFICATIONS} and {@link * #ACTION_CALL_BACK_FROM_MISSED_CALL_NOTIFICATION} to identify the number to display, call or * text back. * @@ -226,11 +223,6 @@ public class CallLogNotificationsService extends IntentService { .callBackFromMissedCall( intent.getStringExtra(EXTRA_MISSED_CALL_NUMBER), intent.getData()); break; - case ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION: - MissedCallNotifier.getInstance(this) - .sendSmsFromMissedCall( - intent.getStringExtra(EXTRA_MISSED_CALL_NUMBER), intent.getData()); - break; default: LogUtil.d("CallLogNotificationsService.onHandleIntent", "could not handle: " + intent); break; diff --git a/java/com/android/dialer/app/calllog/ClearCallLogDialog.java b/java/com/android/dialer/app/calllog/ClearCallLogDialog.java index 0c9bd4b35..a01b89527 100644 --- a/java/com/android/dialer/app/calllog/ClearCallLogDialog.java +++ b/java/com/android/dialer/app/calllog/ClearCallLogDialog.java @@ -54,6 +54,7 @@ public class ClearCallLogDialog extends DialogFragment { ProgressDialog.show( getActivity(), getString(R.string.clearCallLogProgress_title), "", true, false); progressDialog.setOwnerActivity(getActivity()); + CallLogNotificationsService.markNewMissedCallsAsOld(getContext(), null); final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { @Override diff --git a/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java b/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java index b0a6ee135..dfe5776d8 100644 --- a/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java +++ b/java/com/android/dialer/app/calllog/DefaultVoicemailNotifier.java @@ -40,7 +40,7 @@ import com.android.dialer.app.DialtactsActivity; import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; import com.android.dialer.app.contactinfo.ContactPhotoLoader; -import com.android.dialer.app.list.ListsFragment; +import com.android.dialer.app.list.DialtactsPagerAdapter; import com.android.dialer.blocking.FilteredNumbersUtil; import com.android.dialer.common.LogUtil; import com.android.dialer.logging.Logger; @@ -274,7 +274,8 @@ public class DefaultVoicemailNotifier { } private PendingIntent newVoicemailIntent(@Nullable NewCall voicemail) { - Intent intent = DialtactsActivity.getShowTabIntent(context, ListsFragment.TAB_INDEX_VOICEMAIL); + Intent intent = + DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_VOICEMAIL); // TODO (b/35486204): scroll to this voicemail if (voicemail != null) { intent.setData(voicemail.voicemailUri); diff --git a/java/com/android/dialer/app/calllog/IntentProvider.java b/java/com/android/dialer/app/calllog/IntentProvider.java index c53e3ec5e..8b77c3f51 100644 --- a/java/com/android/dialer/app/calllog/IntentProvider.java +++ b/java/com/android/dialer/app/calllog/IntentProvider.java @@ -29,6 +29,7 @@ import com.android.dialer.calldetails.CallDetailsActivity; import com.android.dialer.calldetails.nano.CallDetailsEntries; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.callintent.nano.CallInitiationType; +import com.android.dialer.lightbringer.LightbringerComponent; import com.android.dialer.util.CallUtil; import com.android.dialer.util.IntentUtil; import java.util.ArrayList; @@ -75,6 +76,15 @@ public abstract class IntentProvider { }; } + public static IntentProvider getLightbringerIntentProvider(String number) { + return new IntentProvider() { + @Override + public Intent getIntent(Context context) { + return LightbringerComponent.get(context).getLightbringer().getIntent(context, number); + } + }; + } + public static IntentProvider getReturnVoicemailCallIntentProvider() { return new IntentProvider() { @Override diff --git a/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/java/com/android/dialer/app/calllog/MissedCallNotifier.java index 5b5661615..aa04d81eb 100644 --- a/java/com/android/dialer/app/calllog/MissedCallNotifier.java +++ b/java/com/android/dialer/app/calllog/MissedCallNotifier.java @@ -40,7 +40,7 @@ import com.android.dialer.app.DialtactsActivity; import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; import com.android.dialer.app.contactinfo.ContactPhotoLoader; -import com.android.dialer.app.list.ListsFragment; +import com.android.dialer.app.list.DialtactsPagerAdapter; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.callintent.nano.CallInitiationType; import com.android.dialer.common.LogUtil; @@ -48,7 +48,6 @@ import com.android.dialer.notification.NotificationChannelManager; import com.android.dialer.notification.NotificationChannelManager.Channel; import com.android.dialer.phonenumbercache.ContactInfo; import com.android.dialer.phonenumberutil.PhoneNumberHelper; -import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.IntentUtil; import java.util.HashSet; @@ -187,11 +186,7 @@ public class MissedCallNotifier { .setOnlyAlertOnce(useCallList) .setPublicVersion(publicSummaryBuilder.build()); - NotificationChannelManager.applyChannel( - groupSummary, - context, - Channel.MISSED_CALL, - PhoneAccountHandles.getAccount(context, useCallList ? newCalls.get(0) : null)); + NotificationChannelManager.applyChannel(groupSummary, context, Channel.MISSED_CALL, null); Notification notification = groupSummary.build(); configureLedOnNotification(notification); @@ -291,7 +286,7 @@ public class MissedCallNotifier { if (!PhoneNumberHelper.isUriNumber(call.number)) { builder.addAction( new Notification.Action.Builder( - Icon.createWithResource(context, R.drawable.ic_message_24dp), + Icon.createWithResource(context, R.drawable.quantum_ic_message_white_24), context.getString(R.string.notification_missedCall_message), createSendSmsFromNotificationPendingIntent(call.number, call.callsUri)) .build()); @@ -322,8 +317,7 @@ public class MissedCallNotifier { .setDeleteIntent(createClearMissedCallsPendingIntent(call.callsUri)) .setContentIntent(createCallLogPendingIntent(call.callsUri)); - NotificationChannelManager.applyChannel( - builder, context, Channel.MISSED_CALL, PhoneAccountHandles.getAccount(context, call)); + NotificationChannelManager.applyChannel(builder, context, Channel.MISSED_CALL, null); return builder; } @@ -332,7 +326,6 @@ public class MissedCallNotifier { public void callBackFromMissedCall(String number, Uri callUri) { closeSystemDialogs(context); CallLogNotificationsQueryHelper.removeMissedCallNotifications(context, callUri); - TelecomUtil.cancelMissedCallsNotification(context); DialerUtils.startActivityWithErrorToast( context, new CallIntentBuilder(number, CallInitiationType.Type.MISSED_CALL_NOTIFICATION) @@ -341,11 +334,9 @@ public class MissedCallNotifier { } /** Trigger an intent to send an sms from a missed call number. */ - @WorkerThread public void sendSmsFromMissedCall(String number, Uri callUri) { closeSystemDialogs(context); CallLogNotificationsQueryHelper.removeMissedCallNotifications(context, callUri); - TelecomUtil.cancelMissedCallsNotification(context); DialerUtils.startActivityWithErrorToast( context, IntentUtil.getSendSmsIntent(number).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } @@ -367,7 +358,7 @@ public class MissedCallNotifier { */ private PendingIntent createCallLogPendingIntent(@Nullable Uri callUri) { Intent contentIntent = - DialtactsActivity.getShowTabIntent(context, ListsFragment.TAB_INDEX_HISTORY); + DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_HISTORY); // TODO (b/35486204): scroll to call contentIntent.setData(callUri); return PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT); @@ -393,13 +384,13 @@ public class MissedCallNotifier { private PendingIntent createSendSmsFromNotificationPendingIntent( String number, @NonNull Uri callUri) { - Intent intent = new Intent(context, CallLogNotificationsService.class); - intent.setAction(CallLogNotificationsService.ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION); - intent.putExtra(CallLogNotificationsService.EXTRA_MISSED_CALL_NUMBER, number); + Intent intent = new Intent(context, CallLogNotificationsActivity.class); + intent.setAction(CallLogNotificationsActivity.ACTION_SEND_SMS_FROM_MISSED_CALL_NOTIFICATION); + intent.putExtra(CallLogNotificationsActivity.EXTRA_MISSED_CALL_NUMBER, number); intent.setData(callUri); // Use FLAG_UPDATE_CURRENT to make sure any previous pending intent is updated with the new // extra. - return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } /** Configures a notification to emit the blinky notification light. */ diff --git a/java/com/android/dialer/app/calllog/PhoneAccountHandles.java b/java/com/android/dialer/app/calllog/PhoneAccountHandles.java index b0fa1ed45..acffffb1d 100644 --- a/java/com/android/dialer/app/calllog/PhoneAccountHandles.java +++ b/java/com/android/dialer/app/calllog/PhoneAccountHandles.java @@ -24,6 +24,7 @@ import android.telecom.PhoneAccountHandle; import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; import com.android.dialer.common.LogUtil; import com.android.dialer.telecom.TelecomUtil; +import java.util.List; /** Methods to help extract {@link PhoneAccount} information from database and Telecomm sources. */ class PhoneAccountHandles { @@ -37,6 +38,11 @@ class PhoneAccountHandles { "accountComponentName == null || callToNotify.accountId == null"); handle = TelecomUtil.getDefaultOutgoingPhoneAccount(context, PhoneAccount.SCHEME_TEL); if (handle == null) { + List<PhoneAccountHandle> callCapablePhoneAccounts = + TelecomUtil.getCallCapablePhoneAccounts(context); + if (!callCapablePhoneAccounts.isEmpty()) { + return callCapablePhoneAccounts.get(0); + } return null; } } else { diff --git a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java index 15f860009..bc78eda02 100644 --- a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java +++ b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java @@ -31,6 +31,7 @@ import com.android.dialer.app.R; import com.android.dialer.app.calllog.calllogcache.CallLogCache; import com.android.dialer.calllogutils.PhoneCallDetails; import com.android.dialer.oem.MotorolaUtils; +import com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo; import com.android.dialer.phonenumberutil.PhoneNumberHelper; import com.android.dialer.util.DialerUtils; import java.util.ArrayList; @@ -205,7 +206,7 @@ public class PhoneCallDetailsHelper { && !PhoneNumberHelper.isUriNumber(details.number.toString()) && !mCallLogCache.isVoicemailNumber(details.accountHandle, details.number)) { - if (TextUtils.isEmpty(details.namePrimary) && !TextUtils.isEmpty(details.geocode)) { + if (shouldShowLocation(details)) { numberFormattedLabel = details.geocode; } else if (!(details.numberType == Phone.TYPE_CUSTOM && TextUtils.isEmpty(details.numberLabel))) { @@ -223,6 +224,22 @@ public class PhoneCallDetailsHelper { return numberFormattedLabel; } + /** Returns true if primary name is empty or the data is from Cequint Caller ID. */ + private static boolean shouldShowLocation(PhoneCallDetails details) { + if (TextUtils.isEmpty(details.geocode)) { + return false; + } + // For caller ID provided by Cequint we want to show the geo location. + if (details.sourceType == CachedContactInfo.SOURCE_TYPE_CEQUINT_CALLER_ID) { + return true; + } + // Don't bother showing geo location for contacts. + if (!TextUtils.isEmpty(details.namePrimary)) { + return false; + } + return true; + } + public void setPhoneTypeLabelForTest(CharSequence phoneTypeLabel) { this.mPhoneTypeLabelForTest = phoneTypeLabel; } diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java b/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java index edbe5c6ed..5e820a750 100644 --- a/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java +++ b/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java @@ -16,14 +16,12 @@ package com.android.dialer.app.calllog; -import android.app.Activity; import android.content.Intent; import android.database.ContentObserver; import android.media.AudioManager; import android.os.Bundle; import android.provider.CallLog; import android.provider.VoicemailContract; -import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -119,22 +117,22 @@ public class VisualVoicemailCallLogFragment extends CallLogFragment { } @Override - public void onPageResume(@Nullable Activity activity) { - LogUtil.d("VisualVoicemailCallLogFragment.onPageResume", null); - super.onPageResume(activity); - if (activity != null) { - activity.sendBroadcast(new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL)); - Logger.get(activity).logImpression(DialerImpression.Type.VVM_TAB_VIEWED); - activity.setVolumeControlStream(VoicemailAudioManager.PLAYBACK_STREAM); + public void onVisible() { + LogUtil.enterBlock("VisualVoicemailCallLogFragment.onPageSelected"); + super.onVisible(); + if (getActivity() != null) { + getActivity().sendBroadcast(new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL)); + Logger.get(getActivity()).logImpression(DialerImpression.Type.VVM_TAB_VIEWED); + getActivity().setVolumeControlStream(VoicemailAudioManager.PLAYBACK_STREAM); } } @Override - public void onPagePause(@Nullable Activity activity) { - LogUtil.d("VisualVoicemailCallLogFragment.onPagePause", null); - super.onPagePause(activity); - if (activity != null) { - activity.setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); + public void onNotVisible() { + LogUtil.enterBlock("VisualVoicemailCallLogFragment.onPageUnselected"); + super.onNotVisible(); + if (getActivity() != null) { + getActivity().setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); } } } |