diff options
author | Tobias Thierer <tobiast@google.com> | 2017-06-09 14:16:05 +0000 |
---|---|---|
committer | Tobias Thierer <tobiast@google.com> | 2017-06-09 14:16:05 +0000 |
commit | cded3beaf28a703e1ef8f71bbc6836e6806c3736 (patch) | |
tree | c1b5e8199b5996fc848e7455d04126b9cdbb3c39 /java/com/android/dialer/calllog/database | |
parent | c67d658e7daa453fe9ad9fd1a37f81eaf2048c44 (diff) |
Revert "Update AOSP Dialer source from internal google3 repository at cl/158012278. am: 91ce7d2a47"
This reverts commit c67d658e7daa453fe9ad9fd1a37f81eaf2048c44.
Reason for revert: This CL broke the sailfish-userdebug_javac-all target on master.
Change-Id: I9b54333a654c00154ca84f4ece84bea4f07cc19b
Diffstat (limited to 'java/com/android/dialer/calllog/database')
9 files changed, 121 insertions, 746 deletions
diff --git a/java/com/android/dialer/calllog/database/AndroidManifest.xml b/java/com/android/dialer/calllog/database/AndroidManifest.xml deleted file mode 100644 index 396a6d9a1..000000000 --- a/java/com/android/dialer/calllog/database/AndroidManifest.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - ~ 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 - --> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.dialer.calllog.database"> - - <application> - - <provider - android:authorities="com.android.dialer.annotatedcalllog" - android:exported="false" - android:multiprocess="false" - android:name=".AnnotatedCallLogContentProvider"/> - - </application> -</manifest> diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLog.java b/java/com/android/dialer/calllog/database/AnnotatedCallLog.java new file mode 100644 index 000000000..7dca44a60 --- /dev/null +++ b/java/com/android/dialer/calllog/database/AnnotatedCallLog.java @@ -0,0 +1,53 @@ +/* + * 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.calllog.database; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.support.annotation.WorkerThread; +import com.android.dialer.common.Assert; + +/** Static methods and constants for interacting with the annotated call log table. */ +public final class AnnotatedCallLog { + + private static final String DATABASE_NAME = "annotated_call_log.db"; + + public static final String TABLE_NAME = "AnnotatedCallLog"; + + /** Column names for the annotated call log table. */ + public static final class Columns { + public static final String ID = "_id"; + public static final String TIMESTAMP = "timestamp"; + public static final String CONTACT_NAME = "contact_name"; + } + + private AnnotatedCallLog() {} + + @WorkerThread + public static SQLiteDatabase getWritableDatabase(Context appContext) { + Assert.isWorkerThread(); + + return new AnnotatedCallLogDatabaseHelper(appContext, DATABASE_NAME).getWritableDatabase(); + } + + @WorkerThread + public static SQLiteDatabase getReadableDatabase(Context appContext) { + Assert.isWorkerThread(); + + return new AnnotatedCallLogDatabaseHelper(appContext, DATABASE_NAME).getReadableDatabase(); + } +} diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java deleted file mode 100644 index a9c0d36b0..000000000 --- a/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * 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.calllog.database; - -import android.annotation.TargetApi; -import android.content.ContentProvider; -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.OperationApplicationException; -import android.content.UriMatcher; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteQueryBuilder; -import android.net.Uri; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract; -import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; -import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.CoalescedAnnotatedCallLog; -import com.android.dialer.common.Assert; -import com.android.dialer.common.LogUtil; -import java.util.ArrayList; - -/** {@link ContentProvider} for the annotated call log. */ -public class AnnotatedCallLogContentProvider extends ContentProvider { - - 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; - - private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - - static { - uriMatcher.addURI( - AnnotatedCallLogContract.AUTHORITY, AnnotatedCallLog.TABLE, ANNOTATED_CALL_LOG_TABLE_CODE); - uriMatcher.addURI( - AnnotatedCallLogContract.AUTHORITY, - AnnotatedCallLog.TABLE + "/#", - ANNOTATED_CALL_LOG_TABLE_ID_CODE); - uriMatcher.addURI( - AnnotatedCallLogContract.AUTHORITY, - CoalescedAnnotatedCallLog.TABLE, - COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE); - } - - private AnnotatedCallLogDatabaseHelper databaseHelper; - private Coalescer coalescer; - - private final ThreadLocal<Boolean> applyingBatch = new ThreadLocal<>(); - - /** Ensures that only a single notification is generated from {@link #applyBatch(ArrayList)}. */ - private boolean isApplyingBatch() { - return applyingBatch.get() != null && applyingBatch.get(); - } - - @Override - public boolean onCreate() { - databaseHelper = new AnnotatedCallLogDatabaseHelper(getContext()); - coalescer = CallLogDatabaseComponent.get(getContext()).coalescer(); - return true; - } - - @TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources - @Nullable - @Override - public Cursor query( - @NonNull Uri uri, - @Nullable String[] projection, - @Nullable String selection, - @Nullable String[] selectionArgs, - @Nullable String sortOrder) { - SQLiteDatabase db = databaseHelper.getReadableDatabase(); - SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); - queryBuilder.setTables(AnnotatedCallLog.TABLE); - int match = uriMatcher.match(uri); - switch (match) { - case ANNOTATED_CALL_LOG_TABLE_ID_CODE: - queryBuilder.appendWhere(AnnotatedCallLog._ID + "=" + ContentUris.parseId(uri)); - // fall through - case ANNOTATED_CALL_LOG_TABLE_CODE: - Cursor cursor = - queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); - if (cursor != null) { - cursor.setNotificationUri( - getContext().getContentResolver(), AnnotatedCallLog.CONTENT_URI); - } else { - LogUtil.w("AnnotatedCallLogContentProvider.query", "cursor was null"); - } - return cursor; - case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE: - Assert.checkArgument(projection == null, "projection not supported for coalesced call log"); - Assert.checkArgument(selection == null, "selection not supported for coalesced call log"); - Assert.checkArgument( - selectionArgs == null, "selection args not supported for coalesced call log"); - Assert.checkArgument(sortOrder == null, "sort order not supported for coalesced call log"); - try (Cursor allAnnotatedCallLogRows = - queryBuilder.query( - db, null, null, null, null, null, AnnotatedCallLog.TIMESTAMP + " DESC")) { - Cursor coalescedRows = coalescer.coalesce(allAnnotatedCallLogRows); - coalescedRows.setNotificationUri( - getContext().getContentResolver(), CoalescedAnnotatedCallLog.CONTENT_URI); - return coalescedRows; - } - default: - throw new IllegalArgumentException("Unknown uri: " + uri); - } - } - - @Nullable - @Override - public String getType(@NonNull Uri uri) { - return AnnotatedCallLog.CONTENT_ITEM_TYPE; - } - - @Nullable - @Override - public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { - // Javadoc states values is not nullable, even though it is annotated as such (b/38123194)! - Assert.checkArgument(values != null); - - SQLiteDatabase database = databaseHelper.getWritableDatabase(); - int match = uriMatcher.match(uri); - switch (match) { - case ANNOTATED_CALL_LOG_TABLE_CODE: - Assert.checkArgument( - values.get(AnnotatedCallLog._ID) != null, "You must specify an _ID when inserting"); - break; - case ANNOTATED_CALL_LOG_TABLE_ID_CODE: - Long idFromUri = ContentUris.parseId(uri); - Long idFromValues = values.getAsLong(AnnotatedCallLog._ID); - Assert.checkArgument( - idFromValues == null || idFromValues.equals(idFromUri), - "_ID from values %d does not match ID from URI: %s", - idFromValues, - uri); - if (idFromValues == null) { - values.put(AnnotatedCallLog._ID, idFromUri); - } - break; - case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE: - throw new UnsupportedOperationException("coalesced call log does not support inserting"); - default: - throw new IllegalArgumentException("Unknown uri: " + uri); - } - long id = database.insert(AnnotatedCallLog.TABLE, null, values); - if (id < 0) { - LogUtil.w( - "AnnotatedCallLogContentProvider.insert", - "error inserting row with id: %d", - values.get(AnnotatedCallLog._ID)); - return null; - } - Uri insertedUri = ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id); - if (!isApplyingBatch()) { - notifyChange(insertedUri); - } - return insertedUri; - } - - @Override - public int delete( - @NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { - SQLiteDatabase database = databaseHelper.getWritableDatabase(); - final int match = uriMatcher.match(uri); - switch (match) { - case ANNOTATED_CALL_LOG_TABLE_CODE: - break; - case ANNOTATED_CALL_LOG_TABLE_ID_CODE: - Assert.checkArgument(selection == null, "Do not specify selection when deleting by ID"); - Assert.checkArgument( - selectionArgs == null, "Do not specify selection args when deleting by ID"); - long id = ContentUris.parseId(uri); - Assert.checkArgument(id != -1, "error parsing id from uri %s", uri); - selection = getSelectionWithId(id); - break; - case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE: - throw new UnsupportedOperationException("coalesced call log does not support deleting"); - default: - throw new IllegalArgumentException("Unknown uri: " + uri); - } - int rows = database.delete(AnnotatedCallLog.TABLE, selection, selectionArgs); - if (rows > 0) { - if (!isApplyingBatch()) { - notifyChange(uri); - } - } else { - LogUtil.w("AnnotatedCallLogContentProvider.delete", "no rows deleted"); - } - return rows; - } - - @Override - public int update( - @NonNull Uri uri, - @Nullable ContentValues values, - @Nullable String selection, - @Nullable String[] selectionArgs) { - // Javadoc states values is not nullable, even though it is annotated as such (b/38123194)! - Assert.checkArgument(values != null); - - SQLiteDatabase database = databaseHelper.getWritableDatabase(); - int match = uriMatcher.match(uri); - switch (match) { - case ANNOTATED_CALL_LOG_TABLE_CODE: - break; - case ANNOTATED_CALL_LOG_TABLE_ID_CODE: - Assert.checkArgument( - !values.containsKey(AnnotatedCallLog._ID), "Do not specify _ID when updating by ID"); - Assert.checkArgument(selection == null, "Do not specify selection when updating by ID"); - Assert.checkArgument( - selectionArgs == null, "Do not specify selection args when updating by ID"); - selection = getSelectionWithId(ContentUris.parseId(uri)); - break; - case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE: - throw new UnsupportedOperationException("coalesced call log does not support updating"); - default: - throw new IllegalArgumentException("Unknown uri: " + uri); - } - int rows = database.update(AnnotatedCallLog.TABLE, values, selection, selectionArgs); - if (rows > 0) { - if (!isApplyingBatch()) { - notifyChange(uri); - } - } else { - LogUtil.w("AnnotatedCallLogContentProvider.update", "no rows updated"); - } - return rows; - } - - /** - * {@inheritDoc} - * - * <p>Note: When applyBatch is used with the AnnotatedCallLog, only a single notification for the - * content URI is generated, not individual notifications for each affected URI. - */ - @NonNull - @Override - public ContentProviderResult[] applyBatch(@NonNull ArrayList<ContentProviderOperation> operations) - throws OperationApplicationException { - ContentProviderResult[] results = new ContentProviderResult[operations.size()]; - if (operations.isEmpty()) { - return results; - } - - SQLiteDatabase database = databaseHelper.getWritableDatabase(); - try { - applyingBatch.set(true); - database.beginTransaction(); - for (int i = 0; i < operations.size(); i++) { - ContentProviderOperation operation = operations.get(i); - int match = uriMatcher.match(operation.getUri()); - switch (match) { - case ANNOTATED_CALL_LOG_TABLE_CODE: - case ANNOTATED_CALL_LOG_TABLE_ID_CODE: - // These are allowed values, continue. - break; - case COALESCED_ANNOTATED_CALL_LOG_TABLE_CODE: - throw new UnsupportedOperationException( - "coalesced call log does not support applyBatch"); - default: - throw new IllegalArgumentException("Unknown uri: " + operation.getUri()); - } - ContentProviderResult result = operation.apply(this, results, i); - if (operations.get(i).isInsert()) { - if (result.uri == null) { - throw new OperationApplicationException("error inserting row"); - } - } else if (result.count == 0) { - throw new OperationApplicationException("error updating or deleting rows"); - } - results[i] = result; - } - database.setTransactionSuccessful(); - } finally { - applyingBatch.set(false); - database.endTransaction(); - } - notifyChange(AnnotatedCallLog.CONTENT_URI); - return results; - } - - private String getSelectionWithId(long id) { - return AnnotatedCallLog._ID + "=" + id; - } - - private void notifyChange(Uri uri) { - getContext().getContentResolver().notifyChange(uri, null); - // Any time the annotated call log changes, we need to also notify observers of the - // CoalescedAnnotatedCallLog, since that is just a massaged in-memory view of the real annotated - // call log table. - getContext().getContentResolver().notifyChange(CoalescedAnnotatedCallLog.CONTENT_URI, null); - } -} diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java index 3cca639ff..7b28e5505 100644 --- a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java +++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java @@ -16,25 +16,28 @@ package com.android.dialer.calllog.database; +import static com.android.dialer.calllog.database.AnnotatedCallLog.Columns.CONTACT_NAME; +import static com.android.dialer.calllog.database.AnnotatedCallLog.Columns.ID; +import static com.android.dialer.calllog.database.AnnotatedCallLog.Columns.TIMESTAMP; + import android.content.Context; 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; /** {@link SQLiteOpenHelper} for the AnnotatedCallLog database. */ class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper { - AnnotatedCallLogDatabaseHelper(Context appContext) { - super(appContext, "annotated_call_log.db", null, 1); + AnnotatedCallLogDatabaseHelper(Context appContext, String databaseName) { + super(appContext, databaseName, null, 1); } private static final String CREATE_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("create table if not exists " + AnnotatedCallLog.TABLE_NAME + " (") + .append(ID + " integer primary key, ") + .append(TIMESTAMP + " integer, ") + .append(CONTACT_NAME + " string") .append(");") .toString(); diff --git a/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java b/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java deleted file mode 100644 index ede46911c..000000000 --- a/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.calllog.database; - -import android.content.Context; -import com.android.dialer.inject.HasRootComponent; -import dagger.Subcomponent; - -/** Dagger component for database package. */ -@Subcomponent -public abstract class CallLogDatabaseComponent { - - public abstract Coalescer coalescer(); - - public abstract MutationApplier mutationApplier(); - - public static CallLogDatabaseComponent get(Context context) { - return ((CallLogDatabaseComponent.HasComponent) - ((HasRootComponent) context.getApplicationContext()).component()) - .callLogDatabaseComponent(); - } - - /** Used to refer to the root application component. */ - public interface HasComponent { - CallLogDatabaseComponent callLogDatabaseComponent(); - } -} diff --git a/java/com/android/dialer/calllog/database/CallLogMutations.java b/java/com/android/dialer/calllog/database/CallLogMutations.java new file mode 100644 index 000000000..ec020c6af --- /dev/null +++ b/java/com/android/dialer/calllog/database/CallLogMutations.java @@ -0,0 +1,58 @@ +/* + * 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.calllog.database; + +import android.content.ContentValues; +import android.database.sqlite.SQLiteDatabase; +import android.support.annotation.WorkerThread; +import android.util.ArrayMap; +import android.util.ArraySet; +import com.android.dialer.common.Assert; + +/** A collection of mutations to the annotated call log. */ +public final class CallLogMutations { + + private final ArrayMap<Integer, ContentValues> inserts = new ArrayMap<>(); + private final ArrayMap<Integer, ContentValues> updates = new ArrayMap<>(); + private final ArraySet<Integer> deletes = new ArraySet<>(); + + /** @param contentValues an entire row not including the ID */ + public void insert(int id, ContentValues contentValues) { + inserts.put(id, contentValues); + } + + /** @param contentValues the specific columns to update, not including the ID. */ + public void update(int id, ContentValues contentValues) { + // TODO: Consider merging automatically. + updates.put(id, contentValues); + } + + public void delete(int id) { + deletes.add(id); + } + + public boolean isEmpty() { + return inserts.isEmpty() && updates.isEmpty() && deletes.isEmpty(); + } + + @WorkerThread + public void applyToDatabase(SQLiteDatabase writableDatabase) { + Assert.isWorkerThread(); + + // TODO: Implementation. + } +} diff --git a/java/com/android/dialer/calllog/database/Coalescer.java b/java/com/android/dialer/calllog/database/Coalescer.java deleted file mode 100644 index e3dfb7ece..000000000 --- a/java/com/android/dialer/calllog/database/Coalescer.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.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.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 java.util.ArrayList; -import java.util.List; -import java.util.Map; -import javax.inject.Inject; - -/** - * Coalesces call log rows by combining some adjacent rows. - * - * <p>Applies the business which logic which determines which adjacent rows should be coalasced, and - * then delegates to each data source to determine how individual columns should be aggregated. - */ -public class Coalescer { - - private final DataSources dataSources; - - @Inject - Coalescer(DataSources dataSources) { - this.dataSources = dataSources; - } - - /** - * Reads the entire {@link AnnotatedCallLog} database into memory from the provided {@code - * allAnnotatedCallLog} parameter and then builds and returns a new {@link MatrixCursor} which is - * the result of combining adjacent rows which should be collapsed for display purposes. - * - * @param allAnnotatedCallLogRowsSortedByTimestampDesc all {@link AnnotatedCallLog} rows, sorted - * by timestamp descending - * @return a new {@link MatrixCursor} containing the {@link CoalescedAnnotatedCallLog} rows to - * display - */ - @WorkerThread - @NonNull - Cursor coalesce(@NonNull Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) { - Assert.isWorkerThread(); - - // Note: This method relies on rowsShouldBeCombined to determine which rows should be combined, - // but delegates to data sources to actually aggregate column values. - - MatrixCursor allCoalescedRowsMatrixCursor = - new MatrixCursor( - CoalescedAnnotatedCallLog.ALL_COLUMNS, - Assert.isNotNull(allAnnotatedCallLogRowsSortedByTimestampDesc).getCount()); - - if (allAnnotatedCallLogRowsSortedByTimestampDesc.moveToFirst()) { - int coalescedRowId = 0; - - List<ContentValues> currentRowGroup = new ArrayList<>(); - - do { - ContentValues currentRow = new ContentValues(); - DatabaseUtils.cursorRowToContentValues( - allAnnotatedCallLogRowsSortedByTimestampDesc, currentRow); - - if (currentRowGroup.isEmpty()) { - currentRowGroup.add(currentRow); - continue; - } - - ContentValues previousRow = currentRowGroup.get(currentRowGroup.size() - 1); - - if (!rowsShouldBeCombined(previousRow, currentRow)) { - ContentValues coalescedRow = coalesceRowsForAllDataSources(currentRowGroup); - coalescedRow.put(CoalescedAnnotatedCallLog.NUMBER_CALLS, currentRowGroup.size()); - addContentValuesToMatrixCursor( - coalescedRow, allCoalescedRowsMatrixCursor, coalescedRowId++); - currentRowGroup.clear(); - } - currentRowGroup.add(currentRow); - } while (allAnnotatedCallLogRowsSortedByTimestampDesc.moveToNext()); - - // Deal with leftover rows. - ContentValues coalescedRow = coalesceRowsForAllDataSources(currentRowGroup); - coalescedRow.put(CoalescedAnnotatedCallLog.NUMBER_CALLS, currentRowGroup.size()); - addContentValuesToMatrixCursor(coalescedRow, allCoalescedRowsMatrixCursor, coalescedRowId); - } - return allCoalescedRowsMatrixCursor; - } - - /** - * @param row1 a row from {@link AnnotatedCallLog} - * @param row2 a row from {@link AnnotatedCallLog} - */ - private static boolean rowsShouldBeCombined(ContentValues row1, ContentValues row2) { - // TODO: Real implementation. - return row1.get(AnnotatedCallLog.TIMESTAMP).equals(row2.get(AnnotatedCallLog.TIMESTAMP)); - } - - /** - * Delegates to data sources to aggregate individual columns to create a new coalesced row. - * - * @param individualRows {@link AnnotatedCallLog} rows sorted by timestamp descending - * @return a {@link CoalescedAnnotatedCallLog} row - */ - private ContentValues coalesceRowsForAllDataSources(List<ContentValues> individualRows) { - ContentValues coalescedValues = new ContentValues(); - for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { - coalescedValues.putAll(dataSource.coalesce(individualRows)); - } - return coalescedValues; - } - - /** - * @param contentValues a {@link CoalescedAnnotatedCallLog} row - * @param matrixCursor represents {@link CoalescedAnnotatedCallLog} - */ - private static void addContentValuesToMatrixCursor( - ContentValues contentValues, MatrixCursor matrixCursor, int rowId) { - MatrixCursor.RowBuilder rowBuilder = matrixCursor.newRow(); - rowBuilder.add(CoalescedAnnotatedCallLog._ID, rowId); - for (Map.Entry<String, Object> entry : contentValues.valueSet()) { - rowBuilder.add(entry.getKey(), entry.getValue()); - } - } -} diff --git a/java/com/android/dialer/calllog/database/MutationApplier.java b/java/com/android/dialer/calllog/database/MutationApplier.java deleted file mode 100644 index 21c8a507d..000000000 --- a/java/com/android/dialer/calllog/database/MutationApplier.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.calllog.database; - -import android.content.ContentProviderOperation; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.Context; -import android.content.OperationApplicationException; -import android.os.RemoteException; -import android.support.annotation.WorkerThread; -import android.text.TextUtils; -import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract; -import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; -import com.android.dialer.calllog.datasources.CallLogMutations; -import com.android.dialer.common.Assert; -import com.android.dialer.common.LogUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Map.Entry; -import javax.inject.Inject; - -/** Applies {@link CallLogMutations} to the annotated call log. */ -public class MutationApplier { - - @Inject - MutationApplier() {} - - /** Applies the provided {@link CallLogMutations} to the annotated call log. */ - @WorkerThread - public void applyToDatabase(CallLogMutations mutations, Context appContext) - throws RemoteException, OperationApplicationException { - Assert.isWorkerThread(); - - if (mutations.isEmpty()) { - return; - } - - ArrayList<ContentProviderOperation> operations = new ArrayList<>(); - - if (!mutations.getInserts().isEmpty()) { - LogUtil.i( - "CallLogMutations.applyToDatabase", "inserting %d rows", mutations.getInserts().size()); - for (Entry<Long, ContentValues> entry : mutations.getInserts().entrySet()) { - long id = entry.getKey(); - ContentValues contentValues = entry.getValue(); - operations.add( - ContentProviderOperation.newInsert( - ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id)) - .withValues(contentValues) - .build()); - } - } - - if (!mutations.getUpdates().isEmpty()) { - LogUtil.i( - "CallLogMutations.applyToDatabase", "updating %d rows", mutations.getUpdates().size()); - for (Entry<Long, ContentValues> entry : mutations.getUpdates().entrySet()) { - long id = entry.getKey(); - ContentValues contentValues = entry.getValue(); - operations.add( - ContentProviderOperation.newUpdate( - ContentUris.withAppendedId(AnnotatedCallLog.CONTENT_URI, id)) - .withValues(contentValues) - .build()); - } - } - - if (!mutations.getDeletes().isEmpty()) { - LogUtil.i( - "CallLogMutations.applyToDatabase", "deleting %d rows", mutations.getDeletes().size()); - String[] questionMarks = new String[mutations.getDeletes().size()]; - Arrays.fill(questionMarks, "?"); - - String whereClause = - (AnnotatedCallLog._ID + " in (") + TextUtils.join(",", questionMarks) + ")"; - - String[] whereArgs = new String[mutations.getDeletes().size()]; - int i = 0; - for (long id : mutations.getDeletes()) { - whereArgs[i++] = String.valueOf(id); - } - - operations.add( - ContentProviderOperation.newDelete(AnnotatedCallLog.CONTENT_URI) - .withSelection(whereClause, whereArgs) - .build()); - } - - appContext.getContentResolver().applyBatch(AnnotatedCallLogContract.AUTHORITY, operations); - } -} diff --git a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java b/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java deleted file mode 100644 index 8b3b0a852..000000000 --- a/java/com/android/dialer/calllog/database/contract/AnnotatedCallLogContract.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.calllog.database.contract; - -import android.net.Uri; -import android.provider.BaseColumns; -import com.android.dialer.constants.Constants; -import java.util.Arrays; - -/** Contract for the AnnotatedCallLog content provider. */ -public class AnnotatedCallLogContract { - public static final String AUTHORITY = Constants.get().getAnnotatedCallLogProviderAuthority(); - - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); - - /** - * Columns shared by {@link AnnotatedCallLog} and {@link CoalescedAnnotatedCallLog}. - * - * <p>When adding columns be sure to update {@link #ALL_COMMON_COLUMNS}. - */ - interface CommonColumns extends BaseColumns { - - /** - * Timestamp of the entry, in milliseconds. - * - * <p>Type: INTEGER (long) - */ - String TIMESTAMP = "timestamp"; - - /** - * Name to display for the entry. - * - * <p>Type: TEXT - */ - String CONTACT_NAME = "contact_name"; - - String[] ALL_COMMON_COLUMNS = new String[] {_ID, TIMESTAMP, CONTACT_NAME}; - } - - /** - * AnnotatedCallLog table. - * - * <p>This contains all of the non-coalesced call log entries. - */ - public static final class AnnotatedCallLog implements CommonColumns { - - public static final String TABLE = "AnnotatedCallLog"; - - /** The content URI for this table. */ - public static final Uri CONTENT_URI = - Uri.withAppendedPath(AnnotatedCallLogContract.CONTENT_URI, TABLE); - - /** 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"; - } - - /** - * Coalesced view of the AnnotatedCallLog table. - * - * <p>This is an in-memory view of the {@link AnnotatedCallLog} with some adjacent entries - * collapsed. - * - * <p>When adding columns be sure to update {@link #COLUMNS_ONLY_IN_COALESCED_CALL_LOG}. - */ - public static final class CoalescedAnnotatedCallLog implements CommonColumns { - - public static final String TABLE = "CoalescedAnnotatedCallLog"; - - /** The content URI for this table. */ - public static final Uri CONTENT_URI = - Uri.withAppendedPath(AnnotatedCallLogContract.CONTENT_URI, TABLE); - - /** The MIME type of a {@link android.content.ContentProvider#getType(Uri)} single entry. */ - public static final String CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/coalesced_annotated_call_log"; - - /** - * Number of AnnotatedCallLog rows represented by this CoalescedAnnotatedCallLog row. - * - * <p>Type: INTEGER - */ - public static final String NUMBER_CALLS = "number_calls"; - - /** - * 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}; - - /** All columns in the {@link CoalescedAnnotatedCallLog}. */ - public static final String[] ALL_COLUMNS = - concat(ALL_COMMON_COLUMNS, COLUMNS_ONLY_IN_COALESCED_CALL_LOG); - } - - private static String[] concat(String[] first, String[] second) { - String[] result = Arrays.copyOf(first, first.length + second.length); - System.arraycopy(second, 0, result, first.length, second.length); - return result; - } -} |