summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/calllog
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/calllog')
-rw-r--r--java/com/android/dialer/calllog/CallLogFramework.java2
-rw-r--r--java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java20
-rw-r--r--java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java25
-rw-r--r--java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java33
-rw-r--r--java/com/android/dialer/calllog/database/Coalescer.java52
-rw-r--r--java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java23
-rw-r--r--java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java3
-rw-r--r--java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java54
-rw-r--r--java/com/android/dialer/calllog/testing/FakeCallLogApplication.java22
-rw-r--r--java/com/android/dialer/calllog/ui/NewCallLogFragment.java12
10 files changed, 214 insertions, 32 deletions
diff --git a/java/com/android/dialer/calllog/CallLogFramework.java b/java/com/android/dialer/calllog/CallLogFramework.java
index 55ef15b47..d3a2c638e 100644
--- a/java/com/android/dialer/calllog/CallLogFramework.java
+++ b/java/com/android/dialer/calllog/CallLogFramework.java
@@ -24,8 +24,8 @@ import android.support.annotation.Nullable;
import com.android.dialer.calllog.datasources.CallLogDataSource;
import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.common.Assert;
-import com.android.dialer.common.ConfigProviderBindings;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.configprovider.ConfigProviderBindings;
import javax.inject.Inject;
import javax.inject.Singleton;
diff --git a/java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java b/java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java
index d25ec5e65..273246649 100644
--- a/java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java
+++ b/java/com/android/dialer/calllog/RefreshAnnotatedCallLogWorker.java
@@ -31,6 +31,7 @@ import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.inject.ApplicationContext;
import javax.inject.Inject;
/**
@@ -44,7 +45,7 @@ public class RefreshAnnotatedCallLogWorker implements Worker<Boolean, Void> {
private final DataSources dataSources;
@Inject
- RefreshAnnotatedCallLogWorker(Context appContext, DataSources dataSources) {
+ RefreshAnnotatedCallLogWorker(@ApplicationContext Context appContext, DataSources dataSources) {
this.appContext = appContext;
this.dataSources = dataSources;
}
@@ -159,11 +160,20 @@ public class RefreshAnnotatedCallLogWorker implements Worker<Boolean, Void> {
"applyToDatabase took: %dms",
System.currentTimeMillis() - startTime);
+ for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) {
+ dataSourceName = getName(dataSource);
+ LogUtil.i("RefreshAnnotatedCallLogWorker.rebuild", "onSuccessfulFill'ing %s", dataSourceName);
+ startTime = System.currentTimeMillis();
+ dataSource.onSuccessfulFill(appContext);
+ LogUtil.i(
+ "CallLogFramework.rebuild",
+ "%s.onSuccessfulFill took: %dms",
+ dataSourceName,
+ System.currentTimeMillis() - startTime);
+ }
+
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
- sharedPreferences
- .edit()
- .putBoolean(CallLogFramework.PREF_FORCE_REBUILD, false)
- .commit();
+ sharedPreferences.edit().putBoolean(CallLogFramework.PREF_FORCE_REBUILD, false).apply();
}
private static String getName(CallLogDataSource dataSource) {
diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java
index a9c0d36b0..30aa2bff5 100644
--- a/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java
+++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java
@@ -41,6 +41,13 @@ import java.util.ArrayList;
/** {@link ContentProvider} for the annotated call log. */
public class AnnotatedCallLogContentProvider extends ContentProvider {
+ /**
+ * We sometimes run queries where we potentially pass every ID into a where clause using the
+ * (?,?,?,...) syntax. The maximum number of host parameters is 999, so that's the maximum size
+ * this table can be. See https://www.sqlite.org/limits.html for more details.
+ */
+ private static final int MAX_ROWS = 999;
+
private static final int ANNOTATED_CALL_LOG_TABLE_CODE = 1;
private static final int ANNOTATED_CALL_LOG_TABLE_ID_CODE = 2;
private static final int COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE = 3;
@@ -72,7 +79,7 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
@Override
public boolean onCreate() {
- databaseHelper = new AnnotatedCallLogDatabaseHelper(getContext());
+ databaseHelper = new AnnotatedCallLogDatabaseHelper(getContext(), MAX_ROWS);
coalescer = CallLogDatabaseComponent.get(getContext()).coalescer();
return true;
}
@@ -283,7 +290,21 @@ public class AnnotatedCallLogContentProvider extends ContentProvider {
throw new OperationApplicationException("error inserting row");
}
} else if (result.count == 0) {
- throw new OperationApplicationException("error updating or deleting rows");
+ /*
+ * The batches built by MutationApplier happen to contain operations in order of:
+ *
+ * 1. Inserts
+ * 2. Updates
+ * 3. Deletes
+ *
+ * Let's say the last row in the table is row Z, and MutationApplier wishes to update it,
+ * as well as insert row A. When row A gets inserted, row Z will be deleted via the
+ * trigger if the table is full. Then later, when we try to process the update for row Z,
+ * it won't exist.
+ */
+ LogUtil.w(
+ "AnnotatedCallLogContentProvider.applyBatch",
+ "update or delete failed, possibly because row got cleaned up");
}
results[i] = result;
}
diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
index 3cca639ff..887dfcbb6 100644
--- a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
+++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
@@ -21,28 +21,53 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.common.LogUtil;
+import java.util.Locale;
/** {@link SQLiteOpenHelper} for the AnnotatedCallLog database. */
class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper {
+ private final int maxRows;
- AnnotatedCallLogDatabaseHelper(Context appContext) {
+ AnnotatedCallLogDatabaseHelper(Context appContext, int maxRows) {
super(appContext, "annotated_call_log.db", null, 1);
+ this.maxRows = maxRows;
}
- private static final String CREATE_SQL =
+ private static final String CREATE_TABLE_SQL =
new StringBuilder()
.append("create table if not exists " + AnnotatedCallLog.TABLE + " (")
.append(AnnotatedCallLog._ID + " integer primary key, ")
.append(AnnotatedCallLog.TIMESTAMP + " integer, ")
- .append(AnnotatedCallLog.CONTACT_NAME + " string")
+ .append(AnnotatedCallLog.CONTACT_NAME + " string, ")
+ .append(AnnotatedCallLog.NUMBER + " blob")
.append(");")
.toString();
+ /** Deletes all but the first maxRows rows (by timestamp) to keep the table a manageable size. */
+ private static final String CREATE_TRIGGER_SQL =
+ "create trigger delete_old_rows after insert on "
+ + AnnotatedCallLog.TABLE
+ + " when (select count(*) from "
+ + AnnotatedCallLog.TABLE
+ + ") > %d"
+ + " begin delete from "
+ + AnnotatedCallLog.TABLE
+ + " where "
+ + AnnotatedCallLog._ID
+ + " in (select "
+ + AnnotatedCallLog._ID
+ + " from "
+ + AnnotatedCallLog.TABLE
+ + " order by timestamp limit (select count(*)-%d"
+ + " from "
+ + AnnotatedCallLog.TABLE
+ + " )); end;";
+
@Override
public void onCreate(SQLiteDatabase db) {
LogUtil.enterBlock("AnnotatedCallLogDatabaseHelper.onCreate");
long startTime = System.currentTimeMillis();
- db.execSQL(CREATE_SQL);
+ db.execSQL(CREATE_TABLE_SQL);
+ db.execSQL(String.format(Locale.US, CREATE_TRIGGER_SQL, maxRows, maxRows));
// TODO: Consider logging impression.
LogUtil.i(
"AnnotatedCallLogDatabaseHelper.onCreate",
diff --git a/java/com/android/dialer/calllog/database/Coalescer.java b/java/com/android/dialer/calllog/database/Coalescer.java
index e3dfb7ece..5683687fd 100644
--- a/java/com/android/dialer/calllog/database/Coalescer.java
+++ b/java/com/android/dialer/calllog/database/Coalescer.java
@@ -17,15 +17,18 @@ package com.android.dialer.calllog.database;
import android.content.ContentValues;
import android.database.Cursor;
-import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.support.annotation.NonNull;
import android.support.annotation.WorkerThread;
+import com.android.dialer.DialerPhoneNumber;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
import com.android.dialer.calllog.datasources.CallLogDataSource;
import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.common.Assert;
+import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.protobuf.InvalidProtocolBufferException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -64,6 +67,9 @@ public class Coalescer {
// Note: This method relies on rowsShouldBeCombined to determine which rows should be combined,
// but delegates to data sources to actually aggregate column values.
+ DialerPhoneNumberUtil dialerPhoneNumberUtil =
+ new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());
+
MatrixCursor allCoalescedRowsMatrixCursor =
new MatrixCursor(
CoalescedAnnotatedCallLog.ALL_COLUMNS,
@@ -75,9 +81,8 @@ public class Coalescer {
List<ContentValues> currentRowGroup = new ArrayList<>();
do {
- ContentValues currentRow = new ContentValues();
- DatabaseUtils.cursorRowToContentValues(
- allAnnotatedCallLogRowsSortedByTimestampDesc, currentRow);
+ ContentValues currentRow =
+ cursorRowToContentValues(allAnnotatedCallLogRowsSortedByTimestampDesc);
if (currentRowGroup.isEmpty()) {
currentRowGroup.add(currentRow);
@@ -86,7 +91,7 @@ public class Coalescer {
ContentValues previousRow = currentRowGroup.get(currentRowGroup.size() - 1);
- if (!rowsShouldBeCombined(previousRow, currentRow)) {
+ if (!rowsShouldBeCombined(dialerPhoneNumberUtil, previousRow, currentRow)) {
ContentValues coalescedRow = coalesceRowsForAllDataSources(currentRowGroup);
coalescedRow.put(CoalescedAnnotatedCallLog.NUMBER_CALLS, currentRowGroup.size());
addContentValuesToMatrixCursor(
@@ -104,13 +109,46 @@ public class Coalescer {
return allCoalescedRowsMatrixCursor;
}
+ private static ContentValues cursorRowToContentValues(Cursor cursor) {
+ ContentValues values = new ContentValues();
+ String[] columns = cursor.getColumnNames();
+ int length = columns.length;
+ for (int i = 0; i < length; i++) {
+ if (cursor.getType(i) == Cursor.FIELD_TYPE_BLOB) {
+ values.put(columns[i], cursor.getBlob(i));
+ } else {
+ values.put(columns[i], cursor.getString(i));
+ }
+ }
+ return values;
+ }
+
/**
* @param row1 a row from {@link AnnotatedCallLog}
* @param row2 a row from {@link AnnotatedCallLog}
*/
- private static boolean rowsShouldBeCombined(ContentValues row1, ContentValues row2) {
+ private static boolean rowsShouldBeCombined(
+ DialerPhoneNumberUtil dialerPhoneNumberUtil, ContentValues row1, ContentValues row2) {
// TODO: Real implementation.
- return row1.get(AnnotatedCallLog.TIMESTAMP).equals(row2.get(AnnotatedCallLog.TIMESTAMP));
+ DialerPhoneNumber number1;
+ DialerPhoneNumber number2;
+ try {
+ number1 = DialerPhoneNumber.parseFrom(row1.getAsByteArray(AnnotatedCallLog.NUMBER));
+ number2 = DialerPhoneNumber.parseFrom(row2.getAsByteArray(AnnotatedCallLog.NUMBER));
+ } catch (InvalidProtocolBufferException e) {
+ throw Assert.createAssertionFailException("error parsing DialerPhoneNumber proto", e);
+ }
+
+ if (!number1.hasDialerInternalPhoneNumber() && !number2.hasDialerInternalPhoneNumber()) {
+ // Empty numbers should not be combined.
+ return false;
+ }
+
+ if (!number1.hasDialerInternalPhoneNumber() || !number2.hasDialerInternalPhoneNumber()) {
+ // An empty number should not be combined with a non-empty number.
+ return false;
+ }
+ return dialerPhoneNumberUtil.isExactMatch(number1, number2);
}
/**
diff --git a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
index 8b3b0a852..7f314e37c 100644
--- a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
+++ b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java
@@ -66,6 +66,18 @@ public class AnnotatedCallLogContract {
/** The MIME type of a {@link android.content.ContentProvider#getType(Uri)} single entry. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/annotated_call_log";
+
+ /**
+ * The phone number called or number the call came from, encoded as a {@link
+ * com.android.dialer.DialerPhoneNumber} proto. The number may be empty if it was an incoming
+ * call and the number was unknown.
+ *
+ * <p>This column is only present in the annotated call log, and not the coalesced annotated
+ * call log. The coalesced version uses a formatted number string rather than proto bytes.
+ *
+ * <p>Type: BLOB
+ */
+ public static final String NUMBER = "number";
}
/**
@@ -96,10 +108,19 @@ public class AnnotatedCallLogContract {
public static final String NUMBER_CALLS = "number_calls";
/**
+ * The phone number formatted in a way suitable for display to the user. This value is generated
+ * on the fly when the {@link CoalescedAnnotatedCallLog} is generated.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String FORMATTED_NUMBER = "formatted_number";
+
+ /**
* Columns that are only in the {@link CoalescedAnnotatedCallLog} but not the {@link
* AnnotatedCallLog}.
*/
- private static final String[] COLUMNS_ONLY_IN_COALESCED_CALL_LOG = new String[] {NUMBER_CALLS};
+ private static final String[] COLUMNS_ONLY_IN_COALESCED_CALL_LOG =
+ new String[] {NUMBER_CALLS, FORMATTED_NUMBER};
/** All columns in the {@link CoalescedAnnotatedCallLog}. */
public static final String[] ALL_COLUMNS =
diff --git a/java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java b/java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java
index e9538daab..82a85235b 100644
--- a/java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/contacts/ContactsDataSource.java
@@ -50,6 +50,9 @@ public final class ContactsDataSource implements CallLogDataSource {
CallLogMutations mutations) {
Assert.isWorkerThread();
// TODO: Implementation.
+ for (ContentValues contentValues : mutations.getInserts().values()) {
+ contentValues.put(AnnotatedCallLog.CONTACT_NAME, "Placeholder name");
+ }
}
@Override
diff --git a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
index be2df6043..f2063283f 100644
--- a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
@@ -34,14 +34,19 @@ import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
import android.text.TextUtils;
import android.util.ArraySet;
+import com.android.dialer.DialerPhoneNumber;
import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog;
import com.android.dialer.calllog.datasources.CallLogDataSource;
import com.android.dialer.calllog.datasources.CallLogMutations;
import com.android.dialer.calllog.datasources.util.RowCombiner;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
import com.android.dialer.util.PermissionsUtil;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.protobuf.InvalidProtocolBufferException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@@ -132,16 +137,39 @@ public class SystemCallLogDataSource implements CallLogDataSource {
PreferenceManager.getDefaultSharedPreferences(appContext)
.edit()
.putLong(PREF_LAST_TIMESTAMP_PROCESSED, lastTimestampProcessed)
- .commit();
+ .apply();
}
}
@Override
public ContentValues coalesce(List<ContentValues> individualRowsSortedByTimestampDesc) {
// TODO: Complete implementation.
- return new RowCombiner(individualRowsSortedByTimestampDesc)
- .useMostRecentLong(AnnotatedCallLog.TIMESTAMP)
- .combine();
+ ContentValues coalescedValues =
+ new RowCombiner(individualRowsSortedByTimestampDesc)
+ .useMostRecentLong(AnnotatedCallLog.TIMESTAMP)
+ .combine();
+
+ // All phone numbers in the provided group should be equivalent (but could be formatted
+ // differently). Arbitrarily show the raw phone number of the most recent call.
+ DialerPhoneNumber mostRecentPhoneNumber =
+ getMostRecentPhoneNumber(individualRowsSortedByTimestampDesc);
+ coalescedValues.put(
+ CoalescedAnnotatedCallLog.FORMATTED_NUMBER,
+ mostRecentPhoneNumber.getRawInput().getNumber());
+ return coalescedValues;
+ }
+
+ private static DialerPhoneNumber getMostRecentPhoneNumber(
+ List<ContentValues> individualRowsSortedByTimestampDesc) {
+ DialerPhoneNumber dialerPhoneNumber;
+ byte[] protoBytes =
+ individualRowsSortedByTimestampDesc.get(0).getAsByteArray(AnnotatedCallLog.NUMBER);
+ try {
+ dialerPhoneNumber = DialerPhoneNumber.parseFrom(protoBytes);
+ } catch (InvalidProtocolBufferException e) {
+ throw Assert.createAssertionFailException("couldn't parse DialerPhoneNumber", e);
+ }
+ return dialerPhoneNumber;
}
@TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources
@@ -151,12 +179,18 @@ public class SystemCallLogDataSource implements CallLogDataSource {
PreferenceManager.getDefaultSharedPreferences(appContext)
.getLong(PREF_LAST_TIMESTAMP_PROCESSED, 0L);
+ DialerPhoneNumberUtil dialerPhoneNumberUtil =
+ new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance());
+
+ // TODO: Really should be getting last 1000 by timestamp, not by last modified.
try (Cursor cursor =
appContext
.getContentResolver()
.query(
Calls.CONTENT_URI, // Excludes voicemail
- new String[] {Calls._ID, Calls.DATE, Calls.LAST_MODIFIED},
+ new String[] {
+ Calls._ID, Calls.DATE, Calls.LAST_MODIFIED, Calls.NUMBER, Calls.COUNTRY_ISO
+ },
Calls.LAST_MODIFIED + " > ?",
new String[] {String.valueOf(previousTimestampProcessed)},
Calls.LAST_MODIFIED + " DESC LIMIT 1000")) {
@@ -175,6 +209,8 @@ public class SystemCallLogDataSource implements CallLogDataSource {
int idColumn = cursor.getColumnIndexOrThrow(Calls._ID);
int dateColumn = cursor.getColumnIndexOrThrow(Calls.DATE);
int lastModifiedColumn = cursor.getColumnIndexOrThrow(Calls.LAST_MODIFIED);
+ int numberColumn = cursor.getColumnIndexOrThrow(Calls.NUMBER);
+ int countryIsoColumn = cursor.getColumnIndexOrThrow(Calls.COUNTRY_ISO);
// The cursor orders by LAST_MODIFIED DESC, so the first result is the most recent timestamp
// processed.
@@ -182,9 +218,15 @@ public class SystemCallLogDataSource implements CallLogDataSource {
do {
long id = cursor.getLong(idColumn);
long date = cursor.getLong(dateColumn);
+ String numberAsStr = cursor.getString(numberColumn);
+ String countryIso = cursor.getString(countryIsoColumn);
+
+ byte[] numberAsProtoBytes =
+ dialerPhoneNumberUtil.parse(numberAsStr, countryIso).toByteArray();
ContentValues contentValues = new ContentValues();
contentValues.put(AnnotatedCallLog.TIMESTAMP, date);
+ contentValues.put(AnnotatedCallLog.NUMBER, numberAsProtoBytes);
if (existingAnnotatedCallLogIds.contains(id)) {
mutations.update(id, contentValues);
@@ -202,7 +244,7 @@ public class SystemCallLogDataSource implements CallLogDataSource {
getIdsFromSystemCallLogThatMatch(appContext, existingAnnotatedCallLogIds);
LogUtil.i(
"SystemCallLogDataSource.handleDeletes",
- "found %d entries in system call log",
+ "found %d matching entries in system call log",
systemCallLogIds.size());
Set<Long> idsInAnnotatedCallLogNoLongerInSystemCallLog = new ArraySet<>();
idsInAnnotatedCallLogNoLongerInSystemCallLog.addAll(existingAnnotatedCallLogIds);
diff --git a/java/com/android/dialer/calllog/testing/FakeCallLogApplication.java b/java/com/android/dialer/calllog/testing/FakeCallLogApplication.java
index cb2240539..8aee7dd56 100644
--- a/java/com/android/dialer/calllog/testing/FakeCallLogApplication.java
+++ b/java/com/android/dialer/calllog/testing/FakeCallLogApplication.java
@@ -16,8 +16,12 @@
package com.android.dialer.calllog.testing;
import android.app.Application;
+import com.android.dialer.calllog.CallLogComponent;
import com.android.dialer.calllog.CallLogModule;
import com.android.dialer.calllog.database.CallLogDatabaseComponent;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.testing.TestDialerExecutorModule;
+import com.android.dialer.inject.ContextModule;
import com.android.dialer.inject.HasRootComponent;
import dagger.Component;
import javax.inject.Singleton;
@@ -27,13 +31,23 @@ import javax.inject.Singleton;
* tests to depend on and use all of DialerApplication.
*/
public final class FakeCallLogApplication extends Application implements HasRootComponent {
+ private Object rootComponent;
@Override
- public Object component() {
- return DaggerFakeCallLogApplication_FakeComponent.create();
+ public final synchronized Object component() {
+ if (rootComponent == null) {
+ rootComponent =
+ DaggerFakeCallLogApplication_FakeComponent.builder()
+ .contextModule(new ContextModule(this))
+ .build();
+ }
+ return rootComponent;
}
@Singleton
- @Component(modules = CallLogModule.class)
- interface FakeComponent extends CallLogDatabaseComponent.HasComponent {}
+ @Component(modules = {CallLogModule.class, ContextModule.class, TestDialerExecutorModule.class})
+ interface FakeComponent
+ extends CallLogDatabaseComponent.HasComponent,
+ CallLogComponent.HasComponent,
+ DialerExecutorComponent.HasComponent {}
}
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
index 89ed52fd7..712f7cf25 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
@@ -39,6 +39,14 @@ import com.android.dialer.common.concurrent.DialerExecutorFactory;
public final class NewCallLogFragment extends Fragment
implements CallLogUi, LoaderCallbacks<Cursor> {
+ /*
+ * This is a reasonable time that it might take between related call log writes, that also
+ * shouldn't slow down single-writes too much. For example, when populating the database using
+ * the simulator, using this value results in ~6 refresh cycles (on a release build) to write 120
+ * call log entries.
+ */
+ private static final long WAIT_MILLIS = 100L;
+
private DialerExecutor<Boolean> refreshAnnotatedCallLogTask;
private RecyclerView recyclerView;
@@ -113,13 +121,13 @@ public final class NewCallLogFragment extends Fragment
private void checkAnnotatedCallLogDirtyAndRefreshIfNecessary() {
LogUtil.enterBlock("NewCallLogFragment.checkAnnotatedCallLogDirtyAndRefreshIfNecessary");
- refreshAnnotatedCallLogTask.executeSerial(false /* skipDirtyCheck */);
+ refreshAnnotatedCallLogTask.executeSerialWithWait(false /* skipDirtyCheck */, WAIT_MILLIS);
}
@Override
public void invalidateUi() {
LogUtil.enterBlock("NewCallLogFragment.invalidateUi");
- refreshAnnotatedCallLogTask.executeSerial(true /* skipDirtyCheck */);
+ refreshAnnotatedCallLogTask.executeSerialWithWait(true /* skipDirtyCheck */, WAIT_MILLIS);
}
@Override