summaryrefslogtreecommitdiffstats
path: root/java/com/android/dialer/app/calllog
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/app/calllog')
-rw-r--r--java/com/android/dialer/app/calllog/CallLogActivity.java18
-rw-r--r--java/com/android/dialer/app/calllog/CallLogAdapter.java101
-rw-r--r--java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java3
-rw-r--r--java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java60
-rw-r--r--java/com/android/dialer/app/calllog/CallLogNotificationsService.java69
-rw-r--r--java/com/android/dialer/app/calllog/ClearCallLogDialog.java132
-rw-r--r--java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java14
-rw-r--r--java/com/android/dialer/app/calllog/MissedCallNotifier.java77
-rw-r--r--java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java34
-rw-r--r--java/com/android/dialer/app/calllog/PhoneCallDetailsViews.java10
-rw-r--r--java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java49
-rw-r--r--java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java60
-rw-r--r--java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java96
13 files changed, 370 insertions, 353 deletions
diff --git a/java/com/android/dialer/app/calllog/CallLogActivity.java b/java/com/android/dialer/app/calllog/CallLogActivity.java
index 35e05bc39..1bb894c59 100644
--- a/java/com/android/dialer/app/calllog/CallLogActivity.java
+++ b/java/com/android/dialer/app/calllog/CallLogActivity.java
@@ -32,10 +32,9 @@ import android.view.ViewGroup;
import com.android.contacts.common.list.ViewPagerTabs;
import com.android.dialer.app.DialtactsActivity;
import com.android.dialer.app.R;
-import com.android.dialer.app.calllog.ClearCallLogDialog.Listener;
import com.android.dialer.calldetails.CallDetailsActivity;
+import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.database.CallLogQueryHandler;
-import com.android.dialer.enrichedcall.EnrichedCallComponent;
import com.android.dialer.logging.Logger;
import com.android.dialer.logging.ScreenEvent;
import com.android.dialer.logging.UiAction;
@@ -46,7 +45,7 @@ import com.android.dialer.util.ViewUtil;
/** Activity for viewing call history. */
public class CallLogActivity extends TransactionSafeActivity
- implements ViewPager.OnPageChangeListener, Listener {
+ implements ViewPager.OnPageChangeListener {
private static final int TAB_INDEX_ALL = 0;
private static final int TAB_INDEX_MISSED = 1;
@@ -148,7 +147,7 @@ public class CallLogActivity extends TransactionSafeActivity
startActivity(intent);
return true;
} else if (item.getItemId() == R.id.delete_all) {
- ClearCallLogDialog.show(getFragmentManager(), this);
+ ClearCallLogDialog.show(getFragmentManager());
return true;
}
return super.onOptionsItemSelected(item);
@@ -184,15 +183,6 @@ public class CallLogActivity extends TransactionSafeActivity
}
@Override
- public void callHistoryDeleted() {
- if (EnrichedCallComponent.get(this).getEnrichedCallManager().hasStoredData()) {
- Snackbar.make(
- findViewById(R.id.calllog_frame), getString(R.string.multiple_ec_data_deleted), 5_000)
- .show();
- }
- }
-
- @Override
public void onBackPressed() {
PerformanceReport.recordClick(UiAction.Type.PRESS_ANDROID_BACK_BUTTON);
super.onBackPressed();
@@ -245,7 +235,7 @@ public class CallLogActivity extends TransactionSafeActivity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == DialtactsActivity.ACTIVITY_REQUEST_CODE_CALL_DETAILS) {
+ if (requestCode == ActivityRequestCodes.DIALTACTS_CALL_DETAILS) {
if (resultCode == RESULT_OK
&& data != null
&& data.getBooleanExtra(CallDetailsActivity.EXTRA_HAS_ENRICHED_CALL_DATA, false)) {
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java
index e0cd1706d..61129a7ce 100644
--- a/java/com/android/dialer/app/calllog/CallLogAdapter.java
+++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java
@@ -74,7 +74,6 @@ import com.android.dialer.configprovider.ConfigProviderBindings;
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.HistoryResult;
import com.android.dialer.lightbringer.Lightbringer;
import com.android.dialer.lightbringer.LightbringerComponent;
import com.android.dialer.lightbringer.LightbringerListener;
@@ -90,8 +89,6 @@ import com.android.dialer.phonenumberutil.PhoneNumberHelper;
import com.android.dialer.spam.Spam;
import com.android.dialer.util.PermissionsUtil;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -344,14 +341,29 @@ public class CallLogAdapter extends GroupingListAdapter
// If enriched call capabilities were unknown on the initial load,
// viewHolder.isCallComposerCapable may be unset. Check here if we have the capabilities
// as a last attempt at getting them before showing the expanded view to the user
- EnrichedCallCapabilities capabilities =
- getEnrichedCallManager().getCapabilities(viewHolder.number);
- viewHolder.isCallComposerCapable =
- capabilities != null && capabilities.supportsCallComposer();
- generateAndMapNewCallDetailsEntriesHistoryResults(
- viewHolder.number,
- viewHolder.getDetailedPhoneDetails(),
- getAllHistoricalData(viewHolder.number, viewHolder.getDetailedPhoneDetails()));
+ EnrichedCallCapabilities capabilities = null;
+
+ if (viewHolder.number != null) {
+ capabilities = getEnrichedCallManager().getCapabilities(viewHolder.number);
+ }
+
+ if (capabilities == null) {
+ capabilities = EnrichedCallCapabilities.NO_CAPABILITIES;
+ }
+
+ viewHolder.isCallComposerCapable = capabilities.isCallComposerCapable();
+
+ if (capabilities.isTemporarilyUnavailable()) {
+ LogUtil.i(
+ "mExpandCollapseListener.onClick",
+ "%s is temporarily unavailable, requesting capabilities",
+ LogUtil.sanitizePhoneNumber(viewHolder.number));
+ // Refresh the capabilities when temporarily unavailable, see go/ec-temp-unavailable.
+ // Similarly to when we request capabilities the first time, the 'Share and call' button
+ // won't pop in with the new capabilities. Instead the row needs to be collapsed and
+ // expanded again.
+ getEnrichedCallManager().requestCapabilities(viewHolder.number);
+ }
if (viewHolder.rowId == mCurrentlyExpandedRowId) {
// Hide actions, if the clicked item is the expanded item.
@@ -454,7 +466,7 @@ public class CallLogAdapter extends GroupingListAdapter
* Holds a list of URIs that are pending deletion or undo. If the activity ends before the undo
* timeout, all of the pending URIs will be deleted.
*
- * <p>TODO: move this and OnVoicemailDeletedListener to somewhere like {@link
+ * <p>TODO(twyen): move this and OnVoicemailDeletedListener to somewhere like {@link
* VisualVoicemailCallLogFragment}. The CallLogAdapter does not need to know about what to do with
* hidden item or what to hide.
*/
@@ -817,12 +829,7 @@ public class CallLogAdapter extends GroupingListAdapter
// the value will be false while capabilities are requested. mExpandCollapseListener will
// attempt to set the field properly in that case
views.isCallComposerCapable = isCallComposerCapable(views.number);
- CallDetailsEntries updatedCallDetailsEntries =
- generateAndMapNewCallDetailsEntriesHistoryResults(
- views.number,
- callDetailsEntries,
- getAllHistoricalData(views.number, callDetailsEntries));
- views.setDetailedPhoneDetails(updatedCallDetailsEntries);
+ views.setDetailedPhoneDetails(callDetailsEntries);
views.lightbringerReady = getLightbringer().isReachable(mActivity, views.number);
final AsyncTask<Void, Void, Boolean> loadDataTask =
new AsyncTask<Void, Void, Boolean>() {
@@ -879,46 +886,7 @@ public class CallLogAdapter extends GroupingListAdapter
getEnrichedCallManager().requestCapabilities(number);
return false;
}
- return capabilities.supportsCallComposer();
- }
-
- @NonNull
- private Map<CallDetailsEntry, List<HistoryResult>> getAllHistoricalData(
- @Nullable String number, @NonNull CallDetailsEntries entries) {
- if (number == null) {
- return Collections.emptyMap();
- }
-
- Map<CallDetailsEntry, List<HistoryResult>> historicalData =
- getEnrichedCallManager().getAllHistoricalData(number, entries);
- if (historicalData == null) {
- getEnrichedCallManager().requestAllHistoricalData(number, entries);
- return Collections.emptyMap();
- }
- return historicalData;
- }
-
- private static CallDetailsEntries generateAndMapNewCallDetailsEntriesHistoryResults(
- @Nullable String number,
- @NonNull CallDetailsEntries callDetailsEntries,
- @NonNull Map<CallDetailsEntry, List<HistoryResult>> mappedResults) {
- if (number == null) {
- return callDetailsEntries;
- }
- CallDetailsEntries.Builder mutableCallDetailsEntries = CallDetailsEntries.newBuilder();
- for (CallDetailsEntry entry : callDetailsEntries.getEntriesList()) {
- CallDetailsEntry.Builder newEntry = CallDetailsEntry.newBuilder().mergeFrom(entry);
- List<HistoryResult> results = mappedResults.get(entry);
- if (results != null) {
- newEntry.addAllHistoryResults(mappedResults.get(entry));
- LogUtil.v(
- "CallLogAdapter.generateAndMapNewCallDetailsEntriesHistoryResults",
- "mapped %d results",
- newEntry.getHistoryResultsList().size());
- }
- mutableCallDetailsEntries.addEntries(newEntry.build());
- }
- return mutableCallDetailsEntries.build();
+ return capabilities.isCallComposerCapable();
}
/**
@@ -936,6 +904,10 @@ public class CallLogAdapter extends GroupingListAdapter
(VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.VIA_NUMBER) : "";
final int numberPresentation = cursor.getInt(CallLogQuery.NUMBER_PRESENTATION);
final ContactInfo cachedContactInfo = ContactInfoHelper.getContactInfo(cursor);
+ final int transcriptionState =
+ (VERSION.SDK_INT >= VERSION_CODES.O)
+ ? cursor.getInt(CallLogQuery.TRANSCRIPTION_STATE)
+ : PhoneCallDetailsHelper.TRANSCRIPTION_NOT_STARTED;
final PhoneCallDetails details =
new PhoneCallDetails(number, numberPresentation, postDialDigits);
details.viaNumber = viaNumber;
@@ -945,6 +917,7 @@ public class CallLogAdapter extends GroupingListAdapter
details.features = getCallFeatures(cursor, count);
details.geocode = cursor.getString(CallLogQuery.GEOCODED_LOCATION);
details.transcription = cursor.getString(CallLogQuery.TRANSCRIPTION);
+ details.transcriptionState = transcriptionState;
details.callTypes = getCallTypes(cursor, count);
details.accountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME);
@@ -977,7 +950,7 @@ public class CallLogAdapter extends GroupingListAdapter
}
@MainThread
- private static CallDetailsEntries createCallDetailsEntries(Cursor cursor, int count) {
+ private CallDetailsEntries createCallDetailsEntries(Cursor cursor, int count) {
Assert.isMainThread();
int position = cursor.getPosition();
CallDetailsEntries.Builder entries = CallDetailsEntries.newBuilder();
@@ -990,6 +963,16 @@ public class CallLogAdapter extends GroupingListAdapter
.setDate(cursor.getLong(CallLogQuery.DATE))
.setDuration(cursor.getLong(CallLogQuery.DURATION))
.setFeatures(cursor.getInt(CallLogQuery.FEATURES));
+
+ String phoneAccountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME);
+ if (getLightbringer().getPhoneAccountComponentName() != null
+ && getLightbringer()
+ .getPhoneAccountComponentName()
+ .flattenToString()
+ .equals(phoneAccountComponentName)) {
+ entry.setIsLightbringerCall(true);
+ }
+
entries.addEntries(entry.build());
cursor.moveToNext();
}
diff --git a/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java b/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java
index b1ad0d9a2..78ec7a695 100644
--- a/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java
+++ b/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java
@@ -66,9 +66,8 @@ public class CallLogAsyncTaskUtil {
.update(voicemailUri, values, Voicemails.IS_READ + " = 0", null)
> 0) {
uploadVoicemailLocalChangesToServer(context);
+ CallLogNotificationsService.markAllNewVoicemailsAsOld(context);
}
-
- CallLogNotificationsService.markAllNewVoicemailsAsOld(context);
return null;
}
});
diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
index 99c49b7af..60ed7dd09 100644
--- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
+++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Bundle;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -50,12 +51,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.contacts.common.ClipboardUtils;
-import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.compat.PhoneNumberUtilsCompat;
import com.android.contacts.common.dialog.CallSubjectDialog;
-import com.android.contacts.common.lettertiles.LetterTileDrawable;
-import com.android.contacts.common.lettertiles.LetterTileDrawable.ContactType;
-import com.android.contacts.common.util.UriUtils;
import com.android.dialer.app.DialtactsActivity;
import com.android.dialer.app.R;
import com.android.dialer.app.calllog.CallLogAdapter.OnActionModeStateChangedListener;
@@ -72,9 +69,14 @@ import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.CompatUtils;
+import com.android.dialer.compat.telephony.TelephonyManagerCompat;
import com.android.dialer.configprovider.ConfigProviderBindings;
+import com.android.dialer.constants.ActivityRequestCodes;
+import com.android.dialer.contactphoto.ContactPhotoManager;
import com.android.dialer.dialercontact.DialerContact;
import com.android.dialer.dialercontact.SimDetails;
+import com.android.dialer.lettertile.LetterTileDrawable;
+import com.android.dialer.lettertile.LetterTileDrawable.ContactType;
import com.android.dialer.lightbringer.Lightbringer;
import com.android.dialer.lightbringer.LightbringerComponent;
import com.android.dialer.logging.ContactSource;
@@ -91,6 +93,7 @@ import com.android.dialer.phonenumberutil.PhoneNumberHelper;
import com.android.dialer.telecom.TelecomUtil;
import com.android.dialer.util.CallUtil;
import com.android.dialer.util.DialerUtils;
+import com.android.dialer.util.UriUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -164,7 +167,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
* The callable phone number for the current call log entry. Cached here as the call back intent
* is set only when the actions ViewStub is inflated.
*/
- public String number;
+ @Nullable public String number;
/** The post-dial numbers that are dialed following the phone number. */
public String postDialDigits;
/** The formatted phone number to display. */
@@ -584,8 +587,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
return;
}
+ TextView callTypeOrLocationView =
+ ((TextView) callButtonView.findViewById(R.id.call_type_or_location_text));
+
if (canPlaceCallToNumber) {
callButtonView.setTag(IntentProvider.getReturnCallIntentProvider(number));
+ callTypeOrLocationView.setVisibility(View.GONE);
}
if (!TextUtils.isEmpty(voicemailUri) && canPlaceCallToNumber) {
@@ -594,13 +601,10 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
TextUtils.expandTemplate(
mContext.getString(R.string.call_log_action_call),
nameOrNumber == null ? "" : nameOrNumber));
- TextView callTypeOrLocationView =
- ((TextView) callButtonView.findViewById(R.id.call_type_or_location_text));
+
if (callType == Calls.VOICEMAIL_TYPE && !TextUtils.isEmpty(callTypeOrLocation)) {
callTypeOrLocationView.setText(callTypeOrLocation);
callTypeOrLocationView.setVisibility(View.VISIBLE);
- } else {
- callTypeOrLocationView.setVisibility(View.GONE);
}
callButtonView.setVisibility(View.VISIBLE);
}
@@ -774,12 +778,23 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
return;
}
- final TextView view = phoneCallDetailsViews.voicemailTranscriptionView;
- if (!isExpanded || TextUtils.isEmpty(view.getText())) {
- view.setVisibility(View.GONE);
+ View transcriptContainerView = phoneCallDetailsViews.transcriptionView;
+ TextView transcriptView = phoneCallDetailsViews.voicemailTranscriptionView;
+ TextView transcriptBrandingView = phoneCallDetailsViews.voicemailTranscriptionBrandingView;
+ if (TextUtils.isEmpty(transcriptView.getText())) {
+ Assert.checkArgument(TextUtils.isEmpty(transcriptBrandingView.getText()));
+ }
+ if (!isExpanded || TextUtils.isEmpty(transcriptView.getText())) {
+ transcriptContainerView.setVisibility(View.GONE);
return;
}
- view.setVisibility(View.VISIBLE);
+ transcriptContainerView.setVisibility(View.VISIBLE);
+ transcriptView.setVisibility(View.VISIBLE);
+ if (TextUtils.isEmpty(transcriptBrandingView.getText())) {
+ phoneCallDetailsViews.voicemailTranscriptionBrandingView.setVisibility(View.GONE);
+ } else {
+ phoneCallDetailsViews.voicemailTranscriptionBrandingView.setVisibility(View.VISIBLE);
+ }
}
public void updatePhoto() {
@@ -868,7 +883,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
Activity activity = (Activity) mContext;
activity.startActivityForResult(
CallComposerActivity.newIntent(activity, buildContact()),
- DialtactsActivity.ACTIVITY_REQUEST_CODE_CALL_COMPOSE);
+ ActivityRequestCodes.DIALTACTS_CALL_COMPOSER);
} else if (view.getId() == R.id.share_voicemail) {
Logger.get(mContext).logImpression(DialerImpression.Type.VVM_SHARE_PRESSED);
mVoicemailPlaybackPresenter.shareVoicemail();
@@ -886,6 +901,15 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
return;
}
+ if (info != null && info.lookupKey != null) {
+ Bundle extras = new Bundle();
+ if (intent.hasExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS)) {
+ extras = intent.getParcelableExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS);
+ }
+ extras.putBoolean(TelephonyManagerCompat.ALLOW_ASSISTED_DIAL, true);
+ intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
+ }
+
// We check to see if we are starting a Lightbringer intent. The reason is Lightbringer
// intents need to be started using startActivityForResult instead of the usual startActivity
String packageName = intent.getPackage();
@@ -896,7 +920,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
} else if (CallDetailsActivity.isLaunchIntent(intent)) {
PerformanceReport.recordClick(UiAction.Type.OPEN_CALL_DETAIL);
((Activity) mContext)
- .startActivityForResult(intent, DialtactsActivity.ACTIVITY_REQUEST_CODE_CALL_DETAILS);
+ .startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_CALL_DETAILS);
} else {
if (Intent.ACTION_CALL.equals(intent.getAction())
&& intent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, -1)
@@ -912,7 +936,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
private void startLightbringerActivity(Intent intent) {
try {
Activity activity = (Activity) mContext;
- activity.startActivityForResult(intent, DialtactsActivity.ACTIVITY_REQUEST_CODE_LIGHTBRINGER);
+ activity.startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_LIGHTBRINGER);
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, R.string.activity_not_available, Toast.LENGTH_SHORT).show();
}
@@ -931,7 +955,9 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
contact.setNameOrNumber((String) nameOrNumber);
}
contact.setContactType(getContactType());
- contact.setNumber(number);
+ if (number != null) {
+ contact.setNumber(number);
+ }
/* second line of contact view. */
if (!TextUtils.isEmpty(info.name)) {
contact.setDisplayNumber(displayNumber);
diff --git a/java/com/android/dialer/app/calllog/CallLogNotificationsService.java b/java/com/android/dialer/app/calllog/CallLogNotificationsService.java
index be1ebfb6d..0490b9932 100644
--- a/java/com/android/dialer/app/calllog/CallLogNotificationsService.java
+++ b/java/com/android/dialer/app/calllog/CallLogNotificationsService.java
@@ -24,7 +24,13 @@ import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
+import android.support.annotation.WorkerThread;
+import android.telecom.PhoneAccountHandle;
+import com.android.dialer.app.voicemail.LegacyVoicemailNotificationReceiver;
+import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.telecom.TelecomUtil;
import com.android.dialer.util.PermissionsUtil;
@@ -44,7 +50,8 @@ import com.android.dialer.util.PermissionsUtil;
*/
public class CallLogNotificationsService extends IntentService {
- private static final String ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD =
+ @VisibleForTesting
+ static final String ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD =
"com.android.dialer.calllog.ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD";
private static final String ACTION_MARK_SINGLE_NEW_VOICEMAIL_AS_OLD =
@@ -64,6 +71,10 @@ 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";
+ /** Action mark legacy voicemail as dismissed. */
+ public static final String ACTION_LEGACY_VOICEMAIL_DISMISSED =
+ "com.android.dialer.calllog.ACTION_LEGACY_VOICEMAIL_DISMISSED";
+
/**
* Extra to be included with {@link #ACTION_INCOMING_POST_CALL} to represent a post call note.
*
@@ -79,6 +90,8 @@ public class CallLogNotificationsService extends IntentService {
*/
private static final String EXTRA_POST_CALL_NUMBER = "POST_CALL_NUMBER";
+ private static final String EXTRA_PHONE_ACCOUNT_HANDLE = "PHONE_ACCOUNT_HANDLE";
+
public static final int UNKNOWN_MISSED_CALL_COUNT = -1;
public CallLogNotificationsService() {
@@ -108,6 +121,15 @@ public class CallLogNotificationsService extends IntentService {
context.startService(serviceIntent);
}
+ public static void cancelAllMissedCalls(Context context) {
+ LogUtil.enterBlock("CallLogNotificationsService.cancelAllMissedCalls");
+ DialerExecutorComponent.get(context)
+ .dialerExecutorFactory()
+ .createNonUiTaskBuilder(new CancelAllMissedCallsWorker())
+ .build()
+ .executeSerial(context);
+ }
+
public static PendingIntent createMarkAllNewVoicemailsAsOldIntent(@NonNull Context context) {
Intent intent = new Intent(context, CallLogNotificationsService.class);
intent.setAction(CallLogNotificationsService.ACTION_MARK_ALL_NEW_VOICEMAILS_AS_OLD);
@@ -122,13 +144,6 @@ public class CallLogNotificationsService extends IntentService {
return PendingIntent.getService(context, 0, intent, 0);
}
- public static void cancelAllMissedCalls(@NonNull Context context) {
- LogUtil.enterBlock("CallLogNotificationsService.cancelAllMissedCalls");
- Intent serviceIntent = new Intent(context, CallLogNotificationsService.class);
- serviceIntent.setAction(ACTION_CANCEL_ALL_MISSED_CALLS);
- context.startService(serviceIntent);
- }
-
public static PendingIntent createCancelAllMissedCallsPendingIntent(@NonNull Context context) {
Intent intent = new Intent(context, CallLogNotificationsService.class);
intent.setAction(ACTION_CANCEL_ALL_MISSED_CALLS);
@@ -143,6 +158,14 @@ public class CallLogNotificationsService extends IntentService {
return PendingIntent.getService(context, 0, intent, 0);
}
+ public static PendingIntent createLegacyVoicemailDismissedPendingIntent(
+ @NonNull Context context, PhoneAccountHandle phoneAccountHandle) {
+ Intent intent = new Intent(context, CallLogNotificationsService.class);
+ intent.setAction(ACTION_LEGACY_VOICEMAIL_DISMISSED);
+ intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
+ return PendingIntent.getService(context, 0, intent, 0);
+ }
+
@Override
protected void onHandleIntent(Intent intent) {
if (intent == null) {
@@ -168,15 +191,17 @@ public class CallLogNotificationsService extends IntentService {
VoicemailQueryHandler.markSingleNewVoicemailAsRead(this, voicemailUri);
VisualVoicemailNotifier.cancelSingleVoicemailNotification(this, voicemailUri);
break;
+ case ACTION_LEGACY_VOICEMAIL_DISMISSED:
+ LegacyVoicemailNotificationReceiver.setDismissed(
+ this, intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE), true);
+ break;
case ACTION_INCOMING_POST_CALL:
String note = intent.getStringExtra(EXTRA_POST_CALL_NOTE);
String phoneNumber = intent.getStringExtra(EXTRA_POST_CALL_NUMBER);
MissedCallNotifier.getIstance(this).insertPostCallNotification(phoneNumber, note);
break;
case ACTION_CANCEL_ALL_MISSED_CALLS:
- CallLogNotificationsQueryHelper.markAllMissedCallsInCallLogAsRead(this);
- MissedCallNotifier.cancelAllMissedCallNotifications(this);
- TelecomUtil.cancelMissedCallsNotification(this);
+ cancelAllMissedCalls(this);
break;
case ACTION_CANCEL_SINGLE_MISSED_CALL:
Uri callUri = intent.getData();
@@ -196,4 +221,26 @@ public class CallLogNotificationsService extends IntentService {
break;
}
}
+
+ @WorkerThread
+ private static void cancelAllMissedCallsBackground(Context context) {
+ LogUtil.enterBlock("CallLogNotificationsService.cancelAllMissedCallsBackground");
+ Assert.isWorkerThread();
+ CallLogNotificationsQueryHelper.markAllMissedCallsInCallLogAsRead(context);
+ MissedCallNotifier.cancelAllMissedCallNotifications(context);
+ TelecomUtil.cancelMissedCallsNotification(context);
+ }
+
+ /** Worker that cancels all missed call notifications and updates call log entries. */
+ private static class CancelAllMissedCallsWorker implements Worker<Context, Void> {
+
+ @Nullable
+ @Override
+ public Void doInBackground(@Nullable Context context) throws Throwable {
+ if (context != null) {
+ cancelAllMissedCallsBackground(context);
+ }
+ return null;
+ }
+ }
}
diff --git a/java/com/android/dialer/app/calllog/ClearCallLogDialog.java b/java/com/android/dialer/app/calllog/ClearCallLogDialog.java
index 5c3d4d9fa..b16eb1beb 100644
--- a/java/com/android/dialer/app/calllog/ClearCallLogDialog.java
+++ b/java/com/android/dialer/app/calllog/ClearCallLogDialog.java
@@ -22,76 +22,63 @@ import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.app.ProgressDialog;
-import android.content.ContentResolver;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.CallLog.Calls;
-import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.design.widget.Snackbar;
import com.android.dialer.app.R;
import com.android.dialer.common.Assert;
+import com.android.dialer.common.concurrent.DialerExecutor;
+import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.enrichedcall.EnrichedCallComponent;
import com.android.dialer.phonenumbercache.CachedNumberLookupService;
import com.android.dialer.phonenumbercache.PhoneNumberCache;
/** Dialog that clears the call log after confirming with the user */
public class ClearCallLogDialog extends DialogFragment {
- private Listener listener;
+ private DialerExecutor<Void> clearCallLogTask;
+ private ProgressDialog progressDialog;
/** Preferred way to show this dialog */
- public static void show(FragmentManager fragmentManager, @NonNull Listener listener) {
+ public static void show(FragmentManager fragmentManager) {
ClearCallLogDialog dialog = new ClearCallLogDialog();
- dialog.listener = Assert.isNotNull(listener);
dialog.show(fragmentManager, "deleteCallLog");
}
@Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ clearCallLogTask =
+ DialerExecutorComponent.get(getContext())
+ .dialerExecutorFactory()
+ .createUiTaskBuilder(
+ getFragmentManager(),
+ "clearCallLogTask",
+ new ClearCallLogWorker(getActivity().getApplicationContext()))
+ .onSuccess(this::onSuccess)
+ .build();
+ }
+
+ @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final ContentResolver resolver = getActivity().getContentResolver();
- final Context context = getActivity().getApplicationContext();
- final OnClickListener okListener =
- new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final ProgressDialog progressDialog =
- ProgressDialog.show(
- getActivity(), getString(R.string.clearCallLogProgress_title), "", true, false);
- progressDialog.setOwnerActivity(getActivity());
- CallLogNotificationsService.cancelAllMissedCalls(getContext());
- final AsyncTask<Void, Void, Void> task =
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- resolver.delete(Calls.CONTENT_URI, null, null);
- CachedNumberLookupService cachedNumberLookupService =
- PhoneNumberCache.get(context).getCachedNumberLookupService();
- if (cachedNumberLookupService != null) {
- cachedNumberLookupService.clearAllCacheEntries(context);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- final Activity activity = progressDialog.getOwnerActivity();
-
- if (activity == null || activity.isDestroyed() || activity.isFinishing()) {
- return;
- }
-
- listener.callHistoryDeleted();
- if (progressDialog != null && progressDialog.isShowing()) {
- progressDialog.dismiss();
- }
- }
- };
- // TODO: Once we have the API, we should configure this ProgressDialog
- // to only show up after a certain time (e.g. 150ms)
- progressDialog.show();
- task.execute();
- }
+ OnClickListener okListener =
+ (dialog, which) -> {
+ progressDialog =
+ ProgressDialog.show(
+ getActivity(), getString(R.string.clearCallLogProgress_title), "", true, false);
+ progressDialog.setOwnerActivity(getActivity());
+ CallLogNotificationsService.cancelAllMissedCalls(getContext());
+
+ // TODO: Once we have the API, we should configure this ProgressDialog
+ // to only show up after a certain time (e.g. 150ms)
+ progressDialog.show();
+
+ clearCallLogTask.executeSerial(null);
};
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.clearCallLogConfirmation_title)
@@ -103,7 +90,48 @@ public class ClearCallLogDialog extends DialogFragment {
.create();
}
- interface Listener {
- void callHistoryDeleted();
+ private static class ClearCallLogWorker implements Worker<Void, Void> {
+ private final Context appContext;
+
+ private ClearCallLogWorker(Context appContext) {
+ this.appContext = appContext;
+ }
+
+ @Nullable
+ @Override
+ public Void doInBackground(@Nullable Void unused) throws Throwable {
+ appContext.getContentResolver().delete(Calls.CONTENT_URI, null, null);
+ CachedNumberLookupService cachedNumberLookupService =
+ PhoneNumberCache.get(appContext).getCachedNumberLookupService();
+ if (cachedNumberLookupService != null) {
+ cachedNumberLookupService.clearAllCacheEntries(appContext);
+ }
+ return null;
+ }
+ }
+
+ private void onSuccess(Void unused) {
+ Assert.isNotNull(progressDialog);
+ Activity activity = progressDialog.getOwnerActivity();
+
+ if (activity == null || activity.isDestroyed() || activity.isFinishing()) {
+ return;
+ }
+
+ maybeShowEnrichedCallSnackbar(activity);
+
+ if (progressDialog != null && progressDialog.isShowing()) {
+ progressDialog.dismiss();
+ }
+ }
+
+ private void maybeShowEnrichedCallSnackbar(Activity activity) {
+ if (EnrichedCallComponent.get(activity).getEnrichedCallManager().hasStoredData()) {
+ Snackbar.make(
+ activity.findViewById(R.id.calllog_frame),
+ getString(R.string.multiple_ec_data_deleted),
+ 5_000)
+ .show();
+ }
}
}
diff --git a/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java b/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
index 428c71677..584f07fe3 100644
--- a/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
+++ b/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
@@ -18,7 +18,6 @@ package com.android.dialer.app.calllog;
import android.annotation.TargetApi;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Build.VERSION_CODES;
@@ -35,6 +34,7 @@ import com.android.dialer.app.R;
import com.android.dialer.calllogutils.PhoneAccountUtils;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelManager;
/** Shows a notification in the status bar for legacy vociemail. */
@@ -77,9 +77,7 @@ public final class LegacyVoicemailNotifier {
callVoicemailIntent,
voicemailSettingsIntent,
isRefresh);
- context
- .getSystemService(NotificationManager.class)
- .notify(NOTIFICATION_TAG, NOTIFICATION_ID, notification);
+ DialerNotificationManager.notify(context, NOTIFICATION_TAG, NOTIFICATION_ID, notification);
}
@NonNull
@@ -122,7 +120,10 @@ public final class LegacyVoicemailNotifier {
.setSound(pinnedTelephonyManager.getVoicemailRingtoneUri(handle))
.setOngoing(isOngoing)
.setOnlyAlertOnce(isRefresh)
- .setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle));
+ .setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle))
+ .setDeleteIntent(
+ CallLogNotificationsService.createLegacyVoicemailDismissedPendingIntent(
+ context, handle));
if (pinnedTelephonyManager.isVoicemailVibrationEnabled(handle)) {
builder.setDefaults(Notification.DEFAULT_VIBRATE);
@@ -148,8 +149,7 @@ public final class LegacyVoicemailNotifier {
public static void cancelNotification(@NonNull Context context) {
LogUtil.enterBlock("LegacyVoicemailNotifier.cancelNotification");
Assert.checkArgument(BuildCompat.isAtLeastO());
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- notificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
+ DialerNotificationManager.cancel(context, NOTIFICATION_TAG, NOTIFICATION_ID);
}
private LegacyVoicemailNotifier() {}
diff --git a/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/java/com/android/dialer/app/calllog/MissedCallNotifier.java
index e0e3fdf3f..b363b5ab6 100644
--- a/java/com/android/dialer/app/calllog/MissedCallNotifier.java
+++ b/java/com/android/dialer/app/calllog/MissedCallNotifier.java
@@ -17,7 +17,6 @@ package com.android.dialer.app.calllog;
import android.app.Notification;
import android.app.Notification.Builder;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -48,7 +47,9 @@ import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelId;
+import com.android.dialer.notification.NotificationManagerUtils;
import com.android.dialer.phonenumbercache.ContactInfo;
import com.android.dialer.phonenumberutil.PhoneNumberHelper;
import com.android.dialer.util.DialerUtils;
@@ -59,9 +60,17 @@ import java.util.Set;
/** Creates a notification for calls that the user missed (neither answered nor rejected). */
public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
- static final String NOTIFICATION_TAG_PREFIX = "MissedCall_";
- static final String NOTIFICATION_GROUP = "MissedCall";
+ /** Prefix used to generate a unique tag for each missed call notification. */
+ private static final String NOTIFICATION_TAG_PREFIX = "MissedCall_";
+ /** Common ID for all missed call notifications. */
private static final int NOTIFICATION_ID = 1;
+ /** Tag for the group summary notification. */
+ private static final String GROUP_SUMMARY_NOTIFICATION_TAG = "GroupSummary_MissedCall";
+ /**
+ * Key used to associate all missed call notifications and the summary as belonging to a single
+ * group.
+ */
+ private static final String GROUP_KEY = "MissedCallGroup";
private final Context context;
private final CallLogNotificationsQueryHelper callLogNotificationsQueryHelper;
@@ -202,33 +211,29 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
configureLedOnNotification(notification);
LogUtil.i("MissedCallNotifier.updateMissedCallNotification", "adding missed call notification");
- getNotificationMgr().notify(getNotificationTagForGroupSummary(), NOTIFICATION_ID, notification);
+ DialerNotificationManager.notify(
+ context, GROUP_SUMMARY_NOTIFICATION_TAG, NOTIFICATION_ID, notification);
if (useCallList) {
// Do not repost active notifications to prevent erasing post call notes.
- NotificationManager manager = getNotificationMgr();
Set<String> activeTags = new ArraySet<>();
- for (StatusBarNotification activeNotification : manager.getActiveNotifications()) {
+ for (StatusBarNotification activeNotification :
+ DialerNotificationManager.getActiveNotifications(context)) {
activeTags.add(activeNotification.getTag());
}
for (NewCall call : newCalls) {
String callTag = getNotificationTagForCall(call);
if (!activeTags.contains(callTag)) {
- manager.notify(callTag, NOTIFICATION_ID, getNotificationForCall(call, null));
+ DialerNotificationManager.notify(
+ context, callTag, NOTIFICATION_ID, getNotificationForCall(call, null));
}
}
}
}
public static void cancelAllMissedCallNotifications(@NonNull Context context) {
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
- String tag = notification.getTag();
- if (tag != null && tag.startsWith(NOTIFICATION_TAG_PREFIX)) {
- notificationManager.cancel(tag, notification.getId());
- }
- }
+ NotificationManagerUtils.cancelAllInGroup(context, GROUP_KEY);
}
public static void cancelSingleMissedCallNotification(
@@ -239,31 +244,9 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
"unable to cancel notification, uri is null");
return;
}
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- String callTag = getNotificationTagForCallUri(callUri);
- String summaryTag = getNotificationTagForGroupSummary();
- int notificationCount = 0;
-
- for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
- String currentTag = notification.getTag();
- if (currentTag == null) {
- continue;
- }
- if (currentTag.equals(callTag)) {
- notificationManager.cancel(notification.getTag(), notification.getId());
- } else if (currentTag.startsWith(NOTIFICATION_TAG_PREFIX) && !currentTag.equals(summaryTag)) {
- notificationCount++;
- }
- }
-
- if (notificationCount == 0) {
- // There are no more missed call notifications. Remove the summary notification too.
- notificationManager.cancel(summaryTag, NOTIFICATION_ID);
- }
- }
-
- private static String getNotificationTagForGroupSummary() {
- return NOTIFICATION_TAG_PREFIX + "GroupSummary";
+ // This will also dismiss the group summary if there are no more missed call notifications.
+ DialerNotificationManager.cancel(
+ context, getNotificationTagForCallUri(callUri), NOTIFICATION_ID);
}
private static String getNotificationTagForCall(@NonNull NewCall call) {
@@ -280,11 +263,11 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
for (NewCall call : newCalls) {
if (call.number.equals(number.replace("tel:", ""))) {
// Update the first notification that matches our post call note sender.
- getNotificationMgr()
- .notify(
- getNotificationTagForCall(call),
- NOTIFICATION_ID,
- getNotificationForCall(call, note));
+ DialerNotificationManager.notify(
+ context,
+ getNotificationTagForCall(call),
+ NOTIFICATION_ID,
+ getNotificationForCall(call, note));
break;
}
}
@@ -366,7 +349,7 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
private Notification.Builder createNotificationBuilder() {
return new Notification.Builder(context)
- .setGroup(NOTIFICATION_GROUP)
+ .setGroup(GROUP_KEY)
.setSmallIcon(android.R.drawable.stat_notify_missed_call)
.setColor(context.getResources().getColor(R.color.dialer_theme_color, null))
.setAutoCancel(true)
@@ -466,8 +449,4 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
private void closeSystemDialogs(Context context) {
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
}
-
- private NotificationManager getNotificationMgr() {
- return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- }
}
diff --git a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java
index 0c720775a..c1a00e58d 100644
--- a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java
+++ b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java
@@ -45,6 +45,13 @@ public class PhoneCallDetailsHelper {
/** The maximum number of icons will be shown to represent the call types in a group. */
private static final int MAX_CALL_TYPE_ICONS = 3;
+ // TODO(mdooley): remove when these api's become public
+ // Copied from android.provider.VoicemailContract
+ static final int TRANSCRIPTION_NOT_STARTED = 0;
+ static final int TRANSCRIPTION_IN_PROGRESS = 1;
+ static final int TRANSCRIPTION_FAILED = 2;
+ static final int TRANSCRIPTION_AVAILABLE = 3;
+
private final Context mContext;
private final Resources mResources;
private final CallLogCache mCallLogCache;
@@ -145,14 +152,37 @@ public class PhoneCallDetailsHelper {
if (isVoicemail) {
int relevantLinkTypes = Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS | Linkify.WEB_URLS;
views.voicemailTranscriptionView.setAutoLinkMask(relevantLinkTypes);
- views.voicemailTranscriptionView.setText(
- TextUtils.isEmpty(details.transcription) ? null : details.transcription);
+ boolean showTranscriptBranding = false;
+ if (!TextUtils.isEmpty(details.transcription)) {
+ views.voicemailTranscriptionView.setText(details.transcription);
+
+ // Set the branding text if the voicemail was transcribed by google
+ // TODO(mdooley): the transcription state is only set by the google transcription code,
+ // but a better solution would be to check the SOURCE_PACKAGE
+ showTranscriptBranding = details.transcriptionState == TRANSCRIPTION_AVAILABLE;
+ } else {
+ if (details.transcriptionState == TRANSCRIPTION_IN_PROGRESS) {
+ views.voicemailTranscriptionView.setText(
+ mResources.getString(R.string.voicemail_transcription_in_progress));
+ } else if (details.transcriptionState == TRANSCRIPTION_FAILED) {
+ views.voicemailTranscriptionView.setText(
+ mResources.getString(R.string.voicemail_transcription_failed));
+ }
+ }
+
+ if (showTranscriptBranding) {
+ views.voicemailTranscriptionBrandingView.setText(
+ mResources.getString(R.string.voicemail_transcription_branding_text));
+ } else {
+ views.voicemailTranscriptionBrandingView.setText("");
+ }
}
// Bold if not read
Typeface typeface = details.isRead ? Typeface.SANS_SERIF : Typeface.DEFAULT_BOLD;
views.nameView.setTypeface(typeface);
views.voicemailTranscriptionView.setTypeface(typeface);
+ views.voicemailTranscriptionBrandingView.setTypeface(typeface);
views.callLocationAndDate.setTypeface(typeface);
views.callLocationAndDate.setTextColor(
ContextCompat.getColor(
diff --git a/java/com/android/dialer/app/calllog/PhoneCallDetailsViews.java b/java/com/android/dialer/app/calllog/PhoneCallDetailsViews.java
index e2e27a179..40c0894f0 100644
--- a/java/com/android/dialer/app/calllog/PhoneCallDetailsViews.java
+++ b/java/com/android/dialer/app/calllog/PhoneCallDetailsViews.java
@@ -29,7 +29,9 @@ public final class PhoneCallDetailsViews {
public final View callTypeView;
public final CallTypeIconsView callTypeIcons;
public final TextView callLocationAndDate;
+ public final View transcriptionView;
public final TextView voicemailTranscriptionView;
+ public final TextView voicemailTranscriptionBrandingView;
public final TextView callAccountLabel;
private PhoneCallDetailsViews(
@@ -37,13 +39,17 @@ public final class PhoneCallDetailsViews {
View callTypeView,
CallTypeIconsView callTypeIcons,
TextView callLocationAndDate,
+ View transcriptionView,
TextView voicemailTranscriptionView,
+ TextView voicemailTranscriptionBrandingView,
TextView callAccountLabel) {
this.nameView = nameView;
this.callTypeView = callTypeView;
this.callTypeIcons = callTypeIcons;
this.callLocationAndDate = callLocationAndDate;
+ this.transcriptionView = transcriptionView;
this.voicemailTranscriptionView = voicemailTranscriptionView;
+ this.voicemailTranscriptionBrandingView = voicemailTranscriptionBrandingView;
this.callAccountLabel = callAccountLabel;
}
@@ -60,7 +66,9 @@ public final class PhoneCallDetailsViews {
view.findViewById(R.id.call_type),
(CallTypeIconsView) view.findViewById(R.id.call_type_icons),
(TextView) view.findViewById(R.id.call_location_and_date),
+ view.findViewById(R.id.transcription),
(TextView) view.findViewById(R.id.voicemail_transcription),
+ (TextView) view.findViewById(R.id.voicemail_transcription_branding),
(TextView) view.findViewById(R.id.call_account_label));
}
@@ -70,6 +78,8 @@ public final class PhoneCallDetailsViews {
new View(context),
new CallTypeIconsView(context),
new TextView(context),
+ new View(context),
+ new TextView(context),
new TextView(context),
new TextView(context));
}
diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java b/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java
index 17018b38d..8bfd48b05 100644
--- a/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java
+++ b/java/com/android/dialer/app/calllog/VisualVoicemailCallLogFragment.java
@@ -17,12 +17,14 @@
package com.android.dialer.app.calllog;
import android.app.KeyguardManager;
+import android.content.Context;
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.VisibleForTesting;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -31,15 +33,22 @@ import com.android.dialer.app.list.ListsFragment;
import com.android.dialer.app.voicemail.VoicemailAudioManager;
import com.android.dialer.app.voicemail.VoicemailErrorManager;
import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter;
+import com.android.dialer.app.voicemail.error.VoicemailErrorMessageCreator;
+import com.android.dialer.app.voicemail.error.VoicemailStatus;
+import com.android.dialer.app.voicemail.error.VoicemailStatusWorker;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutor;
+import com.android.dialer.common.concurrent.DialerExecutors;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.util.PermissionsUtil;
+import java.util.List;
public class VisualVoicemailCallLogFragment extends CallLogFragment {
private final ContentObserver mVoicemailStatusObserver = new CustomContentObserver();
private VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
+ private DialerExecutor<Context> mPreSyncVoicemailStatusCheckExecutor;
private VoicemailErrorManager mVoicemailErrorManager;
@@ -56,7 +65,6 @@ public class VisualVoicemailCallLogFragment extends CallLogFragment {
public void onActivityCreated(Bundle savedInstanceState) {
mVoicemailPlaybackPresenter =
VoicemailPlaybackPresenter.getInstance(getActivity(), savedInstanceState);
-
if (PermissionsUtil.hasReadVoicemailPermissions(getContext())
&& PermissionsUtil.hasAddVoicemailPermissions(getContext())) {
getActivity()
@@ -69,6 +77,15 @@ public class VisualVoicemailCallLogFragment extends CallLogFragment {
"read voicemail permission unavailable.");
}
super.onActivityCreated(savedInstanceState);
+
+ mPreSyncVoicemailStatusCheckExecutor =
+ DialerExecutors.createUiTaskBuilder(
+ getActivity().getFragmentManager(),
+ "fetchVoicemailStatus",
+ new VoicemailStatusWorker())
+ .onSuccess(this::onPreSyncVoicemailStatusChecked)
+ .build();
+
mVoicemailErrorManager =
new VoicemailErrorManager(getContext(), getAdapter().getAlertManager(), mModalAlertManager);
@@ -136,14 +153,38 @@ public class VisualVoicemailCallLogFragment extends CallLogFragment {
LogUtil.enterBlock("VisualVoicemailCallLogFragment.onVisible");
super.onVisible();
if (getActivity() != null) {
- Intent intent = new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL);
- intent.setPackage(getActivity().getPackageName());
- getActivity().sendBroadcast(intent);
+ mPreSyncVoicemailStatusCheckExecutor.executeParallel(getActivity());
Logger.get(getActivity()).logImpression(DialerImpression.Type.VVM_TAB_VIEWED);
getActivity().setVolumeControlStream(VoicemailAudioManager.PLAYBACK_STREAM);
}
}
+ private void onPreSyncVoicemailStatusChecked(List<VoicemailStatus> statuses) {
+ if (!shouldAutoSync(new VoicemailErrorMessageCreator(), statuses)) {
+ return;
+ }
+
+ Intent intent = new Intent(VoicemailContract.ACTION_SYNC_VOICEMAIL);
+ intent.setPackage(getActivity().getPackageName());
+ getActivity().sendBroadcast(intent);
+ }
+
+ @VisibleForTesting
+ static boolean shouldAutoSync(
+ VoicemailErrorMessageCreator errorMessageCreator, List<VoicemailStatus> statuses) {
+ for (VoicemailStatus status : statuses) {
+ if (!status.isActive()) {
+ continue;
+ }
+ if (errorMessageCreator.isSyncBlockingError(status)) {
+ LogUtil.i(
+ "VisualVoicemailCallLogFragment.shouldAutoSync", "auto-sync blocked due to " + status);
+ return false;
+ }
+ }
+ return true;
+ }
+
@Override
public void onNotVisible() {
LogUtil.enterBlock("VisualVoicemailCallLogFragment.onNotVisible");
diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java b/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java
index 99fe466d8..cbadfd317 100644
--- a/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java
+++ b/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java
@@ -17,7 +17,6 @@
package com.android.dialer.app.calllog;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -26,7 +25,6 @@ import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
-import android.service.notification.StatusBarNotification;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.os.BuildCompat;
@@ -43,7 +41,9 @@ import com.android.dialer.app.list.DialtactsPagerAdapter;
import com.android.dialer.common.LogUtil;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelManager;
+import com.android.dialer.notification.NotificationManagerUtils;
import com.android.dialer.phonenumbercache.ContactInfo;
import com.android.dialer.telecom.TelecomUtil;
import java.util.List;
@@ -51,9 +51,17 @@ import java.util.Map;
/** Shows a notification in the status bar for visual voicemail. */
final class VisualVoicemailNotifier {
+ /** Prefix used to generate a unique tag for each voicemail notification. */
private static final String NOTIFICATION_TAG_PREFIX = "VisualVoicemail_";
- private static final String NOTIFICATION_GROUP = "VisualVoicemail";
+ /** Common ID for all voicemail notifications. */
private static final int NOTIFICATION_ID = 1;
+ /** Tag for the group summary notification. */
+ private static final String GROUP_SUMMARY_NOTIFICATION_TAG = "GroupSummary_VisualVoicemail";
+ /**
+ * Key used to associate all voicemail notifications and the summary as belonging to a single
+ * group.
+ */
+ private static final String GROUP_KEY = "VisualVoicemailGroup";
public static void showNotifications(
@NonNull Context context,
@@ -82,12 +90,12 @@ final class VisualVoicemailNotifier {
groupSummary.setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle));
}
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- notificationManager.notify(
- getNotificationTagForGroupSummary(), NOTIFICATION_ID, groupSummary.build());
+ DialerNotificationManager.notify(
+ context, GROUP_SUMMARY_NOTIFICATION_TAG, NOTIFICATION_ID, groupSummary.build());
for (NewCall voicemail : newCalls) {
- notificationManager.notify(
+ DialerNotificationManager.notify(
+ context,
getNotificationTagForVoicemail(voicemail),
NOTIFICATION_ID,
createNotificationForVoicemail(context, voicemail, contactInfos));
@@ -96,13 +104,7 @@ final class VisualVoicemailNotifier {
public static void cancelAllVoicemailNotifications(@NonNull Context context) {
LogUtil.enterBlock("VisualVoicemailNotifier.cancelAllVoicemailNotifications");
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
- String tag = notification.getTag();
- if (tag != null && tag.startsWith(NOTIFICATION_TAG_PREFIX)) {
- notificationManager.cancel(tag, notification.getId());
- }
- }
+ NotificationManagerUtils.cancelAllInGroup(context, GROUP_KEY);
}
public static void cancelSingleVoicemailNotification(
@@ -112,27 +114,9 @@ final class VisualVoicemailNotifier {
LogUtil.e("VisualVoicemailNotifier.cancelSingleVoicemailNotification", "uri is null");
return;
}
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- String voicemailTag = getNotificationTagForUri(voicemailUri);
- String summaryTag = getNotificationTagForGroupSummary();
- int notificationCount = 0;
-
- for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
- String currentTag = notification.getTag();
- if (currentTag == null) {
- continue;
- }
- if (currentTag.equals(voicemailTag)) {
- notificationManager.cancel(notification.getTag(), notification.getId());
- } else if (currentTag.startsWith(NOTIFICATION_TAG_PREFIX) && !currentTag.equals(summaryTag)) {
- notificationCount++;
- }
- }
-
- if (notificationCount == 0) {
- // There are no more visual voicemail notifications. Remove the summary notification too.
- notificationManager.cancel(summaryTag, NOTIFICATION_ID);
- }
+ // This will also dismiss the group summary if there are no more voicemail notifications.
+ DialerNotificationManager.cancel(
+ context, getNotificationTagForUri(voicemailUri), NOTIFICATION_ID);
}
private static String getNotificationTagForVoicemail(@NonNull NewCall voicemail) {
@@ -143,15 +127,11 @@ final class VisualVoicemailNotifier {
return NOTIFICATION_TAG_PREFIX + voicemailUri;
}
- private static String getNotificationTagForGroupSummary() {
- return NOTIFICATION_TAG_PREFIX + "GroupSummary";
- }
-
private static Notification.Builder createNotificationBuilder(@NonNull Context context) {
return new Notification.Builder(context)
.setSmallIcon(android.R.drawable.stat_notify_voicemail)
.setColor(context.getColor(R.color.dialer_theme_color))
- .setGroup(NOTIFICATION_GROUP)
+ .setGroup(GROUP_KEY)
.setOnlyAlertOnce(true)
.setAutoCancel(true);
}
diff --git a/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java b/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java
deleted file mode 100644
index 2424b6dbd..000000000
--- a/java/com/android/dialer/app/calllog/calllogcache/CallLogCacheLollipopMr1.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2013 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.calllogcache;
-
-import android.content.Context;
-import android.support.annotation.Nullable;
-import android.telecom.PhoneAccountHandle;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import com.android.dialer.calllogutils.PhoneAccountUtils;
-import com.android.dialer.telecom.TelecomUtil;
-import java.util.Map;
-
-/**
- * This is the CallLogCache for versions of dialer Lollipop Mr1 and above with support for multi-SIM
- * devices.
- *
- * <p>This class should not be initialized directly and instead be acquired from {@link
- * CallLogCache#getCallLogCache}.
- */
-class CallLogCacheLollipopMr1 extends CallLogCache {
-
- private final Map<PhoneAccountHandle, String> mPhoneAccountLabelCache = new ArrayMap<>();
- private final Map<PhoneAccountHandle, Integer> mPhoneAccountColorCache = new ArrayMap<>();
- private final Map<PhoneAccountHandle, Boolean> mPhoneAccountCallWithNoteCache = new ArrayMap<>();
-
- /* package */ CallLogCacheLollipopMr1(Context context) {
- super(context);
- }
-
- @Override
- public void reset() {
- mPhoneAccountLabelCache.clear();
- mPhoneAccountColorCache.clear();
- mPhoneAccountCallWithNoteCache.clear();
-
- super.reset();
- }
-
- @Override
- public boolean isVoicemailNumber(
- PhoneAccountHandle accountHandle, @Nullable CharSequence number) {
- if (TextUtils.isEmpty(number)) {
- return false;
- }
- return TelecomUtil.isVoicemailNumber(mContext, accountHandle, number.toString());
- }
-
- @Override
- public String getAccountLabel(PhoneAccountHandle accountHandle) {
- if (mPhoneAccountLabelCache.containsKey(accountHandle)) {
- return mPhoneAccountLabelCache.get(accountHandle);
- } else {
- String label = PhoneAccountUtils.getAccountLabel(mContext, accountHandle);
- mPhoneAccountLabelCache.put(accountHandle, label);
- return label;
- }
- }
-
- @Override
- public int getAccountColor(PhoneAccountHandle accountHandle) {
- if (mPhoneAccountColorCache.containsKey(accountHandle)) {
- return mPhoneAccountColorCache.get(accountHandle);
- } else {
- Integer color = PhoneAccountUtils.getAccountColor(mContext, accountHandle);
- mPhoneAccountColorCache.put(accountHandle, color);
- return color;
- }
- }
-
- @Override
- public boolean doesAccountSupportCallSubject(PhoneAccountHandle accountHandle) {
- if (mPhoneAccountCallWithNoteCache.containsKey(accountHandle)) {
- return mPhoneAccountCallWithNoteCache.get(accountHandle);
- } else {
- Boolean supportsCallWithNote =
- PhoneAccountUtils.getAccountSupportsCallSubject(mContext, accountHandle);
- mPhoneAccountCallWithNoteCache.put(accountHandle, supportsCallWithNote);
- return supportsCallWithNote;
- }
- }
-}