Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33e06da5 authored by uabdullah's avatar uabdullah Committed by android-build-merger
Browse files

Merge "Refresh annotated call log from the voicemail tab"

am: 7e5da60e

Change-Id: I2a6ba922be9c46b4f5850b66ca53f908fca0a17d
parents 4964fa7b 7e5da60e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.Manifest.permission.READ_CALL_LOG;
import static android.Manifest.permission.READ_CONTACTS;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.READ_VOICEMAIL;
import static android.Manifest.permission.SEND_SMS;
import static android.Manifest.permission.WRITE_CALL_LOG;
import static android.Manifest.permission.WRITE_CONTACTS;
import static android.Manifest.permission.WRITE_VOICEMAIL;
@@ -66,6 +67,7 @@ public class PermissionsUtil {
              WRITE_CALL_LOG,
              READ_PHONE_STATE,
              MODIFY_PHONE_STATE,
              SEND_SMS,
              CALL_PHONE,
              ADD_VOICEMAIL,
              WRITE_VOICEMAIL,
+113 −1
Original line number Diff line number Diff line
@@ -27,17 +27,92 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.dialer.calllog.CallLogComponent;
import com.android.dialer.calllog.CallLogFramework;
import com.android.dialer.calllog.CallLogFramework.CallLogUi;
import com.android.dialer.calllog.RefreshAnnotatedCallLogWorker;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.common.concurrent.UiListener;
import com.android.dialer.database.CallLogQueryHandler;
import com.android.dialer.database.CallLogQueryHandler.Listener;
import com.google.common.util.concurrent.ListenableFuture;

// TODO(uabdullah): Register content observer for VoicemailContract.Status.CONTENT_URI in onStart
/** Fragment for Dialer Voicemail Tab. */
public final class NewVoicemailFragment extends Fragment implements LoaderCallbacks<Cursor> {
public final class NewVoicemailFragment extends Fragment
    implements LoaderCallbacks<Cursor>, CallLogUi {

  /*
   * This is a reasonable time that it might take between related call log writes, that also
   * shouldn't slow down single-writes too much. For example, when populating the database using
   * the simulator, using this value results in ~6 refresh cycles (on a release build) to write 120
   * call log entries.
   */
  private static final long WAIT_MILLIS = 100L;

  private RefreshAnnotatedCallLogWorker refreshAnnotatedCallLogWorker;
  private UiListener<Void> refreshAnnotatedCallLogListener;
  @Nullable private Runnable refreshAnnotatedCallLogRunnable;

  private RecyclerView recyclerView;
  private CallLogQueryHandler callLogQueryHandler;

  public NewVoicemailFragment() {
    LogUtil.enterBlock("NewVoicemailFragment.NewVoicemailFragment");
  }

  @Override
  public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    LogUtil.enterBlock("NewVoicemailFragment.onActivityCreated");

    CallLogComponent component = CallLogComponent.get(getContext());
    CallLogFramework callLogFramework = component.callLogFramework();
    callLogFramework.attachUi(this);

    // TODO(zachh): Use support fragment manager and add support for them in executors library.
    refreshAnnotatedCallLogListener =
        DialerExecutorComponent.get(getContext())
            .createUiListener(
                getActivity().getFragmentManager(), "NewVoicemailFragment.refreshAnnotatedCallLog");
    refreshAnnotatedCallLogWorker = component.getRefreshAnnotatedCallLogWorker();
  }

  @Override
  public void onStart() {
    super.onStart();
    LogUtil.enterBlock("NewVoicemailFragment.onStart");
  }

  @Override
  public void onResume() {
    super.onResume();

    LogUtil.enterBlock("NewCallLogFragment.onResume");

    CallLogFramework callLogFramework = CallLogComponent.get(getContext()).callLogFramework();
    callLogFramework.attachUi(this);

    // TODO(zachh): Consider doing this when fragment becomes visible.
    refreshAnnotatedCallLog(true /* checkDirty */);
  }

  @Override
  public void onPause() {
    super.onPause();

    LogUtil.enterBlock("NewVoicemailFragment.onPause");

    // This is pending work that we don't actually need to follow through with.
    ThreadUtil.getUiThreadHandler().removeCallbacks(refreshAnnotatedCallLogRunnable);

    CallLogFramework callLogFramework = CallLogComponent.get(getContext()).callLogFramework();
    callLogFramework.detachUi();
  }

  @Nullable
  @Override
  public View onCreateView(
@@ -49,6 +124,43 @@ public final class NewVoicemailFragment extends Fragment implements LoaderCallba
    return view;
  }

  private void refreshAnnotatedCallLog(boolean checkDirty) {
    LogUtil.enterBlock("NewVoicemailFragment.refreshAnnotatedCallLog");

    // If we already scheduled a refresh, cancel it and schedule a new one so that repeated requests
    // in quick succession don't result in too much work. For example, if we get 10 requests in
    // 10ms, and a complete refresh takes a constant 200ms, the refresh will take 300ms (100ms wait
    // and 1 iteration @200ms) instead of 2 seconds (10 iterations @ 200ms) since the work requests
    // are serialized in RefreshAnnotatedCallLogWorker.
    //
    // We might get many requests in quick succession, for example, when the simulator inserts
    // hundreds of rows into the system call log, or when the data for a new call is incrementally
    // written to different columns as it becomes available.
    ThreadUtil.getUiThreadHandler().removeCallbacks(refreshAnnotatedCallLogRunnable);

    refreshAnnotatedCallLogRunnable =
        () -> {
          ListenableFuture<Void> future =
              checkDirty
                  ? refreshAnnotatedCallLogWorker.refreshWithDirtyCheck()
                  : refreshAnnotatedCallLogWorker.refreshWithoutDirtyCheck();
          refreshAnnotatedCallLogListener.listen(
              getContext(),
              future,
              unused -> {},
              throwable -> {
                throw new RuntimeException(throwable);
              });
        };
    ThreadUtil.getUiThreadHandler().postDelayed(refreshAnnotatedCallLogRunnable, WAIT_MILLIS);
  }

  @Override
  public void invalidateUi() {
    LogUtil.enterBlock("NewVoicemailFragment.invalidateUi");
    refreshAnnotatedCallLog(false /* checkDirty */);
  }

  @Override
  public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    LogUtil.enterBlock("NewVoicemailFragment.onCreateLoader");