From 682daf24a5733d66c384e8aa854de01fa5b3844e Mon Sep 17 00:00:00 2001 From: zachh Date: Wed, 21 Mar 2018 14:37:13 -0700 Subject: Enable and disable the call log framework on flag changes. Bug: 74821995 Test: unit PiperOrigin-RevId: 189969399 Change-Id: I8e287cc7884dde7640721bd385fe383a4635f3c8 --- .../dialer/calllog/AnnotatedCallLogMigrator.java | 13 +++ java/com/android/dialer/calllog/CallLogConfig.java | 112 +++++++++++++-------- .../android/dialer/calllog/CallLogFramework.java | 38 ++++++- 3 files changed, 118 insertions(+), 45 deletions(-) (limited to 'java/com/android/dialer/calllog') diff --git a/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java b/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java index e2e112cd0..a12a98f0e 100644 --- a/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java +++ b/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java @@ -90,4 +90,17 @@ public final class AnnotatedCallLogMigrator { return true; }); } + + /** + * Clears data that indicates if migration happened or not. This is necessary if migration needs + * to happen again, for example because the call log framework was disabled via flags due to a + * problem. + */ + ListenableFuture clearData() { + return backgroundExecutor.submit( + () -> { + sharedPreferences.edit().remove(PREF_MIGRATED).apply(); + return null; + }); + } } diff --git a/java/com/android/dialer/calllog/CallLogConfig.java b/java/com/android/dialer/calllog/CallLogConfig.java index e6fa9c78f..12056c758 100644 --- a/java/com/android/dialer/calllog/CallLogConfig.java +++ b/java/com/android/dialer/calllog/CallLogConfig.java @@ -28,6 +28,7 @@ import android.support.v4.os.UserManagerCompat; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; +import com.android.dialer.common.concurrent.Annotations.LightweightExecutor; import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.configprovider.ConfigProvider; import com.android.dialer.constants.ScheduledJobIds; @@ -59,18 +60,27 @@ public final class CallLogConfig { private static final String NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY = "newCallLogFrameworkEnabled"; + private final CallLogFramework callLogFramework; private final SharedPreferences sharedPreferences; private final ConfigProvider configProvider; + private final AnnotatedCallLogMigrator annotatedCallLogMigrator; private final ListeningExecutorService backgroundExecutor; + private final ListeningExecutorService lightweightExecutor; @Inject public CallLogConfig( + CallLogFramework callLogFramework, @Unencrypted SharedPreferences sharedPreferences, ConfigProvider configProvider, - @BackgroundExecutor ListeningExecutorService backgroundExecutor) { + AnnotatedCallLogMigrator annotatedCallLogMigrator, + @BackgroundExecutor ListeningExecutorService backgroundExecutor, + @LightweightExecutor ListeningExecutorService lightweightExecutor) { + this.callLogFramework = callLogFramework; this.sharedPreferences = sharedPreferences; this.configProvider = configProvider; + this.annotatedCallLogMigrator = annotatedCallLogMigrator; this.backgroundExecutor = backgroundExecutor; + this.lightweightExecutor = lightweightExecutor; } /** @@ -78,24 +88,22 @@ public final class CallLogConfig { * example by a scheduled job or broadcast receiver which rarely fires. */ public ListenableFuture update() { - return backgroundExecutor.submit( - () -> { - boolean newCallLogFragmentEnabledInConfigProvider = - configProvider.getBoolean("new_call_log_fragment_enabled", false); - boolean newVoicemailFragmentEnabledInConfigProvider = - configProvider.getBoolean("new_voicemail_fragment_enabled", false); - boolean newPeerEnabledInConfigProvider = - configProvider.getBoolean("nui_peer_enabled", false); - - boolean isCallLogFrameworkEnabled = isCallLogFrameworkEnabled(); - boolean callLogFrameworkShouldBeEnabled = - newCallLogFragmentEnabledInConfigProvider - || newVoicemailFragmentEnabledInConfigProvider - || newPeerEnabledInConfigProvider; - - if (callLogFrameworkShouldBeEnabled && !isCallLogFrameworkEnabled) { - enableFramework(); - + boolean newCallLogFragmentEnabledInConfigProvider = + configProvider.getBoolean("new_call_log_fragment_enabled", false); + boolean newVoicemailFragmentEnabledInConfigProvider = + configProvider.getBoolean("new_voicemail_fragment_enabled", false); + boolean newPeerEnabledInConfigProvider = configProvider.getBoolean("nui_peer_enabled", false); + + boolean isCallLogFrameworkEnabled = isCallLogFrameworkEnabled(); + boolean callLogFrameworkShouldBeEnabled = + newCallLogFragmentEnabledInConfigProvider + || newVoicemailFragmentEnabledInConfigProvider + || newPeerEnabledInConfigProvider; + + if (callLogFrameworkShouldBeEnabled && !isCallLogFrameworkEnabled) { + return Futures.transform( + enableFramework(), + unused -> { // Reflect the flag changes only after the framework is enabled. sharedPreferences .edit() @@ -108,21 +116,30 @@ public final class CallLogConfig { .putBoolean(NEW_PEER_ENABLED_PREF_KEY, newPeerEnabledInConfigProvider) .putBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, true) .apply(); - - } else if (!callLogFrameworkShouldBeEnabled && isCallLogFrameworkEnabled) { - // Reflect the flag changes before disabling the framework. - sharedPreferences - .edit() - .putBoolean(NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY, false) - .putBoolean(NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY, false) - .putBoolean(NEW_PEER_ENABLED_PREF_KEY, false) - .putBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, false) - .apply(); - - disableFramework(); - } else { - // We didn't need to enable/disable the framework, but we still need to update the - // individual flags. + return null; + }, + backgroundExecutor); + } else if (!callLogFrameworkShouldBeEnabled && isCallLogFrameworkEnabled) { + // Reflect the flag changes before disabling the framework. + ListenableFuture writeSharedPrefsFuture = + backgroundExecutor.submit( + () -> { + sharedPreferences + .edit() + .putBoolean(NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY, false) + .putBoolean(NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY, false) + .putBoolean(NEW_PEER_ENABLED_PREF_KEY, false) + .putBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, false) + .apply(); + return null; + }); + return Futures.transformAsync( + writeSharedPrefsFuture, unused -> disableFramework(), MoreExecutors.directExecutor()); + } else { + // We didn't need to enable/disable the framework, but we still need to update the + // individual flags. + return backgroundExecutor.submit( + () -> { sharedPreferences .edit() .putBoolean( @@ -133,17 +150,30 @@ public final class CallLogConfig { newVoicemailFragmentEnabledInConfigProvider) .putBoolean(NEW_PEER_ENABLED_PREF_KEY, newPeerEnabledInConfigProvider) .apply(); - } - return null; - }); + return null; + }); + } } - private void enableFramework() { - // TODO(zachh): Register content observers, etc. + private ListenableFuture enableFramework() { + ListenableFuture registerObserversFuture = + lightweightExecutor.submit( + () -> { + callLogFramework.registerContentObservers(); + return null; + }); + ListenableFuture migratorFuture = annotatedCallLogMigrator.migrate(); + return Futures.transform( + Futures.allAsList(registerObserversFuture, migratorFuture), + unused -> null, + MoreExecutors.directExecutor()); } - private void disableFramework() { - // TODO(zachh): Unregister content observers, delete databases, etc. + private ListenableFuture disableFramework() { + return Futures.transform( + Futures.allAsList(callLogFramework.disable(), annotatedCallLogMigrator.clearData()), + unused -> null, + MoreExecutors.directExecutor()); } public boolean isNewCallLogFragmentEnabled() { diff --git a/java/com/android/dialer/calllog/CallLogFramework.java b/java/com/android/dialer/calllog/CallLogFramework.java index 61535e606..365e4d7c0 100644 --- a/java/com/android/dialer/calllog/CallLogFramework.java +++ b/java/com/android/dialer/calllog/CallLogFramework.java @@ -21,6 +21,12 @@ import com.android.dialer.calllog.datasources.CallLogDataSource; import com.android.dialer.calllog.datasources.DataSources; import com.android.dialer.common.LogUtil; import com.android.dialer.configprovider.ConfigProviderBindings; +import com.android.dialer.inject.ApplicationContext; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; +import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; @@ -32,21 +38,23 @@ import javax.inject.Singleton; @Singleton public final class CallLogFramework { + private final Context appContext; private final DataSources dataSources; @Inject - CallLogFramework(DataSources dataSources) { + CallLogFramework(@ApplicationContext Context appContext, DataSources dataSources) { + this.appContext = appContext; this.dataSources = dataSources; } /** Performs necessary setup work when the application is created. */ - public void onApplicationCreate(Context appContext) { - registerContentObservers(appContext); + public void onApplicationCreate() { + registerContentObservers(); CallLogConfig.schedulePollingJob(appContext); } /** Registers the content observers for all data sources. */ - public void registerContentObservers(Context appContext) { + public void registerContentObservers() { LogUtil.enterBlock("CallLogFramework.registerContentObservers"); // This is the same condition used in MainImpl#isNewUiEnabled. It means that bugfood/debug @@ -61,4 +69,26 @@ public final class CallLogFramework { LogUtil.i("CallLogFramework.registerContentObservers", "not registering content observers"); } } + + /** Disables the framework. */ + public ListenableFuture disable() { + LogUtil.enterBlock("CallLogFramework.disable"); + + if (!ConfigProviderBindings.get(appContext).getBoolean("is_nui_shortcut_enabled", false)) { + LogUtil.i("CallLogFramework.disable", "not disabling"); + return Futures.immediateFuture(null); + } + + for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { + dataSource.unregisterContentObservers(appContext); + } + + // Clear data only after all content observers have been disabled. + List> allFutures = new ArrayList<>(); + for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { + allFutures.add(dataSource.clearData()); + } + return Futures.transform( + Futures.allAsList(allFutures), unused -> null, MoreExecutors.directExecutor()); + } } -- cgit v1.2.3