Rebuild Call Log on first launch after NUI is enabled

This improves the first time experience by populating the DB when the user is still in other tabs.

Bug: 72119926
Test: Unit tests
PiperOrigin-RevId: 186418788
Change-Id: If011d7191a09fd1aaca489c6e682ccdc643c2139
diff --git a/java/com/android/dialer/binary/common/DialerApplication.java b/java/com/android/dialer/binary/common/DialerApplication.java
index c0e6ae6..c239260 100644
--- a/java/com/android/dialer/binary/common/DialerApplication.java
+++ b/java/com/android/dialer/binary/common/DialerApplication.java
@@ -23,11 +23,14 @@
 import com.android.dialer.blocking.BlockedNumbersAutoMigrator;
 import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler;
 import com.android.dialer.calllog.CallLogComponent;
+import com.android.dialer.common.concurrent.DefaultFutureCallback;
 import com.android.dialer.common.concurrent.DialerExecutorComponent;
 import com.android.dialer.inject.HasRootComponent;
 import com.android.dialer.notification.NotificationChannelManager;
 import com.android.dialer.persistentlog.PersistentLogger;
 import com.android.dialer.strictmode.StrictModeComponent;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
 
 /** A common application subclass for all Dialer build variants. */
 public abstract class DialerApplication extends Application implements HasRootComponent {
@@ -46,6 +49,10 @@
             DialerExecutorComponent.get(this).dialerExecutorFactory())
         .asyncAutoMigrate();
     CallLogComponent.get(this).callLogFramework().registerContentObservers(getApplicationContext());
+    Futures.addCallback(
+        CallLogComponent.get(this).getAnnotatedCallLogMigrator().migrate(),
+        new DefaultFutureCallback<>(),
+        MoreExecutors.directExecutor());
     PersistentLogger.initialize(this);
 
     if (BuildCompat.isAtLeastO()) {
diff --git a/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java b/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java
new file mode 100644
index 0000000..f8c6fce
--- /dev/null
+++ b/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java
@@ -0,0 +1,92 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor;
+import com.android.dialer.configprovider.ConfigProviderBindings;
+import com.android.dialer.inject.ApplicationContext;
+import com.android.dialer.storage.Unencrypted;
+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 javax.inject.Inject;
+
+/**
+ * Builds the annotated call log on application create once after the feature is enabled to reduce
+ * the latency the first time call log is shown.
+ */
+public final class AnnotatedCallLogMigrator {
+
+  private static final String PREF_MIGRATED = "annotatedCallLogMigratorMigrated";
+
+  private final Context appContext;
+  private final SharedPreferences sharedPreferences;
+  private final RefreshAnnotatedCallLogWorker refreshAnnotatedCallLogWorker;
+  private final ListeningExecutorService backgorundExecutor;
+
+  @Inject
+  AnnotatedCallLogMigrator(
+      @ApplicationContext Context appContext,
+      @Unencrypted SharedPreferences sharedPreferences,
+      @BackgroundExecutor ListeningExecutorService backgroundExecutor,
+      RefreshAnnotatedCallLogWorker refreshAnnotatedCallLogWorker) {
+    this.appContext = appContext;
+    this.sharedPreferences = sharedPreferences;
+    this.backgorundExecutor = backgroundExecutor;
+    this.refreshAnnotatedCallLogWorker = refreshAnnotatedCallLogWorker;
+  }
+
+  /**
+   * Builds the annotated call log on application create once after the feature is enabled to reduce
+   * the latency the first time call log is shown.
+   */
+  public ListenableFuture<Void> migrate() {
+
+    return Futures.transformAsync(
+        shouldMigrate(),
+        (shouldMigrate) -> {
+          if (!shouldMigrate) {
+            return Futures.immediateFuture(null);
+          }
+          return Futures.transform(
+              refreshAnnotatedCallLogWorker.refreshWithoutDirtyCheck(),
+              (unused) -> {
+                sharedPreferences.edit().putBoolean(PREF_MIGRATED, true).apply();
+                return null;
+              },
+              MoreExecutors.directExecutor());
+        },
+        MoreExecutors.directExecutor());
+  }
+
+  private ListenableFuture<Boolean> shouldMigrate() {
+    return backgorundExecutor.submit(
+        () -> {
+          if (!(ConfigProviderBindings.get(appContext)
+              .getBoolean("is_nui_shortcut_enabled", false))) {
+            return false;
+          }
+          if (sharedPreferences.getBoolean(PREF_MIGRATED, false)) {
+            return false;
+          }
+          return true;
+        });
+  }
+}
diff --git a/java/com/android/dialer/calllog/CallLogComponent.java b/java/com/android/dialer/calllog/CallLogComponent.java
index 4f147f1..a2a5084 100644
--- a/java/com/android/dialer/calllog/CallLogComponent.java
+++ b/java/com/android/dialer/calllog/CallLogComponent.java
@@ -30,6 +30,8 @@
 
   public abstract RefreshAnnotatedCallLogWorker getRefreshAnnotatedCallLogWorker();
 
+  public abstract AnnotatedCallLogMigrator getAnnotatedCallLogMigrator();
+
   public abstract ClearMissedCalls getClearMissedCalls();
 
   public static CallLogComponent get(Context context) {