1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.dialer.calllog; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.support.v4.content.LocalBroadcastManager; 22 import com.android.dialer.calllog.datasources.CallLogDataSource; 23 import com.android.dialer.calllog.datasources.DataSources; 24 import com.android.dialer.common.LogUtil; 25 import com.android.dialer.common.concurrent.Annotations.Ui; 26 import com.android.dialer.inject.ApplicationContext; 27 import com.google.common.util.concurrent.Futures; 28 import com.google.common.util.concurrent.ListenableFuture; 29 import com.google.common.util.concurrent.ListeningExecutorService; 30 import com.google.common.util.concurrent.MoreExecutors; 31 import java.util.ArrayList; 32 import java.util.List; 33 import javax.inject.Inject; 34 import javax.inject.Singleton; 35 36 /** 37 * Coordinates work across {@link DataSources}. 38 * 39 * <p>All methods should be called on the main thread. 40 */ 41 @Singleton 42 public final class CallLogFramework { 43 44 private final Context appContext; 45 private final DataSources dataSources; 46 private final AnnotatedCallLogMigrator annotatedCallLogMigrator; 47 private final ListeningExecutorService uiExecutor; 48 private final CallLogState callLogState; 49 50 @Inject CallLogFramework( @pplicationContext Context appContext, DataSources dataSources, AnnotatedCallLogMigrator annotatedCallLogMigrator, @Ui ListeningExecutorService uiExecutor, CallLogState callLogState)51 CallLogFramework( 52 @ApplicationContext Context appContext, 53 DataSources dataSources, 54 AnnotatedCallLogMigrator annotatedCallLogMigrator, 55 @Ui ListeningExecutorService uiExecutor, 56 CallLogState callLogState) { 57 this.appContext = appContext; 58 this.dataSources = dataSources; 59 this.annotatedCallLogMigrator = annotatedCallLogMigrator; 60 this.uiExecutor = uiExecutor; 61 this.callLogState = callLogState; 62 } 63 64 /** Registers the content observers for all data sources. */ registerContentObservers()65 public void registerContentObservers() { 66 LogUtil.enterBlock("CallLogFramework.registerContentObservers"); 67 for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { 68 dataSource.registerContentObservers(); 69 } 70 } 71 72 /** Enables the framework. */ enable()73 public ListenableFuture<Void> enable() { 74 registerContentObservers(); 75 return annotatedCallLogMigrator.migrate(); 76 } 77 78 /** Disables the framework. */ disable()79 public ListenableFuture<Void> disable() { 80 return Futures.transform( 81 Futures.allAsList(disableDataSources(), annotatedCallLogMigrator.clearData()), 82 unused -> null, 83 MoreExecutors.directExecutor()); 84 } 85 disableDataSources()86 private ListenableFuture<Void> disableDataSources() { 87 LogUtil.enterBlock("CallLogFramework.disableDataSources"); 88 89 for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { 90 dataSource.unregisterContentObservers(); 91 } 92 93 callLogState.clearData(); 94 95 // Clear data only after all content observers have been disabled. 96 List<ListenableFuture<Void>> allFutures = new ArrayList<>(); 97 for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { 98 allFutures.add(dataSource.clearData()); 99 } 100 101 return Futures.transform( 102 Futures.allAsList(allFutures), 103 unused -> { 104 // Send a broadcast to the OldMainActivityPeer to remove the NewCallLogFragment and 105 // NewVoicemailFragment if it is currently attached. If this is not done, user interaction 106 // with the fragment could cause call log framework state to be unexpectedly written. For 107 // example scrolling could cause the AnnotatedCallLog to be read (which would trigger 108 // database creation). 109 LocalBroadcastManager.getInstance(appContext) 110 .sendBroadcastSync(new Intent("disableCallLogFramework")); 111 return null; 112 }, 113 uiExecutor); 114 } 115 } 116