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

Commit 5f1d084c authored by zachh's avatar zachh Committed by Copybara-Service
Browse files

Use PreCall.start instead of context.startActivity when starting calls from call log.

For some reason not understood, startActivity with the call intent causes the current activity (MainActivity) to be paused, resumed, and paused again. This results in an opportunity to double-tap the row which causes the InCallUi to open in bubble mode (this is also not well understood).

In any event, PreCall.start eventually uses TelecomManager to place the call rather than startActivity, which is presumably the thing that fixes the problem.

Also refactored TestPreCallModule to remove the many test implementations of PreCall and remove the static field in the module which could cause test interference.

TEST=manual
Bug: 78187587
Test: manual
PiperOrigin-RevId: 193596093
Change-Id: I933020d33db1c158628f14b30c2681c59c86201b
parent ac069a79
Loading
Loading
Loading
Loading
+23 −23
Original line number Diff line number Diff line
@@ -15,8 +15,7 @@
 */
package com.android.dialer.calllog.ui;

import android.content.Context;
import android.content.Intent;
import android.app.Activity;
import android.content.res.ColorStateList;
import android.database.Cursor;
import android.provider.CallLog.Calls;
@@ -34,13 +33,14 @@ import com.android.dialer.calllog.model.CoalescedRow;
import com.android.dialer.calllog.ui.NewCallLogAdapter.PopCounts;
import com.android.dialer.calllog.ui.menu.NewCallLogMenu;
import com.android.dialer.calllogutils.CallLogEntryText;
import com.android.dialer.calllogutils.CallLogIntents;
import com.android.dialer.calllogutils.CallLogRowActions;
import com.android.dialer.calllogutils.NumberAttributesConverter;
import com.android.dialer.calllogutils.PhoneAccountUtils;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.compat.AppCompatConstants;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
import com.android.dialer.oem.MotorolaUtils;
import com.android.dialer.phonenumberutil.PhoneNumberHelper;
import com.android.dialer.telecom.TelecomUtil;
import com.android.dialer.time.Clock;
import com.android.dialer.widget.ContactPhotoView;
@@ -52,7 +52,7 @@ import java.util.concurrent.ExecutorService;
/** {@link RecyclerView.ViewHolder} for the new call log. */
final class NewCallLogViewHolder extends RecyclerView.ViewHolder {

  private final Context context;
  private final Activity activity;
  private final ContactPhotoView contactPhotoView;
  private final TextView primaryTextView;
  private final TextView callCountTextView;
@@ -74,7 +74,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
  NewCallLogViewHolder(
      View view, Clock clock, RealtimeRowProcessor realtimeRowProcessor, PopCounts popCounts) {
    super(view);
    this.context = view.getContext();
    this.activity = (Activity) view.getContext();
    contactPhotoView = view.findViewById(R.id.contact_photo_view);
    primaryTextView = view.findViewById(R.id.primary_text);
    callCountTextView = view.findViewById(R.id.call_count);
@@ -89,7 +89,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
    this.clock = clock;
    this.realtimeRowProcessor = realtimeRowProcessor;
    this.popCounts = popCounts;
    uiExecutorService = DialerExecutorComponent.get(context).uiExecutor();
    uiExecutorService = DialerExecutorComponent.get(activity).uiExecutor();
  }

  /** @param cursor a cursor from {@link CoalescedAnnotatedCallLogCursorLoader}. */
@@ -112,8 +112,8 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {

  private void displayRow(CoalescedRow row) {
    // TODO(zachh): Handle RTL properly.
    primaryTextView.setText(CallLogEntryText.buildPrimaryText(context, row));
    secondaryTextView.setText(CallLogEntryText.buildSecondaryTextForEntries(context, clock, row));
    primaryTextView.setText(CallLogEntryText.buildPrimaryText(activity, row));
    secondaryTextView.setText(CallLogEntryText.buildSecondaryTextForEntries(activity, clock, row));

    if (isUnreadMissedCall(row)) {
      primaryTextView.setTextAppearance(R.style.primary_textview_unread_call);
@@ -168,7 +168,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
  private void setFeatureIcons(CoalescedRow row) {
    ColorStateList colorStateList =
        ColorStateList.valueOf(
            context.getColor(
            activity.getColor(
                isUnreadMissedCall(row)
                    ? R.color.feature_icon_unread_color
                    : R.color.feature_icon_read_color));
@@ -182,7 +182,7 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
    }

    // Handle Wifi Icon
    if (MotorolaUtils.shouldShowWifiIconInCallLog(context, row.getFeatures())) {
    if (MotorolaUtils.shouldShowWifiIconInCallLog(activity, row.getFeatures())) {
      wifiIcon.setVisibility(View.VISIBLE);
      wifiIcon.setImageTintList(colorStateList);
    } else {
@@ -229,10 +229,10 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {

    if (isUnreadMissedCall(row)) {
      callTypeIcon.setImageTintList(
          ColorStateList.valueOf(context.getColor(R.color.call_type_icon_unread_color)));
          ColorStateList.valueOf(activity.getColor(R.color.call_type_icon_unread_color)));
    } else {
      callTypeIcon.setImageTintList(
          ColorStateList.valueOf(context.getColor(R.color.call_type_icon_read_color)));
          ColorStateList.valueOf(activity.getColor(R.color.call_type_icon_read_color)));
    }
  }

@@ -245,17 +245,19 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
      return;
    }

    String phoneAccountLabel = PhoneAccountUtils.getAccountLabel(context, phoneAccountHandle);
    String phoneAccountLabel = PhoneAccountUtils.getAccountLabel(activity, phoneAccountHandle);
    if (TextUtils.isEmpty(phoneAccountLabel)) {
      phoneAccountView.setVisibility(View.GONE);
      return;
    }

    @ColorInt
    int phoneAccountColor = PhoneAccountUtils.getAccountColor(context, phoneAccountHandle);
    int phoneAccountColor = PhoneAccountUtils.getAccountColor(activity, phoneAccountHandle);
    if (phoneAccountColor == PhoneAccount.NO_HIGHLIGHT_COLOR) {
      phoneAccountColor =
          context.getResources().getColor(R.color.dialer_secondary_text_color, context.getTheme());
          activity
              .getResources()
              .getColor(R.color.dialer_secondary_text_color, activity.getTheme());
    }

    phoneAccountView.setText(phoneAccountLabel);
@@ -264,17 +266,15 @@ final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
  }

  private void setOnClickListenerForRow(CoalescedRow row) {
    itemView.setOnClickListener(
        (view) -> {
          Intent callbackIntent = CallLogIntents.getCallBackIntent(context, row);
          if (callbackIntent != null) {
            context.startActivity(callbackIntent);
    if (!PhoneNumberHelper.canPlaceCallsTo(
        row.getNumber().getNormalizedNumber(), row.getNumberPresentation())) {
      return;
    }
        });
    itemView.setOnClickListener(view -> CallLogRowActions.startCallForRow(activity, row));
  }

  private void setOnClickListenerForMenuButon(CoalescedRow row) {
    menuButton.setOnClickListener(NewCallLogMenu.createOnClickListener(context, row));
    menuButton.setOnClickListener(NewCallLogMenu.createOnClickListener(activity, row));
  }

  private class RealtimeRowFutureCallback implements FutureCallback<CoalescedRow> {
+10 −20
Original line number Diff line number Diff line
@@ -15,39 +15,29 @@
 */
package com.android.dialer.calllogutils;

import android.content.Context;
import android.content.Intent;
import android.app.Activity;
import android.provider.CallLog.Calls;
import android.support.annotation.Nullable;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.calllog.model.CoalescedRow;
import com.android.dialer.phonenumberutil.PhoneNumberHelper;
import com.android.dialer.precall.PreCall;
import com.android.dialer.telecom.TelecomUtil;

/** Provides intents related to call log entries. */
public final class CallLogIntents {
/** Actions which can be performed on a call log row. */
public final class CallLogRowActions {

  /**
   * Returns an intent which can be used to call back for the provided row.
   * Places a call to the number in the provided {@link CoalescedRow}.
   *
   * <p>If the call was a video call, a video call will be placed, and if the call was an audio
   * call, an audio call will be placed.
   *
   * @return null if the provided {@code row} doesn't have a number
   * call, an audio call will be placed. The phone account corresponding to the row is used.
   */
  @Nullable
  public static Intent getCallBackIntent(Context context, CoalescedRow row) {
    String normalizedNumber = row.getNumber().getNormalizedNumber();
    if (!PhoneNumberHelper.canPlaceCallsTo(normalizedNumber, row.getNumberPresentation())) {
      return null;
    }

  public static void startCallForRow(Activity activity, CoalescedRow row) {
    // TODO(zachh): More granular logging?
    return PreCall.getIntent(
        context,
        new CallIntentBuilder(normalizedNumber, CallInitiationType.Type.CALL_LOG)
    PreCall.start(
        activity,
        new CallIntentBuilder(
                row.getNumber().getNormalizedNumber(), CallInitiationType.Type.CALL_LOG)
            .setPhoneAccountHandle(
                TelecomUtil.composePhoneAccountHandle(
                    row.getPhoneAccountComponentName(), row.getPhoneAccountId()))
+8 −10
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.precall.PreCall;
import com.android.dialer.precall.PreCallAction;
import com.android.dialer.precall.PreCallComponent;
import com.android.dialer.precall.PreCallCoordinator;
import com.google.common.collect.ImmutableList;
import javax.inject.Inject;
@@ -33,17 +32,16 @@ import javax.inject.Inject;
/** Implementation of {@link PreCall} */
public class PreCallImpl implements PreCall {

  private final ImmutableList<PreCallAction> actions;

  @Inject
  PreCallImpl() {}
  PreCallImpl(ImmutableList<PreCallAction> actions) {
    this.actions = actions;
  }

  @Override
  public ImmutableList<PreCallAction> getActions() {
    return ImmutableList.of(
        new PermissionCheckAction(),
        new MalformedNumberRectifier(
            ImmutableList.of(new UkRegionPrefixInInternationalFormatHandler())),
        new CallingAccountSelector(),
        new AssistedDialAction());
    return actions;
  }

  @NonNull
@@ -52,7 +50,7 @@ public class PreCallImpl implements PreCall {
    Logger.get(context).logImpression(DialerImpression.Type.PRECALL_INITIATED);
    if (!requiresUi(context, builder)) {
      LogUtil.i("PreCallImpl.buildIntent", "No UI requested, running pre-call directly");
      for (PreCallAction action : PreCallComponent.get(context).getPreCall().getActions()) {
      for (PreCallAction action : actions) {
        action.runWithoutUi(context, builder);
      }
      return builder.build();
@@ -64,7 +62,7 @@ public class PreCallImpl implements PreCall {
  }

  private boolean requiresUi(Context context, CallIntentBuilder builder) {
    for (PreCallAction action : PreCallComponent.get(context).getPreCall().getActions()) {
    for (PreCallAction action : actions) {
      if (action.requiresUi(context, builder)) {
        LogUtil.i("PreCallImpl.requiresUi", action + " requested UI");
        return true;
+17 −1
Original line number Diff line number Diff line
@@ -17,15 +17,31 @@
package com.android.dialer.precall.impl;

import com.android.dialer.precall.PreCall;
import com.android.dialer.precall.PreCallAction;
import com.google.common.collect.ImmutableList;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import javax.inject.Singleton;

/** Dagger module for {@link PreCall}. */
@Module
public abstract class PreCallModule {

  private PreCallModule() {}

  @Binds
  @Singleton
  public abstract PreCall bindPreCall(PreCallImpl simulator);
  public abstract PreCall to(PreCallImpl impl);

  @Provides
  @Singleton
  public static ImmutableList<PreCallAction> provideActions() {
    return ImmutableList.of(
        new PermissionCheckAction(),
        new MalformedNumberRectifier(
            ImmutableList.of(new UkRegionPrefixInInternationalFormatHandler())),
        new CallingAccountSelector(),
        new AssistedDialAction());
  }
}