From 2482c0fc58034e01efb7ce7e67408e248f028c95 Mon Sep 17 00:00:00 2001 From: zachh Date: Tue, 20 Mar 2018 17:08:52 -0700 Subject: Added "clearData" to CallLogDataSource and PhoneLookup interfaces. This is necessary to disable the call log framework via flags. This isn't yet called anywhere. Bug: 74821995 Test: unit PiperOrigin-RevId: 189838957 Change-Id: I926c02c41151528eabc208c874acbfe7897a2f93 --- java/com/android/dialer/calllog/CallLogModule.java | 3 +- .../database/AnnotatedCallLogContentProvider.java | 9 +--- .../database/AnnotatedCallLogDatabaseHelper.java | 35 +++++++++++++-- .../calllog/database/AnnotatedCallLogMaxRows.java | 22 ++++++++++ .../calllog/database/CallLogDatabaseComponent.java | 2 + .../calllog/database/CallLogDatabaseModule.java | 36 ++++++++++++++++ .../calllog/datasources/CallLogDataSource.java | 7 +++ .../phonelookup/PhoneLookupDataSource.java | 19 +++++++- .../systemcalllog/SystemCallLogDataSource.java | 50 +++++++++++++++------- .../datasources/voicemail/VoicemailDataSource.java | 5 +++ 10 files changed, 161 insertions(+), 27 deletions(-) create mode 100644 java/com/android/dialer/calllog/database/AnnotatedCallLogMaxRows.java create mode 100644 java/com/android/dialer/calllog/database/CallLogDatabaseModule.java (limited to 'java/com/android/dialer/calllog') diff --git a/java/com/android/dialer/calllog/CallLogModule.java b/java/com/android/dialer/calllog/CallLogModule.java index 9dd9a794d..56572705d 100644 --- a/java/com/android/dialer/calllog/CallLogModule.java +++ b/java/com/android/dialer/calllog/CallLogModule.java @@ -16,6 +16,7 @@ package com.android.dialer.calllog; +import com.android.dialer.calllog.database.CallLogDatabaseModule; import com.android.dialer.calllog.datasources.CallLogDataSource; import com.android.dialer.calllog.datasources.DataSources; import com.android.dialer.calllog.datasources.phonelookup.PhoneLookupDataSource; @@ -26,7 +27,7 @@ import dagger.Module; import dagger.Provides; /** Dagger module which satisfies call log dependencies. */ -@Module +@Module(includes = CallLogDatabaseModule.class) public abstract class CallLogModule { @Provides diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java index 69722731e..9a80af2f7 100644 --- a/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java +++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogContentProvider.java @@ -45,12 +45,7 @@ import java.util.Arrays; /** {@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; @@ -87,7 +82,7 @@ public class AnnotatedCallLogContentProvider extends ContentProvider { @Override public boolean onCreate() { - databaseHelper = new AnnotatedCallLogDatabaseHelper(getContext(), MAX_ROWS); + databaseHelper = CallLogDatabaseComponent.get(getContext()).annotatedCallLogDatabaseHelper(); // Note: As this method is called before Application#onCreate, we must *not* initialize objects // that require preparation work done in Application#onCreate. diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java index 3b67ff2d7..7df83b3d1 100644 --- a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java +++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java @@ -22,15 +22,34 @@ import android.database.sqlite.SQLiteOpenHelper; import android.provider.CallLog.Calls; import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; +import com.android.dialer.inject.ApplicationContext; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; import java.util.Locale; +import javax.inject.Inject; +import javax.inject.Singleton; /** {@link SQLiteOpenHelper} for the AnnotatedCallLog database. */ -class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper { +@Singleton +public class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper { + + private static final String FILENAME = "annotated_call_log.db"; + + private final Context appContext; private final int maxRows; + private final ListeningExecutorService backgroundExecutor; + + @Inject + public AnnotatedCallLogDatabaseHelper( + @ApplicationContext Context appContext, + @AnnotatedCallLogMaxRows int maxRows, + @BackgroundExecutor ListeningExecutorService backgroundExecutor) { + super(appContext, FILENAME, null, 1); - AnnotatedCallLogDatabaseHelper(Context appContext, int maxRows) { - super(appContext, "annotated_call_log.db", null, 1); + this.appContext = appContext; this.maxRows = maxRows; + this.backgroundExecutor = backgroundExecutor; } private static final String CREATE_TABLE_SQL = @@ -127,4 +146,14 @@ class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {} + + /** Closes the database and deletes it. */ + public ListenableFuture delete() { + return backgroundExecutor.submit( + () -> { + close(); + appContext.deleteDatabase(FILENAME); + return null; + }); + } } diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogMaxRows.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogMaxRows.java new file mode 100644 index 000000000..5542d661f --- /dev/null +++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogMaxRows.java @@ -0,0 +1,22 @@ +/* + * 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.database; + +import javax.inject.Qualifier; + +/** Annotation for the max number of rows in the AnnotatedCallLog. */ +@Qualifier +public @interface AnnotatedCallLogMaxRows {} diff --git a/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java b/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java index 991237449..09e291eb0 100644 --- a/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java +++ b/java/com/android/dialer/calllog/database/CallLogDatabaseComponent.java @@ -25,6 +25,8 @@ public abstract class CallLogDatabaseComponent { public abstract Coalescer coalescer(); + public abstract AnnotatedCallLogDatabaseHelper annotatedCallLogDatabaseHelper(); + public static CallLogDatabaseComponent get(Context context) { return ((CallLogDatabaseComponent.HasComponent) ((HasRootComponent) context.getApplicationContext()).component()) diff --git a/java/com/android/dialer/calllog/database/CallLogDatabaseModule.java b/java/com/android/dialer/calllog/database/CallLogDatabaseModule.java new file mode 100644 index 000000000..eef3fb54e --- /dev/null +++ b/java/com/android/dialer/calllog/database/CallLogDatabaseModule.java @@ -0,0 +1,36 @@ +/* + * 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.database; + +import dagger.Module; +import dagger.Provides; + +/** Binds database dependencies. */ +@Module +public class CallLogDatabaseModule { + + @Provides + @AnnotatedCallLogMaxRows + static int provideMaxRows() { + /* + * 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. + */ + return 999; + } +} diff --git a/java/com/android/dialer/calllog/datasources/CallLogDataSource.java b/java/com/android/dialer/calllog/datasources/CallLogDataSource.java index 03a571675..fa3b6a9df 100644 --- a/java/com/android/dialer/calllog/datasources/CallLogDataSource.java +++ b/java/com/android/dialer/calllog/datasources/CallLogDataSource.java @@ -108,4 +108,11 @@ public interface CallLogDataSource { @MainThread void unregisterContentObservers(Context appContext); + + /** + * Clear any data written by this data source. This is called when the new call log framework has + * been disabled (because for example there was a problem with it). + */ + @MainThread + ListenableFuture clearData(); } diff --git a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java index 40b0090b9..615a457e3 100644 --- a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java +++ b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java @@ -40,6 +40,7 @@ import com.android.dialer.common.concurrent.Annotations.LightweightExecutor; import com.android.dialer.phonelookup.PhoneLookup; import com.android.dialer.phonelookup.PhoneLookupInfo; import com.android.dialer.phonelookup.composite.CompositePhoneLookup; +import com.android.dialer.phonelookup.database.PhoneLookupHistoryDatabaseHelper; import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract; import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory; import com.google.common.collect.ImmutableMap; @@ -48,6 +49,7 @@ import com.google.common.collect.Maps; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; import com.google.protobuf.InvalidProtocolBufferException; import java.util.ArrayList; import java.util.Arrays; @@ -85,14 +87,18 @@ public final class PhoneLookupDataSource implements CallLogDataSource { */ private final Set phoneLookupHistoryRowsToDelete = new ArraySet<>(); + private final PhoneLookupHistoryDatabaseHelper phoneLookupHistoryDatabaseHelper; + @Inject PhoneLookupDataSource( CompositePhoneLookup compositePhoneLookup, @BackgroundExecutor ListeningExecutorService backgroundExecutorService, - @LightweightExecutor ListeningExecutorService lightweightExecutorService) { + @LightweightExecutor ListeningExecutorService lightweightExecutorService, + PhoneLookupHistoryDatabaseHelper phoneLookupHistoryDatabaseHelper) { this.compositePhoneLookup = compositePhoneLookup; this.backgroundExecutorService = backgroundExecutorService; this.lightweightExecutorService = lightweightExecutorService; + this.phoneLookupHistoryDatabaseHelper = phoneLookupHistoryDatabaseHelper; } @Override @@ -299,6 +305,17 @@ public final class PhoneLookupDataSource implements CallLogDataSource { compositePhoneLookup.unregisterContentObservers(appContext); } + @Override + public ListenableFuture clearData() { + ListenableFuture clearDataFuture = compositePhoneLookup.clearData(); + ListenableFuture deleteDatabaseFuture = phoneLookupHistoryDatabaseHelper.delete(); + + return Futures.transform( + Futures.allAsList(clearDataFuture, deleteDatabaseFuture), + unused -> null, + MoreExecutors.directExecutor()); + } + private static ImmutableSet queryDistinctDialerPhoneNumbersFromAnnotatedCallLog(Context appContext) { ImmutableSet.Builder numbers = ImmutableSet.builder(); diff --git a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java index 3c34fa6a5..e07996177 100644 --- a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java +++ b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java @@ -20,6 +20,7 @@ import android.Manifest.permission; import android.annotation.TargetApi; import android.content.ContentValues; import android.content.Context; +import android.content.SharedPreferences; import android.database.Cursor; import android.os.Build; import android.os.Build.VERSION; @@ -40,6 +41,7 @@ import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.util.ArraySet; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.calllog.database.AnnotatedCallLogDatabaseHelper; import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; import com.android.dialer.calllog.datasources.CallLogDataSource; import com.android.dialer.calllog.datasources.CallLogMutations; @@ -51,13 +53,15 @@ import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; import com.android.dialer.compat.android.provider.VoicemailCompat; import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil; -import com.android.dialer.storage.StorageComponent; +import com.android.dialer.storage.Unencrypted; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.theme.R; import com.android.dialer.util.PermissionsUtil; import com.google.common.collect.Iterables; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; import com.google.i18n.phonenumbers.PhoneNumberUtil; import java.util.ArrayList; import java.util.Arrays; @@ -77,15 +81,21 @@ public class SystemCallLogDataSource implements CallLogDataSource { private final ListeningExecutorService backgroundExecutorService; private final MarkDirtyObserver markDirtyObserver; + private final SharedPreferences sharedPreferences; + private final AnnotatedCallLogDatabaseHelper annotatedCallLogDatabaseHelper; @Nullable private Long lastTimestampProcessed; @Inject SystemCallLogDataSource( @BackgroundExecutor ListeningExecutorService backgroundExecutorService, - MarkDirtyObserver markDirtyObserver) { + MarkDirtyObserver markDirtyObserver, + @Unencrypted SharedPreferences sharedPreferences, + AnnotatedCallLogDatabaseHelper annotatedCallLogDatabaseHelper) { this.backgroundExecutorService = backgroundExecutorService; this.markDirtyObserver = markDirtyObserver; + this.sharedPreferences = sharedPreferences; + this.annotatedCallLogDatabaseHelper = annotatedCallLogDatabaseHelper; } @MainThread @@ -124,9 +134,25 @@ public class SystemCallLogDataSource implements CallLogDataSource { appContext.getContentResolver().unregisterContentObserver(markDirtyObserver); } + @Override + public ListenableFuture clearData() { + ListenableFuture deleteSharedPref = + backgroundExecutorService.submit( + () -> { + sharedPreferences.edit().remove(PREF_LAST_TIMESTAMP_PROCESSED).apply(); + return null; + }); + + // TODO(zachh): Test re-enabling after deleting database like this. + return Futures.transform( + Futures.allAsList(deleteSharedPref, annotatedCallLogDatabaseHelper.delete()), + unused -> null, + MoreExecutors.directExecutor()); + } + @Override public ListenableFuture isDirty(Context appContext) { - return backgroundExecutorService.submit(() -> isDirtyInternal(appContext)); + return backgroundExecutorService.submit(this::isDirtyInternal); } @Override @@ -136,11 +162,11 @@ public class SystemCallLogDataSource implements CallLogDataSource { @Override public ListenableFuture onSuccessfulFill(Context appContext) { - return backgroundExecutorService.submit(() -> onSuccessfulFillInternal(appContext)); + return backgroundExecutorService.submit(this::onSuccessfulFillInternal); } @WorkerThread - private boolean isDirtyInternal(Context appContext) { + private boolean isDirtyInternal() { Assert.isWorkerThread(); /* @@ -151,9 +177,7 @@ public class SystemCallLogDataSource implements CallLogDataSource { * * Just return false unless the table has never been written to. */ - return !StorageComponent.get(appContext) - .unencryptedSharedPrefs() - .contains(PREF_LAST_TIMESTAMP_PROCESSED); + return !sharedPreferences.contains(PREF_LAST_TIMESTAMP_PROCESSED); } @WorkerThread @@ -183,11 +207,10 @@ public class SystemCallLogDataSource implements CallLogDataSource { } @WorkerThread - private Void onSuccessfulFillInternal(Context appContext) { + private Void onSuccessfulFillInternal() { // If a fill operation was a no-op, lastTimestampProcessed could still be null. if (lastTimestampProcessed != null) { - StorageComponent.get(appContext) - .unencryptedSharedPrefs() + sharedPreferences .edit() .putLong(PREF_LAST_TIMESTAMP_PROCESSED, lastTimestampProcessed) .apply(); @@ -232,10 +255,7 @@ public class SystemCallLogDataSource implements CallLogDataSource { @TargetApi(Build.VERSION_CODES.M) // Uses try-with-resources private void handleInsertsAndUpdates( Context appContext, CallLogMutations mutations, Set existingAnnotatedCallLogIds) { - long previousTimestampProcessed = - StorageComponent.get(appContext) - .unencryptedSharedPrefs() - .getLong(PREF_LAST_TIMESTAMP_PROCESSED, 0L); + long previousTimestampProcessed = sharedPreferences.getLong(PREF_LAST_TIMESTAMP_PROCESSED, 0L); DialerPhoneNumberUtil dialerPhoneNumberUtil = new DialerPhoneNumberUtil(PhoneNumberUtil.getInstance()); diff --git a/java/com/android/dialer/calllog/datasources/voicemail/VoicemailDataSource.java b/java/com/android/dialer/calllog/datasources/voicemail/VoicemailDataSource.java index 86f3d47ce..75c05139d 100644 --- a/java/com/android/dialer/calllog/datasources/voicemail/VoicemailDataSource.java +++ b/java/com/android/dialer/calllog/datasources/voicemail/VoicemailDataSource.java @@ -111,4 +111,9 @@ public class VoicemailDataSource implements CallLogDataSource { @Override public void unregisterContentObservers(Context appContext) {} + + @Override + public ListenableFuture clearData() { + return Futures.immediateFuture(null); + } } -- cgit v1.2.3