summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2018-03-15 16:14:34 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-03-15 16:14:34 +0000
commit94067bd7f3a568fdabfaeb7a4980e9a85cd9b5c3 (patch)
tree915a941b1321789f3552e9410672e330ea00751d
parentede6377e397f4b4d6f6a46d09c10efc52724531a (diff)
parentc44bc801e4e58319ce8c881b576646d04dd2f16f (diff)
Merge changes I4727645c,I13015ee6
* changes: Added CallLogConfig. Split CallDetailsActivity
-rw-r--r--java/com/android/dialer/app/DialtactsActivity.java6
-rw-r--r--java/com/android/dialer/app/calllog/CallLogActivity.java6
-rw-r--r--java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java4
-rw-r--r--java/com/android/dialer/app/calllog/IntentProvider.java4
-rw-r--r--java/com/android/dialer/calldetails/AndroidManifest.xml8
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsActivity.java513
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsActivityCommon.java466
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsAdapter.java120
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java152
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsCursorLoader.java4
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java2
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java5
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java32
-rw-r--r--java/com/android/dialer/calldetails/OldCallDetailsActivity.java94
-rw-r--r--java/com/android/dialer/calldetails/OldCallDetailsAdapter.java73
-rw-r--r--java/com/android/dialer/calldetails/ReportDialogFragment.java2
-rw-r--r--java/com/android/dialer/calllog/CallLogConfig.java152
-rw-r--r--java/com/android/dialer/constants/ActivityRequestCodes.java2
-rw-r--r--java/com/android/dialer/main/impl/OldMainActivityPeer.java6
19 files changed, 1061 insertions, 590 deletions
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java
index 465c57911..1a8e5cc9c 100644
--- a/java/com/android/dialer/app/DialtactsActivity.java
+++ b/java/com/android/dialer/app/DialtactsActivity.java
@@ -91,7 +91,7 @@ import com.android.dialer.app.settings.DialerSettingsActivity;
import com.android.dialer.app.widget.ActionBarController;
import com.android.dialer.app.widget.SearchEditTextLayout;
import com.android.dialer.callcomposer.CallComposerActivity;
-import com.android.dialer.calldetails.CallDetailsActivity;
+import com.android.dialer.calldetails.OldCallDetailsActivity;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.callintent.CallSpecificAppData;
@@ -838,8 +838,8 @@ public class DialtactsActivity extends TransactionSafeActivity
} else if (requestCode == ActivityRequestCodes.DIALTACTS_CALL_DETAILS) {
if (resultCode == RESULT_OK
&& data != null
- && data.getBooleanExtra(CallDetailsActivity.EXTRA_HAS_ENRICHED_CALL_DATA, false)) {
- String number = data.getStringExtra(CallDetailsActivity.EXTRA_PHONE_NUMBER);
+ && data.getBooleanExtra(OldCallDetailsActivity.EXTRA_HAS_ENRICHED_CALL_DATA, false)) {
+ String number = data.getStringExtra(OldCallDetailsActivity.EXTRA_PHONE_NUMBER);
int snackbarDurationMillis = 5_000;
Snackbar.make(parentLayout, getString(R.string.ec_data_deleted), snackbarDurationMillis)
.setAction(
diff --git a/java/com/android/dialer/app/calllog/CallLogActivity.java b/java/com/android/dialer/app/calllog/CallLogActivity.java
index 99e11b06c..017c63a5d 100644
--- a/java/com/android/dialer/app/calllog/CallLogActivity.java
+++ b/java/com/android/dialer/app/calllog/CallLogActivity.java
@@ -33,7 +33,7 @@ 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.calldetails.CallDetailsActivity;
+import com.android.dialer.calldetails.OldCallDetailsActivity;
import com.android.dialer.common.Assert;
import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.database.CallLogQueryHandler;
@@ -282,8 +282,8 @@ public class CallLogActivity extends TransactionSafeActivity
if (requestCode == ActivityRequestCodes.DIALTACTS_CALL_DETAILS) {
if (resultCode == RESULT_OK
&& data != null
- && data.getBooleanExtra(CallDetailsActivity.EXTRA_HAS_ENRICHED_CALL_DATA, false)) {
- String number = data.getStringExtra(CallDetailsActivity.EXTRA_PHONE_NUMBER);
+ && data.getBooleanExtra(OldCallDetailsActivity.EXTRA_HAS_ENRICHED_CALL_DATA, false)) {
+ String number = data.getStringExtra(OldCallDetailsActivity.EXTRA_PHONE_NUMBER);
Snackbar.make(findViewById(R.id.calllog_frame), getString(R.string.ec_data_deleted), 5_000)
.setAction(
R.string.view_conversation,
diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
index 4c187faed..94bd93368 100644
--- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
+++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
@@ -63,8 +63,8 @@ import com.android.dialer.blocking.BlockedNumbersMigrator;
import com.android.dialer.blocking.FilteredNumberCompat;
import com.android.dialer.blocking.FilteredNumbersUtil;
import com.android.dialer.callcomposer.CallComposerActivity;
-import com.android.dialer.calldetails.CallDetailsActivity;
import com.android.dialer.calldetails.CallDetailsEntries;
+import com.android.dialer.calldetails.OldCallDetailsActivity;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction;
import com.android.dialer.clipboard.ClipboardUtils;
@@ -1037,7 +1037,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
String packageName = intent.getPackage();
if (DuoConstants.PACKAGE_NAME.equals(packageName)) {
startDuoActivity(intent);
- } else if (CallDetailsActivity.isLaunchIntent(intent)) {
+ } else if (OldCallDetailsActivity.isLaunchIntent(intent)) {
PerformanceReport.recordClick(UiAction.Type.OPEN_CALL_DETAIL);
((Activity) context)
.startActivityForResult(intent, ActivityRequestCodes.DIALTACTS_CALL_DETAILS);
diff --git a/java/com/android/dialer/app/calllog/IntentProvider.java b/java/com/android/dialer/app/calllog/IntentProvider.java
index 3a07a6fa0..a794c6290 100644
--- a/java/com/android/dialer/app/calllog/IntentProvider.java
+++ b/java/com/android/dialer/app/calllog/IntentProvider.java
@@ -27,8 +27,8 @@ import android.telecom.PhoneAccountHandle;
import android.telephony.TelephonyManager;
import com.android.contacts.common.model.Contact;
import com.android.contacts.common.model.ContactLoader;
-import com.android.dialer.calldetails.CallDetailsActivity;
import com.android.dialer.calldetails.CallDetailsEntries;
+import com.android.dialer.calldetails.OldCallDetailsActivity;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.dialercontact.DialerContact;
@@ -184,7 +184,7 @@ public abstract class IntentProvider {
return new IntentProvider() {
@Override
public Intent getIntent(Context context) {
- return CallDetailsActivity.newInstance(
+ return OldCallDetailsActivity.newInstance(
context, callDetailsEntries, contact, canReportCallerId, canSupportAssistedDialing);
}
};
diff --git a/java/com/android/dialer/calldetails/AndroidManifest.xml b/java/com/android/dialer/calldetails/AndroidManifest.xml
index 9cf656e42..9ef05a380 100644
--- a/java/com/android/dialer/calldetails/AndroidManifest.xml
+++ b/java/com/android/dialer/calldetails/AndroidManifest.xml
@@ -20,8 +20,14 @@
<activity
android:label="@string/call_details"
android:exported="false"
- android:name="com.android.dialer.calldetails.CallDetailsActivity"
+ android:name="com.android.dialer.calldetails.OldCallDetailsActivity"
android:theme="@style/DialerThemeBase.NoActionBar">
</activity>
+ <activity
+ android:label="@string/call_details"
+ android:exported="false"
+ android:name="com.android.dialer.calldetails.CallDetailsActivity"
+ android:theme="@style/DialerThemeBase.NoActionBar">
+ </activity>
</application>
</manifest>
diff --git a/java/com/android/dialer/calldetails/CallDetailsActivity.java b/java/com/android/dialer/calldetails/CallDetailsActivity.java
index ec124df9e..672043b6e 100644
--- a/java/com/android/dialer/calldetails/CallDetailsActivity.java
+++ b/java/com/android/dialer/calldetails/CallDetailsActivity.java
@@ -16,122 +16,42 @@
package com.android.dialer.calldetails;
-import android.Manifest.permission;
-import android.annotation.SuppressLint;
-import android.app.Activity;
import android.app.LoaderManager.LoaderCallbacks;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
-import android.os.AsyncTask;
import android.os.Bundle;
-import android.provider.CallLog;
-import android.provider.CallLog.Calls;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.RequiresPermission;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.Toolbar;
-import android.view.View;
-import android.widget.Toast;
import com.android.dialer.CoalescedIds;
-import com.android.dialer.assisteddialing.ui.AssistedDialingSettingActivity;
-import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
-import com.android.dialer.callintent.CallInitiationType;
-import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
+import com.android.dialer.calldetails.CallDetailsFooterViewHolder.ReportCallIdListener;
+import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.common.Assert;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.AsyncTaskExecutors;
-import com.android.dialer.common.concurrent.DialerExecutor.FailureListener;
-import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
-import com.android.dialer.common.concurrent.DialerExecutor.Worker;
-import com.android.dialer.common.concurrent.DialerExecutorComponent;
-import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.dialercontact.DialerContact;
-import com.android.dialer.duo.Duo;
-import com.android.dialer.duo.DuoComponent;
import com.android.dialer.enrichedcall.EnrichedCallComponent;
-import com.android.dialer.enrichedcall.EnrichedCallManager;
-import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult;
-import com.android.dialer.logging.DialerImpression;
-import com.android.dialer.logging.Logger;
-import com.android.dialer.logging.UiAction;
-import com.android.dialer.performancereport.PerformanceReport;
-import com.android.dialer.postcall.PostCall;
-import com.android.dialer.precall.PreCall;
import com.android.dialer.protos.ProtoParsers;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.i18n.phonenumbers.NumberParseException;
-import com.google.i18n.phonenumbers.PhoneNumberUtil;
-import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
-import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-/** Displays the details of a specific call log entry. */
-public class CallDetailsActivity extends AppCompatActivity {
- private static final int CALL_DETAILS_LOADER_ID = 0;
-
- public static final String EXTRA_PHONE_NUMBER = "phone_number";
- public static final String EXTRA_HAS_ENRICHED_CALL_DATA = "has_enriched_call_data";
- public static final String EXTRA_CALL_DETAILS_ENTRIES = "call_details_entries";
+/**
+ * Displays the details of a specific call log entry.
+ *
+ * <p>This activity is for the new call log.
+ *
+ * <p>See {@link CallDetailsAdapterCommon} for logic shared between this activity and the one for
+ * the old call log.
+ */
+public final class CallDetailsActivity extends CallDetailsActivityCommon {
public static final String EXTRA_COALESCED_CALL_LOG_IDS = "coalesced_call_log_ids";
public static final String EXTRA_CONTACT = "contact";
- public static final String EXTRA_CAN_REPORT_CALLER_ID = "can_report_caller_id";
- public static final String EXTRA_CAN_SUPPORT_ASSISTED_DIALING = "can_support_assisted_dialing";
-
- private final CallDetailsHeaderViewHolder.CallDetailsHeaderListener callDetailsHeaderListener =
- new CallDetailsHeaderListener(this);
- private final CallDetailsFooterViewHolder.DeleteCallDetailsListener deleteCallDetailsListener =
- new DeleteCallDetailsListener(this);
- private final CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener =
- new ReportCallIdListener(this);
- private final EnrichedCallManager.HistoricalDataChangedListener
- enrichedCallHistoricalDataChangedListener =
- new EnrichedCallHistoricalDataChangedListener(this);
-
- private CallDetailsEntries entries;
- private DialerContact contact;
- private CallDetailsAdapter adapter;
- // This will be present only when the activity is launched from the new call log UI, i.e., a list
- // of coalesced annotated call log IDs is included in the intent.
- private Optional<CoalescedIds> coalescedCallLogIds = Optional.absent();
+ private static final int CALL_DETAILS_LOADER_ID = 0;
- public static boolean isLaunchIntent(Intent intent) {
- return intent.getComponent() != null
- && CallDetailsActivity.class.getName().equals(intent.getComponent().getClassName());
- }
+ /** IDs of call log entries, used to retrieve them from the annotated call log. */
+ private CoalescedIds coalescedCallLogIds;
- /**
- * Returns an {@link Intent} for launching the {@link CallDetailsActivity} from the old call log
- * UI.
- */
- public static Intent newInstance(
- Context context,
- CallDetailsEntries details,
- DialerContact contact,
- boolean canReportCallerId,
- boolean canSupportAssistedDialing) {
- Intent intent = new Intent(context, CallDetailsActivity.class);
- ProtoParsers.put(intent, EXTRA_CONTACT, Assert.isNotNull(contact));
- ProtoParsers.put(intent, EXTRA_CALL_DETAILS_ENTRIES, Assert.isNotNull(details));
- intent.putExtra(EXTRA_CAN_REPORT_CALLER_ID, canReportCallerId);
- intent.putExtra(EXTRA_CAN_SUPPORT_ASSISTED_DIALING, canSupportAssistedDialing);
- return intent;
- }
+ private DialerContact contact;
- /**
- * Returns an {@link Intent} for launching the {@link CallDetailsActivity} from the new call log
- * UI.
- */
+ /** Returns an {@link Intent} to launch this activity. */
public static Intent newInstance(
Context context,
CoalescedIds coalescedAnnotatedCallLogIds,
@@ -148,99 +68,39 @@ public class CallDetailsActivity extends AppCompatActivity {
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.call_details_activity);
- Toolbar toolbar = findViewById(R.id.toolbar);
- toolbar.setTitle(R.string.call_details);
- toolbar.setNavigationOnClickListener(
- v -> {
- PerformanceReport.recordClick(UiAction.Type.CLOSE_CALL_DETAIL_WITH_CANCEL_BUTTON);
- finish();
- });
- onHandleIntent(getIntent());
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- // Some calls may not be recorded (eg. from quick contact),
- // so we should restart recording after these calls. (Recorded call is stopped)
- PostCall.restartPerformanceRecordingIfARecentCallExist(this);
- if (!PerformanceReport.isRecording()) {
- PerformanceReport.startRecording();
- }
-
- PostCall.promptUserForMessageIfNecessary(this, findViewById(R.id.recycler_view));
+ protected void handleIntent(Intent intent) {
+ Assert.checkArgument(intent.hasExtra(EXTRA_COALESCED_CALL_LOG_IDS));
+ Assert.checkArgument(intent.hasExtra(EXTRA_CAN_REPORT_CALLER_ID));
+ Assert.checkArgument(intent.hasExtra(EXTRA_CAN_SUPPORT_ASSISTED_DIALING));
- EnrichedCallComponent.get(this)
- .getEnrichedCallManager()
- .registerHistoricalDataChangedListener(enrichedCallHistoricalDataChangedListener);
- EnrichedCallComponent.get(this)
- .getEnrichedCallManager()
- .requestAllHistoricalData(contact.getNumber(), entries);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
+ contact = ProtoParsers.getTrusted(intent, EXTRA_CONTACT, DialerContact.getDefaultInstance());
+ setCallDetailsEntries(CallDetailsEntries.getDefaultInstance());
+ coalescedCallLogIds =
+ ProtoParsers.getTrusted(
+ intent, EXTRA_COALESCED_CALL_LOG_IDS, CoalescedIds.getDefaultInstance());
- EnrichedCallComponent.get(this)
- .getEnrichedCallManager()
- .unregisterHistoricalDataChangedListener(enrichedCallHistoricalDataChangedListener);
+ getLoaderManager()
+ .initLoader(
+ CALL_DETAILS_LOADER_ID, /* args = */ null, new CallDetailsLoaderCallbacks(this));
}
@Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- onHandleIntent(intent);
- }
-
- private void onHandleIntent(Intent intent) {
- boolean hasCallDetailsEntries = intent.hasExtra(EXTRA_CALL_DETAILS_ENTRIES);
- boolean hasCoalescedCallLogIds = intent.hasExtra(EXTRA_COALESCED_CALL_LOG_IDS);
- Assert.checkArgument(
- (hasCallDetailsEntries && !hasCoalescedCallLogIds)
- || (!hasCallDetailsEntries && hasCoalescedCallLogIds),
- "One and only one of EXTRA_CALL_DETAILS_ENTRIES and EXTRA_COALESCED_CALL_LOG_IDS "
- + "can be included in the intent.");
-
- contact = ProtoParsers.getTrusted(intent, EXTRA_CONTACT, DialerContact.getDefaultInstance());
- if (hasCallDetailsEntries) {
- entries =
- ProtoParsers.getTrusted(
- intent, EXTRA_CALL_DETAILS_ENTRIES, CallDetailsEntries.getDefaultInstance());
- } else {
- entries = CallDetailsEntries.getDefaultInstance();
- coalescedCallLogIds =
- Optional.of(
- ProtoParsers.getTrusted(
- intent, EXTRA_COALESCED_CALL_LOG_IDS, CoalescedIds.getDefaultInstance()));
- getLoaderManager()
- .initLoader(
- CALL_DETAILS_LOADER_ID, /* args = */ null, new CallDetailsLoaderCallbacks(this));
- }
-
- adapter =
- new CallDetailsAdapter(
- this /* context */,
- contact,
- entries.getEntriesList(),
- callDetailsHeaderListener,
- reportCallIdListener,
- deleteCallDetailsListener);
-
- RecyclerView recyclerView = findViewById(R.id.recycler_view);
- recyclerView.setLayoutManager(new LinearLayoutManager(this));
- recyclerView.setAdapter(adapter);
- PerformanceReport.logOnScrollStateChange(recyclerView);
+ protected CallDetailsAdapterCommon createAdapter(
+ CallDetailsHeaderListener callDetailsHeaderListener,
+ ReportCallIdListener reportCallIdListener,
+ DeleteCallDetailsListener deleteCallDetailsListener) {
+ return new CallDetailsAdapter(
+ this,
+ contact,
+ getCallDetailsEntries(),
+ callDetailsHeaderListener,
+ reportCallIdListener,
+ deleteCallDetailsListener);
}
@Override
- public void onBackPressed() {
- PerformanceReport.recordClick(UiAction.Type.PRESS_ANDROID_BACK_BUTTON);
- super.onBackPressed();
+ protected String getNumber() {
+ return contact.getNumber();
}
/**
@@ -256,9 +116,7 @@ public class CallDetailsActivity extends AppCompatActivity {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- Assert.checkState(activity.coalescedCallLogIds.isPresent());
-
- return new CallDetailsCursorLoader(activity, activity.coalescedCallLogIds.get());
+ return new CallDetailsCursorLoader(activity, Assert.isNotNull(activity.coalescedCallLogIds));
}
@Override
@@ -272,290 +130,11 @@ public class CallDetailsActivity extends AppCompatActivity {
}
private void updateCallDetailsEntries(CallDetailsEntries newEntries) {
- activity.entries = newEntries;
- activity.adapter.updateCallDetailsEntries(newEntries.getEntriesList());
+ activity.setCallDetailsEntries(newEntries);
+ activity.getAdapter().updateCallDetailsEntries(newEntries);
EnrichedCallComponent.get(activity)
.getEnrichedCallManager()
- .requestAllHistoricalData(activity.contact.getNumber(), newEntries);
- }
- }
-
- /** Delete specified calls from the call log. */
- private static class DeleteCallsTask extends AsyncTask<Void, Void, Void> {
- // Use a weak reference to hold the Activity so that there is no memory leak.
- private final WeakReference<Activity> activityWeakReference;
-
- private final DialerContact contact;
- private final CallDetailsEntries callDetailsEntries;
- private final String callIds;
-
- DeleteCallsTask(
- Activity activity, DialerContact contact, CallDetailsEntries callDetailsEntries) {
- this.activityWeakReference = new WeakReference<>(activity);
- this.contact = contact;
- this.callDetailsEntries = callDetailsEntries;
-
- StringBuilder callIds = new StringBuilder();
- for (CallDetailsEntry entry : callDetailsEntries.getEntriesList()) {
- if (callIds.length() != 0) {
- callIds.append(",");
- }
- callIds.append(entry.getCallId());
- }
- this.callIds = callIds.toString();
- }
-
- @Override
- // Suppress the lint check here as the user will not be able to see call log entries if
- // permission.WRITE_CALL_LOG is not granted.
- @SuppressLint("MissingPermission")
- @RequiresPermission(value = permission.WRITE_CALL_LOG)
- protected Void doInBackground(Void... params) {
- Activity activity = activityWeakReference.get();
- if (activity == null) {
- return null;
- }
-
- activity
- .getContentResolver()
- .delete(
- Calls.CONTENT_URI,
- CallLog.Calls._ID + " IN (" + callIds + ")" /* where */,
- null /* selectionArgs */);
- return null;
- }
-
- @Override
- public void onPostExecute(Void result) {
- Activity activity = activityWeakReference.get();
- if (activity == null) {
- return;
- }
-
- Intent data = new Intent();
- data.putExtra(EXTRA_PHONE_NUMBER, contact.getNumber());
- for (CallDetailsEntry entry : callDetailsEntries.getEntriesList()) {
- if (entry.getHistoryResultsCount() > 0) {
- data.putExtra(EXTRA_HAS_ENRICHED_CALL_DATA, true);
- break;
- }
- }
-
- activity.setResult(RESULT_OK, data);
- activity.finish();
- }
- }
-
- private static final class CallDetailsHeaderListener
- implements CallDetailsHeaderViewHolder.CallDetailsHeaderListener {
- private final WeakReference<CallDetailsActivity> activityWeakReference;
-
- CallDetailsHeaderListener(CallDetailsActivity activity) {
- this.activityWeakReference = new WeakReference<>(activity);
- }
-
- @Override
- public void placeImsVideoCall(String phoneNumber) {
- Logger.get(getActivity())
- .logImpression(DialerImpression.Type.CALL_DETAILS_IMS_VIDEO_CALL_BACK);
- PreCall.start(
- getActivity(),
- new CallIntentBuilder(phoneNumber, CallInitiationType.Type.CALL_DETAILS)
- .setIsVideoCall(true));
- }
-
- @Override
- public void placeDuoVideoCall(String phoneNumber) {
- Logger.get(getActivity())
- .logImpression(DialerImpression.Type.CALL_DETAILS_LIGHTBRINGER_CALL_BACK);
- Duo duo = DuoComponent.get(getActivity()).getDuo();
- if (!duo.isReachable(getActivity(), phoneNumber)) {
- placeImsVideoCall(phoneNumber);
- return;
- }
-
- try {
- getActivity()
- .startActivityForResult(
- duo.getIntent(getActivity(), phoneNumber), ActivityRequestCodes.DIALTACTS_DUO);
- } catch (ActivityNotFoundException e) {
- Toast.makeText(getActivity(), R.string.activity_not_available, Toast.LENGTH_SHORT).show();
- }
- }
-
- @Override
- public void placeVoiceCall(String phoneNumber, String postDialDigits) {
- Logger.get(getActivity()).logImpression(DialerImpression.Type.CALL_DETAILS_VOICE_CALL_BACK);
-
- boolean canSupportedAssistedDialing =
- getActivity()
- .getIntent()
- .getExtras()
- .getBoolean(EXTRA_CAN_SUPPORT_ASSISTED_DIALING, false);
- CallIntentBuilder callIntentBuilder =
- new CallIntentBuilder(phoneNumber + postDialDigits, CallInitiationType.Type.CALL_DETAILS);
- if (canSupportedAssistedDialing) {
- callIntentBuilder.setAllowAssistedDial(true);
- }
-
- PreCall.start(getActivity(), callIntentBuilder);
- }
-
- private CallDetailsActivity getActivity() {
- return Preconditions.checkNotNull(activityWeakReference.get());
- }
-
- @Override
- public void openAssistedDialingSettings(View unused) {
- Intent intent = new Intent(getActivity(), AssistedDialingSettingActivity.class);
- getActivity().startActivity(intent);
- }
-
- @Override
- public void createAssistedDialerNumberParserTask(
- AssistedDialingNumberParseWorker worker,
- SuccessListener<Integer> successListener,
- FailureListener failureListener) {
- DialerExecutorComponent.get(getActivity().getApplicationContext())
- .dialerExecutorFactory()
- .createUiTaskBuilder(
- getActivity().getFragmentManager(),
- "CallDetailsActivity.createAssistedDialerNumberParserTask",
- new AssistedDialingNumberParseWorker())
- .onSuccess(successListener)
- .onFailure(failureListener)
- .build()
- .executeParallel(getActivity().contact.getNumber());
- }
- }
-
- static class AssistedDialingNumberParseWorker implements Worker<String, Integer> {
-
- @Override
- public Integer doInBackground(@NonNull String phoneNumber) {
- PhoneNumber parsedNumber = null;
- try {
- parsedNumber = PhoneNumberUtil.getInstance().parse(phoneNumber, null);
- } catch (NumberParseException e) {
- LogUtil.w(
- "AssistedDialingNumberParseWorker.doInBackground",
- "couldn't parse phone number: " + LogUtil.sanitizePii(phoneNumber),
- e);
- return 0;
- }
- return parsedNumber.getCountryCode();
- }
- }
-
- private static final class DeleteCallDetailsListener
- implements CallDetailsFooterViewHolder.DeleteCallDetailsListener {
- private static final String ASYNC_TASK_ID = "task_delete";
-
- private final WeakReference<CallDetailsActivity> activityWeakReference;
-
- DeleteCallDetailsListener(CallDetailsActivity activity) {
- this.activityWeakReference = new WeakReference<>(activity);
- }
-
- @Override
- public void delete() {
- AsyncTaskExecutors.createAsyncTaskExecutor()
- .submit(
- ASYNC_TASK_ID,
- new DeleteCallsTask(getActivity(), getActivity().contact, getActivity().entries));
- }
-
- private CallDetailsActivity getActivity() {
- return Preconditions.checkNotNull(activityWeakReference.get());
- }
- }
-
- private static final class ReportCallIdListener
- implements CallDetailsFooterViewHolder.ReportCallIdListener {
- private final WeakReference<Activity> activityWeakReference;
-
- ReportCallIdListener(Activity activity) {
- this.activityWeakReference = new WeakReference<>(activity);
- }
-
- @Override
- public void reportCallId(String number) {
- ReportDialogFragment.newInstance(number)
- .show(getActivity().getFragmentManager(), null /* tag */);
- }
-
- @Override
- public boolean canReportCallerId(String number) {
- return getActivity().getIntent().getExtras().getBoolean(EXTRA_CAN_REPORT_CALLER_ID, false);
- }
-
- private Activity getActivity() {
- return Preconditions.checkNotNull(activityWeakReference.get());
- }
- }
-
- private static final class EnrichedCallHistoricalDataChangedListener
- implements EnrichedCallManager.HistoricalDataChangedListener {
- private final WeakReference<CallDetailsActivity> activityWeakReference;
-
- EnrichedCallHistoricalDataChangedListener(CallDetailsActivity activity) {
- this.activityWeakReference = new WeakReference<>(activity);
- }
-
- @Override
- public void onHistoricalDataChanged() {
- CallDetailsActivity activity = getActivity();
- Map<CallDetailsEntry, List<HistoryResult>> mappedResults =
- getAllHistoricalData(activity.contact.getNumber(), activity.entries);
-
- activity.adapter.updateCallDetailsEntries(
- generateAndMapNewCallDetailsEntriesHistoryResults(
- activity.contact.getNumber(), activity.entries, mappedResults)
- .getEntriesList());
- }
-
- private CallDetailsActivity getActivity() {
- return Preconditions.checkNotNull(activityWeakReference.get());
- }
-
- @NonNull
- private Map<CallDetailsEntry, List<HistoryResult>> getAllHistoricalData(
- @Nullable String number, @NonNull CallDetailsEntries entries) {
- if (number == null) {
- return Collections.emptyMap();
- }
-
- Map<CallDetailsEntry, List<HistoryResult>> historicalData =
- EnrichedCallComponent.get(getActivity())
- .getEnrichedCallManager()
- .getAllHistoricalData(number, entries);
- if (historicalData == null) {
- 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(
- "CallDetailsActivity.generateAndMapNewCallDetailsEntriesHistoryResults",
- "mapped %d results",
- newEntry.getHistoryResultsList().size());
- }
- mutableCallDetailsEntries.addEntries(newEntry.build());
- }
- return mutableCallDetailsEntries.build();
+ .requestAllHistoricalData(activity.getNumber(), newEntries);
}
}
}
diff --git a/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java b/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java
new file mode 100644
index 000000000..45200b9ce
--- /dev/null
+++ b/java/com/android/dialer/calldetails/CallDetailsActivityCommon.java
@@ -0,0 +1,466 @@
+/*
+ * 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.calldetails;
+
+import android.Manifest.permission;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.CallLog;
+import android.provider.CallLog.Calls;
+import android.support.annotation.CallSuper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresPermission;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.widget.Toast;
+import com.android.dialer.assisteddialing.ui.AssistedDialingSettingActivity;
+import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
+import com.android.dialer.callintent.CallInitiationType;
+import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutor.FailureListener;
+import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
+import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.database.Selection;
+import com.android.dialer.constants.ActivityRequestCodes;
+import com.android.dialer.duo.Duo;
+import com.android.dialer.duo.DuoComponent;
+import com.android.dialer.enrichedcall.EnrichedCallComponent;
+import com.android.dialer.enrichedcall.EnrichedCallManager;
+import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult;
+import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.Logger;
+import com.android.dialer.logging.UiAction;
+import com.android.dialer.performancereport.PerformanceReport;
+import com.android.dialer.postcall.PostCall;
+import com.android.dialer.precall.PreCall;
+import com.google.common.base.Preconditions;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Contains common logic shared between {@link OldCallDetailsActivity} and {@link
+ * CallDetailsActivity}.
+ */
+abstract class CallDetailsActivityCommon extends AppCompatActivity {
+
+ public static final String EXTRA_PHONE_NUMBER = "phone_number";
+ public static final String EXTRA_HAS_ENRICHED_CALL_DATA = "has_enriched_call_data";
+ public static final String EXTRA_CAN_REPORT_CALLER_ID = "can_report_caller_id";
+ public static final String EXTRA_CAN_SUPPORT_ASSISTED_DIALING = "can_support_assisted_dialing";
+
+ private final CallDetailsHeaderViewHolder.CallDetailsHeaderListener callDetailsHeaderListener =
+ new CallDetailsHeaderListener(this);
+ private final CallDetailsFooterViewHolder.DeleteCallDetailsListener deleteCallDetailsListener =
+ new DeleteCallDetailsListener(this);
+ private final CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener =
+ new ReportCallIdListener(this);
+ private final EnrichedCallManager.HistoricalDataChangedListener
+ enrichedCallHistoricalDataChangedListener =
+ new EnrichedCallHistoricalDataChangedListener(this);
+
+ private CallDetailsAdapterCommon adapter;
+ private CallDetailsEntries callDetailsEntries;
+
+ /**
+ * Handles the intent that launches {@link OldCallDetailsActivity} or {@link CallDetailsActivity},
+ * e.g., extract data from intent extras, start loading data, etc.
+ */
+ protected abstract void handleIntent(Intent intent);
+
+ /** Creates an adapter for {@link OldCallDetailsActivity} or {@link CallDetailsActivity}. */
+ protected abstract CallDetailsAdapterCommon createAdapter(
+ CallDetailsHeaderViewHolder.CallDetailsHeaderListener callDetailsHeaderListener,
+ CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener,
+ CallDetailsFooterViewHolder.DeleteCallDetailsListener deleteCallDetailsListener);
+
+ /** Returns the phone number of the call details. */
+ protected abstract String getNumber();
+
+ @Override
+ @CallSuper
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.call_details_activity);
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ toolbar.setTitle(R.string.call_details);
+ toolbar.setNavigationOnClickListener(
+ v -> {
+ PerformanceReport.recordClick(UiAction.Type.CLOSE_CALL_DETAIL_WITH_CANCEL_BUTTON);
+ finish();
+ });
+ handleIntent(getIntent());
+ setupRecyclerViewForEntries();
+ }
+
+ @Override
+ @CallSuper
+ protected void onResume() {
+ super.onResume();
+
+ // Some calls may not be recorded (eg. from quick contact),
+ // so we should restart recording after these calls. (Recorded call is stopped)
+ PostCall.restartPerformanceRecordingIfARecentCallExist(this);
+ if (!PerformanceReport.isRecording()) {
+ PerformanceReport.startRecording();
+ }
+
+ PostCall.promptUserForMessageIfNecessary(this, findViewById(R.id.recycler_view));
+
+ EnrichedCallComponent.get(this)
+ .getEnrichedCallManager()
+ .registerHistoricalDataChangedListener(enrichedCallHistoricalDataChangedListener);
+ EnrichedCallComponent.get(this)
+ .getEnrichedCallManager()
+ .requestAllHistoricalData(getNumber(), callDetailsEntries);
+ }
+
+ @Override
+ @CallSuper
+ protected void onPause() {
+ super.onPause();
+
+ EnrichedCallComponent.get(this)
+ .getEnrichedCallManager()
+ .unregisterHistoricalDataChangedListener(enrichedCallHistoricalDataChangedListener);
+ }
+
+ @Override
+ @CallSuper
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ handleIntent(intent);
+ setupRecyclerViewForEntries();
+ }
+
+ private void setupRecyclerViewForEntries() {
+ adapter =
+ createAdapter(callDetailsHeaderListener, reportCallIdListener, deleteCallDetailsListener);
+
+ RecyclerView recyclerView = findViewById(R.id.recycler_view);
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+ recyclerView.setAdapter(adapter);
+ PerformanceReport.logOnScrollStateChange(recyclerView);
+ }
+
+ final CallDetailsAdapterCommon getAdapter() {
+ return adapter;
+ }
+
+ @Override
+ @CallSuper
+ public void onBackPressed() {
+ PerformanceReport.recordClick(UiAction.Type.PRESS_ANDROID_BACK_BUTTON);
+ super.onBackPressed();
+ }
+
+ protected final void setCallDetailsEntries(CallDetailsEntries entries) {
+ this.callDetailsEntries = entries;
+ }
+
+ protected final CallDetailsEntries getCallDetailsEntries() {
+ return callDetailsEntries;
+ }
+
+ /** A {@link Worker} that deletes specified entries from the call log. */
+ private static final class DeleteCallsWorker implements Worker<CallDetailsEntries, Void> {
+ // Use a weak reference to hold the Activity so that there is no memory leak.
+ private final WeakReference<Context> contextWeakReference;
+
+ DeleteCallsWorker(Context context) {
+ this.contextWeakReference = new WeakReference<>(context);
+ }
+
+ @Override
+ // Suppress the lint check here as the user will not be able to see call log entries if
+ // permission.WRITE_CALL_LOG is not granted.
+ @SuppressLint("MissingPermission")
+ @RequiresPermission(value = permission.WRITE_CALL_LOG)
+ public Void doInBackground(CallDetailsEntries callDetailsEntries) {
+ Context context = contextWeakReference.get();
+ if (context == null) {
+ return null;
+ }
+
+ Selection selection =
+ Selection.builder()
+ .and(Selection.column(CallLog.Calls._ID).in(getCallLogIdList(callDetailsEntries)))
+ .build();
+
+ context
+ .getContentResolver()
+ .delete(Calls.CONTENT_URI, selection.getSelection(), selection.getSelectionArgs());
+ return null;
+ }
+
+ private static List<String> getCallLogIdList(CallDetailsEntries callDetailsEntries) {
+ Assert.checkArgument(callDetailsEntries.getEntriesCount() > 0);
+
+ List<String> idStrings = new ArrayList<>(callDetailsEntries.getEntriesCount());
+
+ for (CallDetailsEntry entry : callDetailsEntries.getEntriesList()) {
+ idStrings.add(String.valueOf(entry.getCallId()));
+ }
+
+ return idStrings;
+ }
+ }
+
+ private static final class CallDetailsHeaderListener
+ implements CallDetailsHeaderViewHolder.CallDetailsHeaderListener {
+ private final WeakReference<CallDetailsActivityCommon> activityWeakReference;
+
+ CallDetailsHeaderListener(CallDetailsActivityCommon activity) {
+ this.activityWeakReference = new WeakReference<>(activity);
+ }
+
+ @Override
+ public void placeImsVideoCall(String phoneNumber) {
+ Logger.get(getActivity())
+ .logImpression(DialerImpression.Type.CALL_DETAILS_IMS_VIDEO_CALL_BACK);
+ PreCall.start(
+ getActivity(),
+ new CallIntentBuilder(phoneNumber, CallInitiationType.Type.CALL_DETAILS)
+ .setIsVideoCall(true));
+ }
+
+ @Override
+ public void placeDuoVideoCall(String phoneNumber) {
+ Logger.get(getActivity())
+ .logImpression(DialerImpression.Type.CALL_DETAILS_LIGHTBRINGER_CALL_BACK);
+ Duo duo = DuoComponent.get(getActivity()).getDuo();
+ if (!duo.isReachable(getActivity(), phoneNumber)) {
+ placeImsVideoCall(phoneNumber);
+ return;
+ }
+
+ try {
+ getActivity()
+ .startActivityForResult(
+ duo.getIntent(getActivity(), phoneNumber), ActivityRequestCodes.DIALTACTS_DUO);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(getActivity(), R.string.activity_not_available, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void placeVoiceCall(String phoneNumber, String postDialDigits) {
+ Logger.get(getActivity()).logImpression(DialerImpression.Type.CALL_DETAILS_VOICE_CALL_BACK);
+
+ boolean canSupportedAssistedDialing =
+ getActivity()
+ .getIntent()
+ .getExtras()
+ .getBoolean(EXTRA_CAN_SUPPORT_ASSISTED_DIALING, false);
+ CallIntentBuilder callIntentBuilder =
+ new CallIntentBuilder(phoneNumber + postDialDigits, CallInitiationType.Type.CALL_DETAILS);
+ if (canSupportedAssistedDialing) {
+ callIntentBuilder.setAllowAssistedDial(true);
+ }
+
+ PreCall.start(getActivity(), callIntentBuilder);
+ }
+
+ private CallDetailsActivityCommon getActivity() {
+ return Preconditions.checkNotNull(activityWeakReference.get());
+ }
+
+ @Override
+ public void openAssistedDialingSettings(View unused) {
+ Intent intent = new Intent(getActivity(), AssistedDialingSettingActivity.class);
+ getActivity().startActivity(intent);
+ }
+
+ @Override
+ public void createAssistedDialerNumberParserTask(
+ AssistedDialingNumberParseWorker worker,
+ SuccessListener<Integer> successListener,
+ FailureListener failureListener) {
+ DialerExecutorComponent.get(getActivity().getApplicationContext())
+ .dialerExecutorFactory()
+ .createUiTaskBuilder(
+ getActivity().getFragmentManager(),
+ "CallDetailsActivityCommon.createAssistedDialerNumberParserTask",
+ new AssistedDialingNumberParseWorker())
+ .onSuccess(successListener)
+ .onFailure(failureListener)
+ .build()
+ .executeParallel(getActivity().getNumber());
+ }
+ }
+
+ static final class AssistedDialingNumberParseWorker implements Worker<String, Integer> {
+
+ @Override
+ public Integer doInBackground(@NonNull String phoneNumber) {
+ PhoneNumber parsedNumber;
+ try {
+ parsedNumber = PhoneNumberUtil.getInstance().parse(phoneNumber, null);
+ } catch (NumberParseException e) {
+ LogUtil.w(
+ "AssistedDialingNumberParseWorker.doInBackground",
+ "couldn't parse phone number: " + LogUtil.sanitizePii(phoneNumber),
+ e);
+ return 0;
+ }
+ return parsedNumber.getCountryCode();
+ }
+ }
+
+ private static final class DeleteCallDetailsListener
+ implements CallDetailsFooterViewHolder.DeleteCallDetailsListener {
+
+ private final WeakReference<CallDetailsActivityCommon> activityWeakReference;
+
+ DeleteCallDetailsListener(CallDetailsActivityCommon activity) {
+ this.activityWeakReference = new WeakReference<>(activity);
+ }
+
+ @Override
+ public void delete() {
+ CallDetailsActivityCommon activity = getActivity();
+ DialerExecutorComponent.get(activity)
+ .dialerExecutorFactory()
+ .createNonUiTaskBuilder(new DeleteCallsWorker(activity))
+ .onSuccess(
+ unused -> {
+ Intent data = new Intent();
+ data.putExtra(EXTRA_PHONE_NUMBER, activity.getNumber());
+ for (CallDetailsEntry entry : activity.getCallDetailsEntries().getEntriesList()) {
+ if (entry.getHistoryResultsCount() > 0) {
+ data.putExtra(EXTRA_HAS_ENRICHED_CALL_DATA, true);
+ break;
+ }
+ }
+
+ activity.setResult(RESULT_OK, data);
+ activity.finish();
+ })
+ .build()
+ .executeSerial(activity.getCallDetailsEntries());
+ }
+
+ private CallDetailsActivityCommon getActivity() {
+ return Preconditions.checkNotNull(activityWeakReference.get());
+ }
+ }
+
+ private static final class ReportCallIdListener
+ implements CallDetailsFooterViewHolder.ReportCallIdListener {
+ private final WeakReference<Activity> activityWeakReference;
+
+ ReportCallIdListener(Activity activity) {
+ this.activityWeakReference = new WeakReference<>(activity);
+ }
+
+ @Override
+ public void reportCallId(String number) {
+ ReportDialogFragment.newInstance(number)
+ .show(getActivity().getFragmentManager(), null /* tag */);
+ }
+
+ @Override
+ public boolean canReportCallerId(String number) {
+ return getActivity().getIntent().getExtras().getBoolean(EXTRA_CAN_REPORT_CALLER_ID, false);
+ }
+
+ private Activity getActivity() {
+ return Preconditions.checkNotNull(activityWeakReference.get());
+ }
+ }
+
+ private static final class EnrichedCallHistoricalDataChangedListener
+ implements EnrichedCallManager.HistoricalDataChangedListener {
+ private final WeakReference<CallDetailsActivityCommon> activityWeakReference;
+
+ EnrichedCallHistoricalDataChangedListener(CallDetailsActivityCommon activity) {
+ this.activityWeakReference = new WeakReference<>(activity);
+ }
+
+ @Override
+ public void onHistoricalDataChanged() {
+ CallDetailsActivityCommon activity = getActivity();
+ Map<CallDetailsEntry, List<HistoryResult>> mappedResults =
+ getAllHistoricalData(activity.getNumber(), activity.callDetailsEntries);
+
+ activity.adapter.updateCallDetailsEntries(
+ generateAndMapNewCallDetailsEntriesHistoryResults(
+ activity.getNumber(), activity.callDetailsEntries, mappedResults));
+ }
+
+ private CallDetailsActivityCommon getActivity() {
+ return Preconditions.checkNotNull(activityWeakReference.get());
+ }
+
+ @NonNull
+ private Map<CallDetailsEntry, List<HistoryResult>> getAllHistoricalData(
+ @Nullable String number, @NonNull CallDetailsEntries entries) {
+ if (number == null) {
+ return Collections.emptyMap();
+ }
+
+ Map<CallDetailsEntry, List<HistoryResult>> historicalData =
+ EnrichedCallComponent.get(getActivity())
+ .getEnrichedCallManager()
+ .getAllHistoricalData(number, entries);
+ if (historicalData == null) {
+ 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(
+ "CallDetailsActivityCommon.generateAndMapNewCallDetailsEntriesHistoryResults",
+ "mapped %d results",
+ newEntry.getHistoryResultsList().size());
+ }
+ mutableCallDetailsEntries.addEntries(newEntry.build());
+ }
+ return mutableCallDetailsEntries.build();
+ }
+ }
+}
diff --git a/java/com/android/dialer/calldetails/CallDetailsAdapter.java b/java/com/android/dialer/calldetails/CallDetailsAdapter.java
index 030366e9f..dfa472a71 100644
--- a/java/com/android/dialer/calldetails/CallDetailsAdapter.java
+++ b/java/com/android/dialer/calldetails/CallDetailsAdapter.java
@@ -17,119 +17,55 @@
package com.android.dialer.calldetails;
import android.content.Context;
-import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
+import android.view.View;
import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
-import com.android.dialer.calllogutils.CallTypeHelper;
-import com.android.dialer.calllogutils.CallbackActionHelper;
-import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction;
-import com.android.dialer.common.Assert;
import com.android.dialer.dialercontact.DialerContact;
-import com.android.dialer.duo.DuoComponent;
-import java.util.List;
-/** Adapter for RecyclerView in {@link CallDetailsActivity}. */
-final class CallDetailsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
-
- private static final int HEADER_VIEW_TYPE = 1;
- private static final int CALL_ENTRY_VIEW_TYPE = 2;
- private static final int FOOTER_VIEW_TYPE = 3;
+/**
+ * A {@link RecyclerView.Adapter} for {@link CallDetailsActivity}.
+ *
+ * <p>See {@link CallDetailsAdapterCommon} for logic shared between this adapter and {@link
+ * OldCallDetailsAdapter}.
+ */
+final class CallDetailsAdapter extends CallDetailsAdapterCommon {
private final DialerContact contact;
- private final CallDetailsHeaderListener callDetailsHeaderListener;
- private final CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener;
- private final DeleteCallDetailsListener deleteCallDetailsListener;
- private final CallTypeHelper callTypeHelper;
- private List<CallDetailsEntry> callDetailsEntries;
CallDetailsAdapter(
Context context,
- @NonNull DialerContact contact,
- @NonNull List<CallDetailsEntry> callDetailsEntries,
+ DialerContact contact,
+ CallDetailsEntries callDetailsEntries,
CallDetailsHeaderListener callDetailsHeaderListener,
CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener,
DeleteCallDetailsListener deleteCallDetailsListener) {
- this.contact = Assert.isNotNull(contact);
- this.callDetailsEntries = callDetailsEntries;
- this.callDetailsHeaderListener = callDetailsHeaderListener;
- this.reportCallIdListener = reportCallIdListener;
- this.deleteCallDetailsListener = deleteCallDetailsListener;
- callTypeHelper = new CallTypeHelper(context.getResources(), DuoComponent.get(context).getDuo());
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- LayoutInflater inflater = LayoutInflater.from(parent.getContext());
- switch (viewType) {
- case HEADER_VIEW_TYPE:
- return new CallDetailsHeaderViewHolder(
- inflater.inflate(R.layout.contact_container, parent, false), callDetailsHeaderListener);
- case CALL_ENTRY_VIEW_TYPE:
- return new CallDetailsEntryViewHolder(
- inflater.inflate(R.layout.call_details_entry, parent, false));
- case FOOTER_VIEW_TYPE:
- return new CallDetailsFooterViewHolder(
- inflater.inflate(R.layout.call_details_footer, parent, false),
- reportCallIdListener,
- deleteCallDetailsListener);
- default:
- throw Assert.createIllegalStateFailException(
- "No ViewHolder available for viewType: " + viewType);
- }
+ super(
+ context,
+ callDetailsEntries,
+ callDetailsHeaderListener,
+ reportCallIdListener,
+ deleteCallDetailsListener);
+ this.contact = contact;
}
@Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- if (position == 0) { // Header
- ((CallDetailsHeaderViewHolder) holder).updateContactInfo(contact, getCallbackAction());
- ((CallDetailsHeaderViewHolder) holder)
- .updateAssistedDialingInfo(callDetailsEntries.get(position));
- } else if (position == getItemCount() - 1) {
- ((CallDetailsFooterViewHolder) holder).setPhoneNumber(contact.getNumber());
- } else {
- CallDetailsEntryViewHolder viewHolder = (CallDetailsEntryViewHolder) holder;
- CallDetailsEntry entry = callDetailsEntries.get(position - 1);
- viewHolder.setCallDetails(
- contact.getNumber(),
- entry,
- callTypeHelper,
- !entry.getHistoryResultsList().isEmpty() && position != getItemCount() - 2);
- }
+ protected CallDetailsHeaderViewHolder createCallDetailsHeaderViewHolder(
+ View container, CallDetailsHeaderListener callDetailsHeaderListener) {
+ return new CallDetailsHeaderViewHolder(
+ container, contact.getNumber(), contact.getPostDialDigits(), callDetailsHeaderListener);
}
@Override
- public int getItemViewType(int position) {
- if (position == 0) { // Header
- return HEADER_VIEW_TYPE;
- } else if (position == getItemCount() - 1) {
- return FOOTER_VIEW_TYPE;
- } else {
- return CALL_ENTRY_VIEW_TYPE;
- }
+ protected void bindCallDetailsHeaderViewHolder(
+ CallDetailsHeaderViewHolder callDetailsHeaderViewHolder, int position) {
+ callDetailsHeaderViewHolder.updateContactInfo(contact, getCallbackAction());
+ callDetailsHeaderViewHolder.updateAssistedDialingInfo(
+ getCallDetailsEntries().getEntries(position));
}
@Override
- public int getItemCount() {
- return callDetailsEntries.isEmpty()
- ? 0
- : callDetailsEntries.size() + 2; // plus header and footer
- }
-
- void updateCallDetailsEntries(List<CallDetailsEntry> entries) {
- callDetailsEntries = entries;
- notifyDataSetChanged();
- }
-
- private @CallbackAction int getCallbackAction() {
- Assert.checkState(!callDetailsEntries.isEmpty());
-
- CallDetailsEntry entry = callDetailsEntries.get(0);
- return CallbackActionHelper.getCallbackAction(
- contact.getNumber(), entry.getFeatures(), entry.getIsDuoCall());
+ protected String getNumber() {
+ return contact.getNumber();
}
}
diff --git a/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java b/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java
new file mode 100644
index 000000000..27feff89d
--- /dev/null
+++ b/java/com/android/dialer/calldetails/CallDetailsAdapterCommon.java
@@ -0,0 +1,152 @@
+/*
+ * 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.calldetails;
+
+import android.content.Context;
+import android.support.annotation.CallSuper;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
+import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
+import com.android.dialer.calldetails.CallDetailsFooterViewHolder.ReportCallIdListener;
+import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
+import com.android.dialer.calllogutils.CallTypeHelper;
+import com.android.dialer.calllogutils.CallbackActionHelper;
+import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction;
+import com.android.dialer.common.Assert;
+import com.android.dialer.duo.DuoComponent;
+
+/**
+ * Contains common logic shared between {@link OldCallDetailsAdapter} and {@link
+ * CallDetailsAdapter}.
+ */
+abstract class CallDetailsAdapterCommon extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+
+ private static final int HEADER_VIEW_TYPE = 1;
+ private static final int CALL_ENTRY_VIEW_TYPE = 2;
+ private static final int FOOTER_VIEW_TYPE = 3;
+
+ private final CallDetailsHeaderListener callDetailsHeaderListener;
+ private final ReportCallIdListener reportCallIdListener;
+ private final DeleteCallDetailsListener deleteCallDetailsListener;
+ private final CallTypeHelper callTypeHelper;
+
+ private CallDetailsEntries callDetailsEntries;
+
+ protected abstract void bindCallDetailsHeaderViewHolder(
+ CallDetailsHeaderViewHolder viewHolder, int position);
+
+ protected abstract CallDetailsHeaderViewHolder createCallDetailsHeaderViewHolder(
+ View container, CallDetailsHeaderListener callDetailsHeaderListener);
+
+ /** Returns the phone number of the call details. */
+ protected abstract String getNumber();
+
+ CallDetailsAdapterCommon(
+ Context context,
+ CallDetailsEntries callDetailsEntries,
+ CallDetailsHeaderListener callDetailsHeaderListener,
+ ReportCallIdListener reportCallIdListener,
+ DeleteCallDetailsListener deleteCallDetailsListener) {
+ this.callDetailsEntries = callDetailsEntries;
+ this.callDetailsHeaderListener = callDetailsHeaderListener;
+ this.reportCallIdListener = reportCallIdListener;
+ this.deleteCallDetailsListener = deleteCallDetailsListener;
+ this.callTypeHelper =
+ new CallTypeHelper(context.getResources(), DuoComponent.get(context).getDuo());
+ }
+
+ @Override
+ @CallSuper
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+ switch (viewType) {
+ case HEADER_VIEW_TYPE:
+ return createCallDetailsHeaderViewHolder(
+ inflater.inflate(R.layout.contact_container, parent, false), callDetailsHeaderListener);
+ case CALL_ENTRY_VIEW_TYPE:
+ return new CallDetailsEntryViewHolder(
+ inflater.inflate(R.layout.call_details_entry, parent, false));
+ case FOOTER_VIEW_TYPE:
+ return new CallDetailsFooterViewHolder(
+ inflater.inflate(R.layout.call_details_footer, parent, false),
+ reportCallIdListener,
+ deleteCallDetailsListener);
+ default:
+ throw Assert.createIllegalStateFailException(
+ "No ViewHolder available for viewType: " + viewType);
+ }
+ }
+
+ @Override
+ @CallSuper
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ if (position == 0) { // Header
+ bindCallDetailsHeaderViewHolder((CallDetailsHeaderViewHolder) holder, position);
+ } else if (position == getItemCount() - 1) {
+ ((CallDetailsFooterViewHolder) holder).setPhoneNumber(getNumber());
+ } else {
+ CallDetailsEntryViewHolder viewHolder = (CallDetailsEntryViewHolder) holder;
+ CallDetailsEntry entry = callDetailsEntries.getEntries(position - 1);
+ viewHolder.setCallDetails(
+ getNumber(),
+ entry,
+ callTypeHelper,
+ !entry.getHistoryResultsList().isEmpty() && position != getItemCount() - 2);
+ }
+ }
+
+ @Override
+ @CallSuper
+ public int getItemViewType(int position) {
+ if (position == 0) { // Header
+ return HEADER_VIEW_TYPE;
+ } else if (position == getItemCount() - 1) {
+ return FOOTER_VIEW_TYPE;
+ } else {
+ return CALL_ENTRY_VIEW_TYPE;
+ }
+ }
+
+ @Override
+ @CallSuper
+ public int getItemCount() {
+ return callDetailsEntries.getEntriesCount() == 0
+ ? 0
+ : callDetailsEntries.getEntriesCount() + 2; // plus header and footer
+ }
+
+ final CallDetailsEntries getCallDetailsEntries() {
+ return callDetailsEntries;
+ }
+
+ final void updateCallDetailsEntries(CallDetailsEntries entries) {
+ callDetailsEntries = entries;
+ notifyDataSetChanged();
+ }
+
+ final @CallbackAction int getCallbackAction() {
+ Assert.checkState(!callDetailsEntries.getEntriesList().isEmpty());
+
+ CallDetailsEntry entry = callDetailsEntries.getEntries(0);
+ return CallbackActionHelper.getCallbackAction(
+ getNumber(), entry.getFeatures(), entry.getIsDuoCall());
+ }
+}
diff --git a/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java b/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java
index 15c64c927..3b8af4026 100644
--- a/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java
+++ b/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java
@@ -73,8 +73,8 @@ public final class CallDetailsCursorLoader extends CursorLoader {
// the data loading but no data can be fetched and we want to ensure the data set is not empty
// when building CallDetailsEntries proto (see toCallDetailsEntries(Cursor)).
//
- // CallDetailsActivity doesn't respond to underlying data changes when launched from the old
- // call log and we decided to keep it that way when launched from the new call log.
+ // OldCallDetailsActivity doesn't respond to underlying data changes and we decided to keep it
+ // that way in CallDetailsActivity.
}
/**
diff --git a/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java b/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
index c65bb9196..f50876d50 100644
--- a/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
+++ b/java/com/android/dialer/calldetails/CallDetailsEntryViewHolder.java
@@ -40,7 +40,7 @@ import com.android.dialer.oem.MotorolaUtils;
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.IntentUtil;
-/** ViewHolder for call entries in {@link CallDetailsActivity}. */
+/** ViewHolder for call entries in {@link OldCallDetailsActivity} or {@link CallDetailsActivity}. */
public class CallDetailsEntryViewHolder extends ViewHolder {
private final CallTypeIconsView callTypeIcon;
diff --git a/java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java b/java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java
index 30b28d83a..d6e6dbec6 100644
--- a/java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java
+++ b/java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java
@@ -31,7 +31,7 @@ import com.android.dialer.performancereport.PerformanceReport;
import com.android.dialer.util.CallUtil;
import com.android.dialer.util.DialerUtils;
-/** ViewHolder container for {@link CallDetailsActivity} footer. */
+/** ViewHolder for the footer in {@link OldCallDetailsActivity} or {@link CallDetailsActivity}. */
final class CallDetailsFooterViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
private final ReportCallIdListener reportCallIdListener;
@@ -91,7 +91,8 @@ final class CallDetailsFooterViewHolder extends RecyclerView.ViewHolder implemen
} else if (view == delete) {
deleteCallDetailsListener.delete();
} else {
- Assert.fail("View on click not implemented: " + view);
+ throw Assert.createUnsupportedOperationFailException(
+ "View on click not implemented: " + view);
}
}
diff --git a/java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java b/java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java
index 647c6edb6..34ed68836 100644
--- a/java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java
+++ b/java/com/android/dialer/calldetails/CallDetailsHeaderViewHolder.java
@@ -27,7 +27,7 @@ import android.widget.ImageView;
import android.widget.QuickContactBadge;
import android.widget.RelativeLayout;
import android.widget.TextView;
-import com.android.dialer.calldetails.CallDetailsActivity.AssistedDialingNumberParseWorker;
+import com.android.dialer.calldetails.CallDetailsActivityCommon.AssistedDialingNumberParseWorker;
import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction;
import com.android.dialer.common.Assert;
@@ -40,7 +40,11 @@ import com.android.dialer.dialercontact.DialerContact;
import com.android.dialer.logging.InteractionEvent;
import com.android.dialer.logging.Logger;
-/** ViewHolder for Header/Contact in {@link CallDetailsActivity}. */
+/**
+ * ViewHolder for the header in {@link OldCallDetailsActivity} or {@link CallDetailsActivity}.
+ *
+ * <p>The header contains contact info and the primary callback button.
+ */
public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder
implements OnClickListener, FailureListener {
@@ -54,10 +58,16 @@ public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder
private final TextView assistedDialingInternationalDirectDialCodeAndCountryCodeText;
private final RelativeLayout assistedDialingContainer;
- private DialerContact contact;
+ private final String number;
+ private final String postDialDigits;
+
private @CallbackAction int callbackAction;
- CallDetailsHeaderViewHolder(View container, CallDetailsHeaderListener callDetailsHeaderListener) {
+ CallDetailsHeaderViewHolder(
+ View container,
+ String number,
+ String postDialDigits,
+ CallDetailsHeaderListener callDetailsHeaderListener) {
super(container);
context = container.getContext();
callbackButton = container.findViewById(R.id.call_back_button);
@@ -73,7 +83,11 @@ public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder
callDetailsHeaderListener::openAssistedDialingSettings);
callbackButton.setOnClickListener(this);
+
+ this.number = number;
+ this.postDialDigits = postDialDigits;
this.callDetailsHeaderListener = callDetailsHeaderListener;
+
Logger.get(context)
.logQuickContactOnTouch(
contactPhoto, InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_CALL_DETAILS, true);
@@ -89,7 +103,7 @@ public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder
if (callDetailsEntry != null && hasAssistedDialingFeature(callDetailsEntry.getFeatures())) {
showAssistedDialingContainer(true);
callDetailsHeaderListener.createAssistedDialerNumberParserTask(
- new CallDetailsActivity.AssistedDialingNumberParseWorker(),
+ new CallDetailsActivityCommon.AssistedDialingNumberParseWorker(),
this::updateAssistedDialingText,
this::onFailure);
@@ -132,7 +146,6 @@ public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder
/** Populates the contact info fields based on the current contact information. */
void updateContactInfo(DialerContact contact, @CallbackAction int callbackAction) {
- this.contact = contact;
ContactPhotoManager.getInstance(context)
.loadDialerThumbnailOrPhoto(
contactPhoto,
@@ -194,14 +207,13 @@ public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder
if (view == callbackButton) {
switch (callbackAction) {
case CallbackAction.IMS_VIDEO:
- callDetailsHeaderListener.placeImsVideoCall(contact.getNumber());
+ callDetailsHeaderListener.placeImsVideoCall(number);
break;
case CallbackAction.DUO:
- callDetailsHeaderListener.placeDuoVideoCall(contact.getNumber());
+ callDetailsHeaderListener.placeDuoVideoCall(number);
break;
case CallbackAction.VOICE:
- callDetailsHeaderListener.placeVoiceCall(
- contact.getNumber(), contact.getPostDialDigits());
+ callDetailsHeaderListener.placeVoiceCall(number, postDialDigits);
break;
case CallbackAction.NONE:
default:
diff --git a/java/com/android/dialer/calldetails/OldCallDetailsActivity.java b/java/com/android/dialer/calldetails/OldCallDetailsActivity.java
new file mode 100644
index 000000000..1891265fb
--- /dev/null
+++ b/java/com/android/dialer/calldetails/OldCallDetailsActivity.java
@@ -0,0 +1,94 @@
+/*
+ * 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.calldetails;
+
+import android.content.Context;
+import android.content.Intent;
+import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
+import com.android.dialer.calldetails.CallDetailsFooterViewHolder.ReportCallIdListener;
+import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
+import com.android.dialer.common.Assert;
+import com.android.dialer.dialercontact.DialerContact;
+import com.android.dialer.protos.ProtoParsers;
+
+/**
+ * Displays the details of a specific call log entry.
+ *
+ * <p>This activity is for the old call log.
+ *
+ * <p>See {@link CallDetailsAdapterCommon} for logic shared between this activity and the one for
+ * the new call log.
+ */
+public final class OldCallDetailsActivity extends CallDetailsActivityCommon {
+ public static final String EXTRA_CALL_DETAILS_ENTRIES = "call_details_entries";
+ public static final String EXTRA_CONTACT = "contact";
+
+ /** Contains info to be shown in the header. */
+ private DialerContact contact;
+
+ public static boolean isLaunchIntent(Intent intent) {
+ return intent.getComponent() != null
+ && OldCallDetailsActivity.class.getName().equals(intent.getComponent().getClassName());
+ }
+
+ /** Returns an {@link Intent} to launch this activity. */
+ public static Intent newInstance(
+ Context context,
+ CallDetailsEntries details,
+ DialerContact contact,
+ boolean canReportCallerId,
+ boolean canSupportAssistedDialing) {
+ Intent intent = new Intent(context, OldCallDetailsActivity.class);
+ ProtoParsers.put(intent, EXTRA_CONTACT, Assert.isNotNull(contact));
+ ProtoParsers.put(intent, EXTRA_CALL_DETAILS_ENTRIES, Assert.isNotNull(details));
+ intent.putExtra(EXTRA_CAN_REPORT_CALLER_ID, canReportCallerId);
+ intent.putExtra(EXTRA_CAN_SUPPORT_ASSISTED_DIALING, canSupportAssistedDialing);
+ return intent;
+ }
+
+ @Override
+ protected void handleIntent(Intent intent) {
+ Assert.checkArgument(intent.hasExtra(EXTRA_CONTACT));
+ Assert.checkArgument(intent.hasExtra(EXTRA_CALL_DETAILS_ENTRIES));
+ Assert.checkArgument(intent.hasExtra(EXTRA_CAN_REPORT_CALLER_ID));
+ Assert.checkArgument(intent.hasExtra(EXTRA_CAN_SUPPORT_ASSISTED_DIALING));
+
+ contact = ProtoParsers.getTrusted(intent, EXTRA_CONTACT, DialerContact.getDefaultInstance());
+ setCallDetailsEntries(
+ ProtoParsers.getTrusted(
+ intent, EXTRA_CALL_DETAILS_ENTRIES, CallDetailsEntries.getDefaultInstance()));
+ }
+
+ @Override
+ protected CallDetailsAdapterCommon createAdapter(
+ CallDetailsHeaderListener callDetailsHeaderListener,
+ ReportCallIdListener reportCallIdListener,
+ DeleteCallDetailsListener deleteCallDetailsListener) {
+ return new OldCallDetailsAdapter(
+ /* context = */ this,
+ contact,
+ getCallDetailsEntries(),
+ callDetailsHeaderListener,
+ reportCallIdListener,
+ deleteCallDetailsListener);
+ }
+
+ @Override
+ protected String getNumber() {
+ return contact.getNumber();
+ }
+}
diff --git a/java/com/android/dialer/calldetails/OldCallDetailsAdapter.java b/java/com/android/dialer/calldetails/OldCallDetailsAdapter.java
new file mode 100644
index 000000000..010f5cd6c
--- /dev/null
+++ b/java/com/android/dialer/calldetails/OldCallDetailsAdapter.java
@@ -0,0 +1,73 @@
+/*
+ * 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.calldetails;
+
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
+import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
+import com.android.dialer.dialercontact.DialerContact;
+
+/**
+ * A {@link RecyclerView.Adapter} for {@link OldCallDetailsActivity}.
+ *
+ * <p>See {@link CallDetailsAdapterCommon} for logic shared between this adapter and {@link
+ * CallDetailsAdapter}.
+ */
+final class OldCallDetailsAdapter extends CallDetailsAdapterCommon {
+
+ /** Contains info to be shown in the header. */
+ private final DialerContact contact;
+
+ OldCallDetailsAdapter(
+ Context context,
+ DialerContact contact,
+ CallDetailsEntries callDetailsEntries,
+ CallDetailsHeaderListener callDetailsHeaderListener,
+ CallDetailsFooterViewHolder.ReportCallIdListener reportCallIdListener,
+ DeleteCallDetailsListener deleteCallDetailsListener) {
+ super(
+ context,
+ callDetailsEntries,
+ callDetailsHeaderListener,
+ reportCallIdListener,
+ deleteCallDetailsListener);
+ this.contact = contact;
+ }
+
+ @Override
+ protected CallDetailsHeaderViewHolder createCallDetailsHeaderViewHolder(
+ View container, CallDetailsHeaderListener callDetailsHeaderListener) {
+ return new CallDetailsHeaderViewHolder(
+ container, contact.getNumber(), contact.getPostDialDigits(), callDetailsHeaderListener);
+ }
+
+ @Override
+ protected void bindCallDetailsHeaderViewHolder(
+ CallDetailsHeaderViewHolder callDetailsHeaderViewHolder, int position) {
+ callDetailsHeaderViewHolder.updateContactInfo(contact, getCallbackAction());
+ callDetailsHeaderViewHolder.updateAssistedDialingInfo(
+ getCallDetailsEntries().getEntries(position));
+ }
+
+ @Override
+ protected String getNumber() {
+ return contact.getNumber();
+ }
+}
diff --git a/java/com/android/dialer/calldetails/ReportDialogFragment.java b/java/com/android/dialer/calldetails/ReportDialogFragment.java
index 0861c9dbb..d75fe51e2 100644
--- a/java/com/android/dialer/calldetails/ReportDialogFragment.java
+++ b/java/com/android/dialer/calldetails/ReportDialogFragment.java
@@ -38,7 +38,7 @@ import com.android.dialer.phonenumbercache.CachedNumberLookupService;
import com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo;
import com.android.dialer.phonenumbercache.PhoneNumberCache;
-/** Dialog for reporting an inaccurate caller id information in {@link CallDetailsActivity}. */
+/** Dialog for reporting an inaccurate caller id information. */
public class ReportDialogFragment extends DialogFragment {
private static final String KEY_NUMBER = "number";
diff --git a/java/com/android/dialer/calllog/CallLogConfig.java b/java/com/android/dialer/calllog/CallLogConfig.java
new file mode 100644
index 000000000..84400e411
--- /dev/null
+++ b/java/com/android/dialer/calllog/CallLogConfig.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.calllog;
+
+import android.content.SharedPreferences;
+import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor;
+import com.android.dialer.configprovider.ConfigProvider;
+import com.android.dialer.storage.Unencrypted;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import javax.inject.Inject;
+
+/**
+ * Determines if new call log components are enabled.
+ *
+ * <p>When the underlying flag values from the {@link ConfigProvider} changes, it is necessary to do
+ * work such as registering/unregistering content observers, and this class is responsible for
+ * coordinating that work.
+ *
+ * <p>New UI application components should use this class instead of reading flags directly from the
+ * {@link ConfigProvider}.
+ */
+public final class CallLogConfig {
+
+ private static final String NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY = "newCallLogFragmentEnabled";
+ private static final String NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY =
+ "newVoicemailFragmentEnabled";
+ private static final String NEW_PEER_ENABLED_PREF_KEY = "newPeerEnabled";
+ private static final String NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY =
+ "newCallLogFrameworkEnabled";
+
+ private final SharedPreferences sharedPreferences;
+ private final ConfigProvider configProvider;
+ private final ListeningExecutorService backgroundExecutor;
+
+ @Inject
+ CallLogConfig(
+ @Unencrypted SharedPreferences sharedPreferences,
+ ConfigProvider configProvider,
+ @BackgroundExecutor ListeningExecutorService backgroundExecutor) {
+ this.sharedPreferences = sharedPreferences;
+ this.configProvider = configProvider;
+ this.backgroundExecutor = backgroundExecutor;
+ }
+
+ /**
+ * Updates the config values. This may kick off a lot of work so should be done infrequently, for
+ * example by a scheduled job or broadcast receiver which rarely fires.
+ */
+ public ListenableFuture<Void> update() {
+ return backgroundExecutor.submit(
+ () -> {
+ boolean newCallLogFragmentEnabledInConfigProvider =
+ configProvider.getBoolean("new_call_log_fragment_enabled", false);
+ boolean newVoicemailFragmentEnabledInConfigProvider =
+ configProvider.getBoolean("new_voicemail_fragment_enabled", false);
+ boolean newPeerEnabledInConfigProvider =
+ configProvider.getBoolean("nui_peer_enabled", false);
+
+ boolean isCallLogFrameworkEnabled = isCallLogFrameworkEnabled();
+ boolean callLogFrameworkShouldBeEnabled =
+ newCallLogFragmentEnabledInConfigProvider
+ || newVoicemailFragmentEnabledInConfigProvider
+ || newPeerEnabledInConfigProvider;
+
+ if (callLogFrameworkShouldBeEnabled && !isCallLogFrameworkEnabled) {
+ enableFramework();
+
+ // Reflect the flag changes only after the framework is enabled.
+ sharedPreferences
+ .edit()
+ .putBoolean(
+ NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY,
+ newCallLogFragmentEnabledInConfigProvider)
+ .putBoolean(
+ NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY,
+ newVoicemailFragmentEnabledInConfigProvider)
+ .putBoolean(NEW_PEER_ENABLED_PREF_KEY, newPeerEnabledInConfigProvider)
+ .putBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, true)
+ .apply();
+
+ } else if (!callLogFrameworkShouldBeEnabled && isCallLogFrameworkEnabled) {
+ // Reflect the flag changes before disabling the framework.
+ sharedPreferences
+ .edit()
+ .putBoolean(NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY, false)
+ .putBoolean(NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY, false)
+ .putBoolean(NEW_PEER_ENABLED_PREF_KEY, false)
+ .putBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, false)
+ .apply();
+
+ disableFramework();
+ } else {
+ // We didn't need to enable/disable the framework, but we still need to update the
+ // individual flags.
+ sharedPreferences
+ .edit()
+ .putBoolean(
+ NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY,
+ newCallLogFragmentEnabledInConfigProvider)
+ .putBoolean(
+ NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY,
+ newVoicemailFragmentEnabledInConfigProvider)
+ .putBoolean(NEW_PEER_ENABLED_PREF_KEY, newPeerEnabledInConfigProvider)
+ .apply();
+ }
+ return null;
+ });
+ }
+
+ private void enableFramework() {
+ // TODO(zachh): Register content observers, etc.
+ }
+
+ private void disableFramework() {
+ // TODO(zachh): Unregister content observers, delete databases, etc.
+ }
+
+ public boolean isNewCallLogFragmentEnabled() {
+ return sharedPreferences.getBoolean(NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY, false);
+ }
+
+ public boolean isNewVoicemailFragmentEnabled() {
+ return sharedPreferences.getBoolean(NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY, false);
+ }
+
+ public boolean isNewPeerEnabled() {
+ return sharedPreferences.getBoolean(NEW_PEER_ENABLED_PREF_KEY, false);
+ }
+
+ /**
+ * Returns true if the new call log framework is enabled, meaning that content observers are
+ * firing and PhoneLookupHistory is being populated, etc.
+ */
+ public boolean isCallLogFrameworkEnabled() {
+ return sharedPreferences.getBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, false);
+ }
+}
diff --git a/java/com/android/dialer/constants/ActivityRequestCodes.java b/java/com/android/dialer/constants/ActivityRequestCodes.java
index 4fe3e298e..66c38fa64 100644
--- a/java/com/android/dialer/constants/ActivityRequestCodes.java
+++ b/java/com/android/dialer/constants/ActivityRequestCodes.java
@@ -35,6 +35,6 @@ public final class ActivityRequestCodes {
/** Request code for {@link Duo#getIntent(android.content.Context, String)}. */
public static final int DIALTACTS_DUO = 3;
- /** Request code for {@link com.android.dialer.calldetails.CallDetailsActivity} intent. */
+ /** Request code for {@link com.android.dialer.calldetails.OldCallDetailsActivity} intent. */
public static final int DIALTACTS_CALL_DETAILS = 4;
}
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index 03afef4b4..9f15d28c5 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -61,7 +61,7 @@ import com.android.dialer.app.list.OnListFragmentScrolledListener;
import com.android.dialer.app.list.PhoneFavoriteSquareTileView;
import com.android.dialer.app.list.RemoveView;
import com.android.dialer.callcomposer.CallComposerActivity;
-import com.android.dialer.calldetails.CallDetailsActivity;
+import com.android.dialer.calldetails.OldCallDetailsActivity;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.callintent.CallSpecificAppData;
import com.android.dialer.common.FragmentUtils.FragmentUtilListener;
@@ -506,8 +506,8 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
} else if (requestCode == ActivityRequestCodes.DIALTACTS_CALL_DETAILS) {
if (resultCode == AppCompatActivity.RESULT_OK
&& data != null
- && data.getBooleanExtra(CallDetailsActivity.EXTRA_HAS_ENRICHED_CALL_DATA, false)) {
- String number = data.getStringExtra(CallDetailsActivity.EXTRA_PHONE_NUMBER);
+ && data.getBooleanExtra(OldCallDetailsActivity.EXTRA_HAS_ENRICHED_CALL_DATA, false)) {
+ String number = data.getStringExtra(OldCallDetailsActivity.EXTRA_PHONE_NUMBER);
int snackbarDurationMillis = 5_000;
Snackbar.make(
snackbarContainer,