summaryrefslogtreecommitdiffstats
path: root/java/com/android/dialer/calldetails
diff options
context:
space:
mode:
authorlinyuh <linyuh@google.com>2017-12-13 10:12:56 -0800
committerCopybara-Service <copybara-piper@google.com>2017-12-13 10:13:59 -0800
commita98ac7f0b74d6f993e9ef2a7f1ad094d1027d712 (patch)
treec9930d95ee9a8fb61d26ae66afe42d7d3f47b791 /java/com/android/dialer/calldetails
parentecfba0c3588bdbd77c5bda509b66bc621837986b (diff)
downloadandroid_packages_apps_Dialer-a98ac7f0b74d6f993e9ef2a7f1ad094d1027d712.tar.gz
android_packages_apps_Dialer-a98ac7f0b74d6f993e9ef2a7f1ad094d1027d712.tar.bz2
android_packages_apps_Dialer-a98ac7f0b74d6f993e9ef2a7f1ad094d1027d712.zip
Integrate CallDetailsActivity with the new call log UI.
Bug: 70218437 Test: CallDetailsActivityTest, CallDetailsCursorLoaderTest, ModulesTest PiperOrigin-RevId: 178918820 Change-Id: Ib8034190550e8ca8e6e7fd9ce521bfadc73e834f
Diffstat (limited to 'java/com/android/dialer/calldetails')
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsActivity.java107
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsAdapter.java4
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsCursorLoader.java139
3 files changed, 240 insertions, 10 deletions
diff --git a/java/com/android/dialer/calldetails/CallDetailsActivity.java b/java/com/android/dialer/calldetails/CallDetailsActivity.java
index c29f9e9ae..b314e26bf 100644
--- a/java/com/android/dialer/calldetails/CallDetailsActivity.java
+++ b/java/com/android/dialer/calldetails/CallDetailsActivity.java
@@ -19,9 +19,12 @@ 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;
@@ -35,11 +38,13 @@ 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.DialerPhoneNumber;
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.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.AsyncTaskExecutors;
@@ -62,6 +67,7 @@ import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
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.PhoneNumberUtil;
import java.lang.ref.WeakReference;
@@ -71,10 +77,12 @@ 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";
+ 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";
private static final String EXTRA_CAN_SUPPORT_ASSISTED_DIALING = "can_support_assisted_dialing";
@@ -93,23 +101,47 @@ public class CallDetailsActivity extends AppCompatActivity {
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();
+
public static boolean isLaunchIntent(Intent intent) {
return intent.getComponent() != null
&& CallDetailsActivity.class.getName().equals(intent.getComponent().getClassName());
}
+ /**
+ * Returns an {@link Intent} for launching the {@link CallDetailsActivity} from the old call log
+ * UI.
+ */
public static Intent newInstance(
Context context,
- @NonNull CallDetailsEntries details,
- @NonNull DialerContact contact,
+ CallDetailsEntries details,
+ DialerContact contact,
boolean canReportCallerId,
boolean canSupportAssistedDialing) {
- Assert.isNotNull(details);
- Assert.isNotNull(contact);
+ 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;
+ }
+ /**
+ * Returns an {@link Intent} for launching the {@link CallDetailsActivity} from the new call log
+ * UI.
+ */
+ public static Intent newInstance(
+ Context context,
+ CoalescedIds coalescedAnnotatedCallLogIds,
+ DialerContact contact,
+ boolean canReportCallerId,
+ boolean canSupportAssistedDialing) {
Intent intent = new Intent(context, CallDetailsActivity.class);
- ProtoParsers.put(intent, EXTRA_CONTACT, contact);
- ProtoParsers.put(intent, EXTRA_CALL_DETAILS_ENTRIES, details);
+ ProtoParsers.put(intent, EXTRA_CONTACT, Assert.isNotNull(contact));
+ ProtoParsers.put(
+ intent, EXTRA_COALESCED_CALL_LOG_IDS, Assert.isNotNull(coalescedAnnotatedCallLogIds));
intent.putExtra(EXTRA_CAN_REPORT_CALLER_ID, canReportCallerId);
intent.putExtra(EXTRA_CAN_SUPPORT_ASSISTED_DIALING, canSupportAssistedDialing);
return intent;
@@ -166,10 +198,30 @@ public class CallDetailsActivity extends AppCompatActivity {
}
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());
- entries =
- ProtoParsers.getTrusted(
- intent, EXTRA_CALL_DETAILS_ENTRIES, CallDetailsEntries.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 */,
@@ -191,6 +243,43 @@ public class CallDetailsActivity extends AppCompatActivity {
super.onBackPressed();
}
+ /**
+ * {@link LoaderCallbacks} for {@link CallDetailsCursorLoader}, which loads call detail entries
+ * from {@link AnnotatedCallLog}.
+ */
+ private static final class CallDetailsLoaderCallbacks implements LoaderCallbacks<Cursor> {
+ private final CallDetailsActivity activity;
+
+ CallDetailsLoaderCallbacks(CallDetailsActivity callDetailsActivity) {
+ this.activity = callDetailsActivity;
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ Assert.checkState(activity.coalescedCallLogIds.isPresent());
+
+ return new CallDetailsCursorLoader(activity, activity.coalescedCallLogIds.get());
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ updateCallDetailsEntries(CallDetailsCursorLoader.toCallDetailsEntries(data));
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ updateCallDetailsEntries(CallDetailsEntries.getDefaultInstance());
+ }
+
+ private void updateCallDetailsEntries(CallDetailsEntries newEntries) {
+ activity.entries = newEntries;
+ activity.adapter.updateCallDetailsEntries(newEntries.getEntriesList());
+ 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.
diff --git a/java/com/android/dialer/calldetails/CallDetailsAdapter.java b/java/com/android/dialer/calldetails/CallDetailsAdapter.java
index 9095b86ea..030366e9f 100644
--- a/java/com/android/dialer/calldetails/CallDetailsAdapter.java
+++ b/java/com/android/dialer/calldetails/CallDetailsAdapter.java
@@ -115,7 +115,9 @@ final class CallDetailsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
@Override
public int getItemCount() {
- return callDetailsEntries.size() + 2; // Header + footer
+ return callDetailsEntries.isEmpty()
+ ? 0
+ : callDetailsEntries.size() + 2; // plus header and footer
}
void updateCallDetailsEntries(List<CallDetailsEntry> entries) {
diff --git a/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java b/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java
new file mode 100644
index 000000000..838525372
--- /dev/null
+++ b/java/com/android/dialer/calldetails/CallDetailsCursorLoader.java
@@ -0,0 +1,139 @@
+/*
+ * 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.CursorLoader;
+import android.database.Cursor;
+import com.android.dialer.CoalescedIds;
+import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
+import com.android.dialer.common.Assert;
+import com.android.dialer.duo.DuoConstants;
+
+/**
+ * A {@link CursorLoader} that loads call detail entries from {@link AnnotatedCallLog} for {@link
+ * CallDetailsActivity}.
+ */
+public final class CallDetailsCursorLoader extends CursorLoader {
+
+ // Columns in AnnotatedCallLog that are needed to build a CallDetailsEntry proto.
+ // Be sure to update (1) constants that store indexes of the elements and (2) method
+ // toCallDetailsEntry(Cursor) when updating this array.
+ public static final String[] COLUMNS_FOR_CALL_DETAILS =
+ new String[] {
+ AnnotatedCallLog._ID,
+ AnnotatedCallLog.CALL_TYPE,
+ AnnotatedCallLog.FEATURES,
+ AnnotatedCallLog.TIMESTAMP,
+ AnnotatedCallLog.DURATION,
+ AnnotatedCallLog.DATA_USAGE,
+ AnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME
+ };
+
+ // Indexes for COLUMNS_FOR_CALL_DETAILS
+ private static final int ID = 0;
+ private static final int CALL_TYPE = 1;
+ private static final int FEATURES = 2;
+ private static final int TIMESTAMP = 3;
+ private static final int DURATION = 4;
+ private static final int DATA_USAGE = 5;
+ private static final int PHONE_ACCOUNT_COMPONENT_NAME = 6;
+
+ CallDetailsCursorLoader(Context context, CoalescedIds coalescedIds) {
+ super(
+ context,
+ AnnotatedCallLog.CONTENT_URI,
+ COLUMNS_FOR_CALL_DETAILS,
+ annotatedCallLogIdsSelection(coalescedIds),
+ annotatedCallLogIdsSelectionArgs(coalescedIds),
+ AnnotatedCallLog.TIMESTAMP + " DESC");
+ }
+
+ /**
+ * Build a string of the form "COLUMN_NAME IN (?, ?, ..., ?)", where COLUMN_NAME is the name of
+ * the ID column in {@link AnnotatedCallLog}.
+ *
+ * <p>This string will be used as the {@code selection} parameter to initialize the loader.
+ */
+ private static String annotatedCallLogIdsSelection(CoalescedIds coalescedIds) {
+ // First, build a string of question marks ('?') separated by commas (',').
+ StringBuilder questionMarks = new StringBuilder();
+ for (int i = 0; i < coalescedIds.getCoalescedIdCount(); i++) {
+ if (i != 0) {
+ questionMarks.append(", ");
+ }
+ questionMarks.append("?");
+ }
+
+ return AnnotatedCallLog._ID + " IN (" + questionMarks + ")";
+ }
+
+ /**
+ * Returns a string that will be used as the {@code selectionArgs} parameter to initialize the
+ * loader.
+ */
+ private static String[] annotatedCallLogIdsSelectionArgs(CoalescedIds coalescedIds) {
+ String[] args = new String[coalescedIds.getCoalescedIdCount()];
+
+ for (int i = 0; i < coalescedIds.getCoalescedIdCount(); i++) {
+ args[i] = String.valueOf(coalescedIds.getCoalescedId(i));
+ }
+
+ return args;
+ }
+
+ /**
+ * Creates a new {@link CallDetailsEntries} from the entire data set loaded by this loader.
+ *
+ * @param cursor A cursor pointing to the data set loaded by this loader. The caller must ensure
+ * the cursor is not null and the data set it points to is not empty.
+ * @return A {@link CallDetailsEntries} proto.
+ */
+ static CallDetailsEntries toCallDetailsEntries(Cursor cursor) {
+ Assert.isNotNull(cursor);
+ Assert.checkArgument(cursor.moveToFirst());
+
+ CallDetailsEntries.Builder entries = CallDetailsEntries.newBuilder();
+
+ do {
+ entries.addEntries(toCallDetailsEntry(cursor));
+ } while (cursor.moveToNext());
+
+ return entries.build();
+ }
+
+ /** Creates a new {@link CallDetailsEntry} from the provided cursor using its current position. */
+ private static CallDetailsEntry toCallDetailsEntry(Cursor cursor) {
+ CallDetailsEntry.Builder entry = CallDetailsEntry.newBuilder();
+ entry
+ .setCallId(cursor.getLong(ID))
+ .setCallType(cursor.getInt(CALL_TYPE))
+ .setFeatures(cursor.getInt(FEATURES))
+ .setDate(cursor.getLong(TIMESTAMP))
+ .setDuration(cursor.getLong(DURATION))
+ .setDataUsage(cursor.getLong(DATA_USAGE));
+
+ String phoneAccountComponentName = cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME);
+ entry.setIsDuoCall(
+ DuoConstants.PHONE_ACCOUNT_COMPONENT_NAME
+ .flattenToString()
+ .equals(phoneAccountComponentName));
+
+ return entry.build();
+ }
+}