Updating PrimaryCallState value class to use AutoValue with builder pattern.

Bug: 34502119
Test: BottomRowTest,CallCardPresenterTest,PrimaryCallStateTest,TopRowTest
PiperOrigin-RevId: 187071451
Change-Id: Ib1b4baee397f61eade84bf1a887596dddc37230a
diff --git a/java/com/android/incallui/CallCardPresenter.java b/java/com/android/incallui/CallCardPresenter.java
index b945b08..ad92f57 100644
--- a/java/com/android/incallui/CallCardPresenter.java
+++ b/java/com/android/incallui/CallCardPresenter.java
@@ -352,7 +352,7 @@
       callState = this.primary.getState();
       updatePrimaryCallState();
     } else {
-      getUi().setCallState(PrimaryCallState.createEmptyPrimaryCallState());
+      getUi().setCallState(PrimaryCallState.empty());
     }
 
     maybeShowManageConferenceCallButton();
@@ -472,34 +472,39 @@
           !VideoCallPresenter.showIncomingVideo(primary.getVideoState(), primary.getState());
       getUi()
           .setCallState(
-              new PrimaryCallState(
-                  primary.getState(),
-                  primary.isVideoCall(),
-                  primary.getVideoTech().getSessionModificationState(),
-                  primary.getDisconnectCause(),
-                  getConnectionLabel(),
-                  getCallStateIcon(),
-                  getGatewayNumber(),
-                  shouldShowCallSubject(primary) ? primary.getCallSubject() : null,
-                  PhoneNumberHelper.formatNumber(
-                      primary.getCallbackNumber(), primary.getSimCountryIso()),
-                  primary.hasProperty(Details.PROPERTY_WIFI),
-                  primary.isConferenceCall()
-                      && !primary.hasProperty(Details.PROPERTY_GENERIC_CONFERENCE),
-                  isWorkCall,
-                  isAttemptingHdAudioCall,
-                  isHdAudioCall,
-                  !TextUtils.isEmpty(primary.getLastForwardedNumber()) || primary.isCallForwarded(),
-                  shouldShowContactPhoto,
-                  primary.getConnectTimeMillis(),
-                  primary.isVoiceMailNumber(),
-                  primary.isRemotelyHeld(),
-                  isBusiness,
-                  supports2ndCallOnHold(),
-                  getSwapToSecondaryButtonState(),
-                  primary.isAssistedDialed(),
-                  null,
-                  primary.getAssistedDialingExtras()));
+              PrimaryCallState.builder()
+                  .setState(primary.getState())
+                  .setIsVideoCall(primary.isVideoCall())
+                  .setSessionModificationState(primary.getVideoTech().getSessionModificationState())
+                  .setDisconnectCause(primary.getDisconnectCause())
+                  .setConnectionLabel(getConnectionLabel())
+                  .setConnectionIcon(getCallStateIcon())
+                  .setGatewayNumber(getGatewayNumber())
+                  .setCallSubject(shouldShowCallSubject(primary) ? primary.getCallSubject() : null)
+                  .setCallbackNumber(
+                      PhoneNumberHelper.formatNumber(
+                          primary.getCallbackNumber(), primary.getSimCountryIso()))
+                  .setIsWifi(primary.hasProperty(Details.PROPERTY_WIFI))
+                  .setIsConference(
+                      primary.isConferenceCall()
+                          && !primary.hasProperty(Details.PROPERTY_GENERIC_CONFERENCE))
+                  .setIsWorkCall(isWorkCall)
+                  .setIsHdAttempting(isAttemptingHdAudioCall)
+                  .setIsHdAudioCall(isHdAudioCall)
+                  .setIsForwardedNumber(
+                      !TextUtils.isEmpty(primary.getLastForwardedNumber())
+                          || primary.isCallForwarded())
+                  .setShouldShowContactPhoto(shouldShowContactPhoto)
+                  .setConnectTimeMillis(primary.getConnectTimeMillis())
+                  .setIsVoiceMailNumber(primary.isVoiceMailNumber())
+                  .setIsRemotelyHeld(primary.isRemotelyHeld())
+                  .setIsBusinessNumber(isBusiness)
+                  .setSupportsCallOnHold(supports2ndCallOnHold())
+                  .setSwapToSecondaryButtonState(getSwapToSecondaryButtonState())
+                  .setIsAssistedDialed(primary.isAssistedDialed())
+                  .setCustomLabel(null)
+                  .setAssistedDialingExtras(primary.getAssistedDialingExtras())
+                  .build());
 
       InCallActivity activity =
           (InCallActivity) (inCallScreen.getInCallScreenFragment().getActivity());
diff --git a/java/com/android/incallui/answer/impl/AnswerFragment.java b/java/com/android/incallui/answer/impl/AnswerFragment.java
index 3439a3e..4729b41 100644
--- a/java/com/android/incallui/answer/impl/AnswerFragment.java
+++ b/java/com/android/incallui/answer/impl/AnswerFragment.java
@@ -858,7 +858,7 @@
   public void onAnswerProgressUpdate(@FloatRange(from = -1f, to = 1f) float answerProgress) {
     // Don't fade the window background for call waiting or video upgrades. Fading the background
     // shows the system wallpaper which looks bad because on reject we switch to another call.
-    if (primaryCallState.state == State.INCOMING && !isVideoCall()) {
+    if (primaryCallState.state() == State.INCOMING && !isVideoCall()) {
       answerScreenDelegate.updateWindowBackgroundColor(answerProgress);
     }
 
@@ -969,7 +969,7 @@
         if (hasCallOnHold()) {
           getAnswerMethod()
               .setHintText(getText(R.string.call_incoming_default_label_answer_and_release_third));
-        } else if (primaryCallState.supportsCallOnHold) {
+        } else if (primaryCallState.supportsCallOnHold()) {
           getAnswerMethod()
               .setHintText(getText(R.string.call_incoming_default_label_answer_and_release_second));
         }
@@ -1048,9 +1048,9 @@
 
   private boolean canRejectCallWithSms() {
     return primaryCallState != null
-        && !(primaryCallState.state == State.DISCONNECTED
-            || primaryCallState.state == State.DISCONNECTING
-            || primaryCallState.state == State.IDLE);
+        && !(primaryCallState.state() == State.DISCONNECTED
+            || primaryCallState.state() == State.DISCONNECTING
+            || primaryCallState.state() == State.IDLE);
   }
 
   private void createInCallScreenDelegate() {
diff --git a/java/com/android/incallui/callpending/CallPendingActivity.java b/java/com/android/incallui/callpending/CallPendingActivity.java
index 306eed8..c7ce2b1 100644
--- a/java/com/android/incallui/callpending/CallPendingActivity.java
+++ b/java/com/android/incallui/callpending/CallPendingActivity.java
@@ -147,8 +147,10 @@
         (InCallScreen) getSupportFragmentManager().findFragmentByTag(TAG_IN_CALL_SCREEN);
     inCallScreen.setPrimary(createPrimaryInfo());
     inCallScreen.setCallState(
-        PrimaryCallState.createEmptyPrimaryCallStateWithState(
-            State.CALL_PENDING, getCallPendingLabel()));
+        PrimaryCallState.builder()
+            .setState(State.CALL_PENDING)
+            .setCustomLabel(getCallPendingLabel())
+            .build());
     inCallScreen.setEndCallButtonEnabled(true, true);
   }
 
diff --git a/java/com/android/incallui/contactgrid/BottomRow.java b/java/com/android/incallui/contactgrid/BottomRow.java
index 610eeca..dc86d81 100644
--- a/java/com/android/incallui/contactgrid/BottomRow.java
+++ b/java/com/android/incallui/contactgrid/BottomRow.java
@@ -74,11 +74,11 @@
 
   public static Info getInfo(Context context, PrimaryCallState state, PrimaryInfo primaryInfo) {
     CharSequence label;
-    boolean isTimerVisible = state.state == State.ACTIVE;
-    boolean isForwardIconVisible = state.isForwardedNumber;
-    boolean isWorkIconVisible = state.isWorkCall;
-    boolean isHdIconVisible = state.isHdAudioCall && !isForwardIconVisible;
-    boolean isHdAttemptingIconVisible = state.isHdAttempting;
+    boolean isTimerVisible = state.state() == State.ACTIVE;
+    boolean isForwardIconVisible = state.isForwardedNumber();
+    boolean isWorkIconVisible = state.isWorkCall();
+    boolean isHdIconVisible = state.isHdAudioCall() && !isForwardIconVisible;
+    boolean isHdAttemptingIconVisible = state.isHdAttempting();
     boolean isSpamIconVisible = false;
     boolean shouldPopulateAccessibilityEvent = true;
 
@@ -86,14 +86,14 @@
       label = context.getString(R.string.contact_grid_incoming_suspected_spam);
       isSpamIconVisible = true;
       isHdIconVisible = false;
-    } else if (state.state == State.DISCONNECTING) {
+    } else if (state.state() == State.DISCONNECTING) {
       // While in the DISCONNECTING state we display a "Hanging up" message in order to make the UI
       // feel more responsive.  (In GSM it's normal to see a delay of a couple of seconds while
       // negotiating the disconnect with the network, so the "Hanging up" state at least lets the
       // user know that we're doing something.  This state is currently not used with CDMA.)
       label = context.getString(R.string.incall_hanging_up);
-    } else if (state.state == State.DISCONNECTED) {
-      label = state.disconnectCause.getLabel();
+    } else if (state.state() == State.DISCONNECTED) {
+      label = state.disconnectCause().getLabel();
       if (TextUtils.isEmpty(label)) {
         label = context.getString(R.string.incall_call_ended);
       }
@@ -134,6 +134,6 @@
   }
 
   private static boolean isIncoming(PrimaryCallState state) {
-    return state.state == State.INCOMING || state.state == State.CALL_WAITING;
+    return state.state() == State.INCOMING || state.state() == State.CALL_WAITING;
   }
 }
diff --git a/java/com/android/incallui/contactgrid/ContactGridManager.java b/java/com/android/incallui/contactgrid/ContactGridManager.java
index 6dec764..1b76958 100644
--- a/java/com/android/incallui/contactgrid/ContactGridManager.java
+++ b/java/com/android/incallui/contactgrid/ContactGridManager.java
@@ -86,7 +86,7 @@
   private final View deviceNumberDivider;
 
   private PrimaryInfo primaryInfo = PrimaryInfo.empty();
-  private PrimaryCallState primaryCallState = PrimaryCallState.createEmptyPrimaryCallState();
+  private PrimaryCallState primaryCallState = PrimaryCallState.empty();
   private final LetterTileDrawable letterTile;
   private boolean isInMultiWindowMode;
 
@@ -305,11 +305,11 @@
               primaryInfo.contactInfoLookupKey(),
               LetterTileDrawable.SHAPE_CIRCLE,
               LetterTileDrawable.getContactTypeFromPrimitives(
-                  primaryCallState.isVoiceMailNumber,
+                  primaryCallState.isVoiceMailNumber(),
                   primaryInfo.isSpam(),
-                  primaryCallState.isBusinessNumber,
+                  primaryCallState.isBusinessNumber(),
                   primaryInfo.numberPresentation(),
-                  primaryCallState.isConference));
+                  primaryCallState.isConference()));
           // By invalidating the avatarImageView we force a redraw of the letter tile.
           // This is required to properly display the updated letter tile iconography based on the
           // contact type, because the background drawable reference cached in the view, and the
@@ -381,7 +381,7 @@
     if (info.isTimerVisible) {
       bottomTextSwitcher.setDisplayedChild(1);
       bottomTimerView.setBase(
-          primaryCallState.connectTimeMillis
+          primaryCallState.connectTimeMillis()
               - System.currentTimeMillis()
               + SystemClock.elapsedRealtime());
       if (!isTimerStarted) {
@@ -404,14 +404,15 @@
     if (deviceNumberTextView == null) {
       return;
     }
-    if (isInMultiWindowMode || TextUtils.isEmpty(primaryCallState.callbackNumber)) {
+    if (isInMultiWindowMode || TextUtils.isEmpty(primaryCallState.callbackNumber())) {
       deviceNumberTextView.setVisibility(View.GONE);
       deviceNumberDivider.setVisibility(View.GONE);
       return;
     }
     // This is used for carriers like Project Fi to show the callback number for emergency calls.
     deviceNumberTextView.setText(
-        context.getString(R.string.contact_grid_callback_number, primaryCallState.callbackNumber));
+        context.getString(
+            R.string.contact_grid_callback_number, primaryCallState.callbackNumber()));
     deviceNumberTextView.setVisibility(View.VISIBLE);
     if (primaryInfo.shouldShowLocation()) {
       deviceNumberDivider.setVisibility(View.VISIBLE);
diff --git a/java/com/android/incallui/contactgrid/TopRow.java b/java/com/android/incallui/contactgrid/TopRow.java
index 5eb38f9..f551092 100644
--- a/java/com/android/incallui/contactgrid/TopRow.java
+++ b/java/com/android/incallui/contactgrid/TopRow.java
@@ -62,19 +62,19 @@
 
   public static Info getInfo(Context context, PrimaryCallState state, PrimaryInfo primaryInfo) {
     CharSequence label = null;
-    Drawable icon = state.connectionIcon;
+    Drawable icon = state.connectionIcon();
     boolean labelIsSingleLine = true;
 
-    if (state.isWifi && icon == null) {
+    if (state.isWifi() && icon == null) {
       icon = context.getDrawable(R.drawable.quantum_ic_network_wifi_vd_theme_24);
     }
 
-    if (state.state == State.INCOMING || state.state == State.CALL_WAITING) {
+    if (state.state() == State.INCOMING || state.state() == State.CALL_WAITING) {
       // Call from
       // [Wi-Fi icon] Video call from
       // Hey Jake, pick up!
-      if (!TextUtils.isEmpty(state.callSubject)) {
-        label = state.callSubject;
+      if (!TextUtils.isEmpty(state.callSubject())) {
+        label = state.callSubject();
         labelIsSingleLine = false;
       } else {
         label = getLabelForIncoming(context, state);
@@ -84,22 +84,22 @@
           label = TextUtils.concat(label, " ", spanDisplayNumber(primaryInfo.number()));
         }
       }
-    } else if (VideoUtils.hasSentVideoUpgradeRequest(state.sessionModificationState)
-        || VideoUtils.hasReceivedVideoUpgradeRequest(state.sessionModificationState)) {
+    } else if (VideoUtils.hasSentVideoUpgradeRequest(state.sessionModificationState())
+        || VideoUtils.hasReceivedVideoUpgradeRequest(state.sessionModificationState())) {
       label = getLabelForVideoRequest(context, state);
-    } else if (state.state == State.PULLING) {
+    } else if (state.state() == State.PULLING) {
       label = context.getString(R.string.incall_transferring);
-    } else if (state.state == State.DIALING || state.state == State.CONNECTING) {
+    } else if (state.state() == State.DIALING || state.state() == State.CONNECTING) {
       // [Wi-Fi icon] Calling via Google Guest
       // Calling...
       label = getLabelForDialing(context, state);
-    } else if (state.state == State.ACTIVE && state.isRemotelyHeld) {
+    } else if (state.state() == State.ACTIVE && state.isRemotelyHeld()) {
       label = context.getString(R.string.incall_remotely_held);
-    } else if (state.state == State.ACTIVE
+    } else if (state.state() == State.ACTIVE
         && shouldShowNumber(primaryInfo, false /* isIncoming */)) {
       label = spanDisplayNumber(primaryInfo.number());
-    } else if (state.state == State.CALL_PENDING && !TextUtils.isEmpty(state.customLabel)) {
-      label = state.customLabel;
+    } else if (state.state() == State.CALL_PENDING && !TextUtils.isEmpty(state.customLabel())) {
+      label = state.customLabel();
     } else {
       // Video calling...
       // [Wi-Fi icon] Starbucks Wi-Fi
@@ -133,13 +133,14 @@
   }
 
   private static CharSequence getLabelForIncoming(Context context, PrimaryCallState state) {
-    if (state.isVideoCall) {
-      return getLabelForIncomingVideo(context, state.sessionModificationState, state.isWifi);
-    } else if (state.isWifi && !TextUtils.isEmpty(state.connectionLabel)) {
-      return state.connectionLabel;
+    if (state.isVideoCall()) {
+      return getLabelForIncomingVideo(context, state.sessionModificationState(), state.isWifi());
+    } else if (state.isWifi() && !TextUtils.isEmpty(state.connectionLabel())) {
+      return state.connectionLabel();
     } else if (isAccount(state)) {
-      return context.getString(R.string.contact_grid_incoming_via_template, state.connectionLabel);
-    } else if (state.isWorkCall) {
+      return context.getString(
+          R.string.contact_grid_incoming_via_template, state.connectionLabel());
+    } else if (state.isWorkCall()) {
       return context.getString(R.string.contact_grid_incoming_work_call);
     } else {
       return context.getString(R.string.contact_grid_incoming_voice_call);
@@ -164,43 +165,43 @@
   }
 
   private static CharSequence getLabelForDialing(Context context, PrimaryCallState state) {
-    if (!TextUtils.isEmpty(state.connectionLabel) && !state.isWifi) {
-      return context.getString(R.string.incall_calling_via_template, state.connectionLabel);
+    if (!TextUtils.isEmpty(state.connectionLabel()) && !state.isWifi()) {
+      return context.getString(R.string.incall_calling_via_template, state.connectionLabel());
     } else {
-      if (state.isVideoCall) {
-        if (state.isWifi) {
+      if (state.isVideoCall()) {
+        if (state.isWifi()) {
           return context.getString(R.string.incall_wifi_video_call_requesting);
         } else {
           return context.getString(R.string.incall_video_call_requesting);
         }
       }
 
-      if (state.isAssistedDialed && state.assistedDialingExtras != null) {
+      if (state.isAssistedDialed() && state.assistedDialingExtras() != null) {
         LogUtil.i("TopRow.getLabelForDialing", "using assisted dialing label.");
         String countryCode =
-            String.valueOf(state.assistedDialingExtras.transformedNumberCountryCallingCode());
+            String.valueOf(state.assistedDialingExtras().transformedNumberCountryCallingCode());
         return context.getString(
             R.string.incall_connecting_assited_dialed,
             countryCode,
-            state.assistedDialingExtras.userHomeCountryCode());
+            state.assistedDialingExtras().userHomeCountryCode());
       }
       return context.getString(R.string.incall_connecting);
     }
   }
 
   private static CharSequence getConnectionLabel(PrimaryCallState state) {
-    if (!TextUtils.isEmpty(state.connectionLabel)
-        && (isAccount(state) || state.isWifi || state.isConference)) {
+    if (!TextUtils.isEmpty(state.connectionLabel())
+        && (isAccount(state) || state.isWifi() || state.isConference())) {
       // We normally don't show a "call state label" at all when active
       // (but we can use the call state label to display the provider name).
-      return state.connectionLabel;
+      return state.connectionLabel();
     } else {
       return null;
     }
   }
 
   private static CharSequence getLabelForVideoRequest(Context context, PrimaryCallState state) {
-    switch (state.sessionModificationState) {
+    switch (state.sessionModificationState()) {
       case SessionModificationState.WAITING_FOR_UPGRADE_TO_VIDEO_RESPONSE:
         return context.getString(R.string.incall_video_call_upgrade_request);
       case SessionModificationState.REQUEST_FAILED:
@@ -211,7 +212,7 @@
       case SessionModificationState.UPGRADE_TO_VIDEO_REQUEST_TIMED_OUT:
         return context.getString(R.string.incall_video_call_request_timed_out);
       case SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST:
-        return getLabelForIncomingVideo(context, state.sessionModificationState, state.isWifi);
+        return getLabelForIncomingVideo(context, state.sessionModificationState(), state.isWifi());
       case SessionModificationState.NO_REQUEST:
       default:
         Assert.fail();
@@ -220,6 +221,6 @@
   }
 
   private static boolean isAccount(PrimaryCallState state) {
-    return !TextUtils.isEmpty(state.connectionLabel) && TextUtils.isEmpty(state.gatewayNumber);
+    return !TextUtils.isEmpty(state.connectionLabel()) && TextUtils.isEmpty(state.gatewayNumber());
   }
 }
diff --git a/java/com/android/incallui/incall/impl/InCallFragment.java b/java/com/android/incallui/incall/impl/InCallFragment.java
index 9a6d1c4..29160ab 100644
--- a/java/com/android/incallui/incall/impl/InCallFragment.java
+++ b/java/com/android/incallui/incall/impl/InCallFragment.java
@@ -321,11 +321,12 @@
     LogUtil.i("InCallFragment.setCallState", primaryCallState.toString());
     contactGridManager.setCallState(primaryCallState);
     getButtonController(InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY)
-        .setAllowed(primaryCallState.swapToSecondaryButtonState != ButtonState.NOT_SUPPORT);
+        .setAllowed(primaryCallState.swapToSecondaryButtonState() != ButtonState.NOT_SUPPORT);
     getButtonController(InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY)
-        .setEnabled(primaryCallState.swapToSecondaryButtonState == ButtonState.ENABLED);
+        .setEnabled(primaryCallState.swapToSecondaryButtonState() == ButtonState.ENABLED);
     buttonChooser =
-        ButtonChooserFactory.newButtonChooser(voiceNetworkType, primaryCallState.isWifi, phoneType);
+        ButtonChooserFactory.newButtonChooser(
+            voiceNetworkType, primaryCallState.isWifi(), phoneType);
     updateButtonStates();
   }
 
diff --git a/java/com/android/incallui/incall/protocol/PrimaryCallState.java b/java/com/android/incallui/incall/protocol/PrimaryCallState.java
index 7a3abed..1d536e9 100644
--- a/java/com/android/incallui/incall/protocol/PrimaryCallState.java
+++ b/java/com/android/incallui/incall/protocol/PrimaryCallState.java
@@ -26,12 +26,14 @@
 import com.android.incallui.call.DialerCall;
 import com.android.incallui.call.DialerCall.State;
 import com.android.incallui.videotech.utils.SessionModificationState;
+import com.google.auto.value.AutoValue;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
 
 /** State of the primary call. */
-public class PrimaryCallState {
+@AutoValue
+public abstract class PrimaryCallState {
 
   /**
    * Button state that will be invisible if not supported, visible but invalid if disabled, or
@@ -45,126 +47,159 @@
     int ENABLED = 2;
   }
 
-  public final int state;
-  public final boolean isVideoCall;
-  @SessionModificationState public final int sessionModificationState;
-  public final DisconnectCause disconnectCause;
-  public final String connectionLabel;
-  public final Drawable connectionIcon;
-  public final String gatewayNumber;
-  public final String callSubject;
-  public final String callbackNumber;
-  public final boolean isWifi;
-  public final boolean isConference;
-  public final boolean isWorkCall;
-  public final boolean isHdAttempting;
-  public final boolean isHdAudioCall;
-  public final boolean isForwardedNumber;
-  public final boolean shouldShowContactPhoto;
-  public final long connectTimeMillis;
-  public final boolean isVoiceMailNumber;
-  public final boolean isRemotelyHeld;
-  public final boolean isBusinessNumber;
-  public final boolean supportsCallOnHold;
-  public final @ButtonState int swapToSecondaryButtonState;
-  public final boolean isAssistedDialed;
-  @Nullable public final String customLabel;
-  @Nullable public final TransformationInfo assistedDialingExtras;
+  public abstract int state();
 
-  // TODO: Convert to autovalue. a bug
-  public static PrimaryCallState createEmptyPrimaryCallState() {
-    return createEmptyPrimaryCallStateWithState(DialerCall.State.IDLE, null);
+  public abstract boolean isVideoCall();
+
+  @SessionModificationState
+  public abstract int sessionModificationState();
+
+  public abstract DisconnectCause disconnectCause();
+
+  @Nullable
+  public abstract String connectionLabel();
+
+  @Nullable
+  public abstract Drawable connectionIcon();
+
+  @Nullable
+  public abstract String gatewayNumber();
+
+  @Nullable
+  public abstract String callSubject();
+
+  @Nullable
+  public abstract String callbackNumber();
+
+  public abstract boolean isWifi();
+
+  public abstract boolean isConference();
+
+  public abstract boolean isWorkCall();
+
+  public abstract boolean isHdAttempting();
+
+  public abstract boolean isHdAudioCall();
+
+  public abstract boolean isForwardedNumber();
+
+  public abstract boolean shouldShowContactPhoto();
+
+  public abstract long connectTimeMillis();
+
+  public abstract boolean isVoiceMailNumber();
+
+  public abstract boolean isRemotelyHeld();
+
+  public abstract boolean isBusinessNumber();
+
+  public abstract boolean supportsCallOnHold();
+
+  public abstract @ButtonState int swapToSecondaryButtonState();
+
+  public abstract boolean isAssistedDialed();
+
+  @Nullable
+  public abstract String customLabel();
+
+  @Nullable
+  public abstract TransformationInfo assistedDialingExtras();
+
+  public static Builder builder() {
+    return new AutoValue_PrimaryCallState.Builder()
+        .setState(DialerCall.State.IDLE)
+        .setIsVideoCall(false)
+        .setSessionModificationState(SessionModificationState.NO_REQUEST)
+        .setDisconnectCause(new DisconnectCause(DisconnectCause.UNKNOWN))
+        .setIsWifi(false)
+        .setIsConference(false)
+        .setIsWorkCall(false)
+        .setIsHdAttempting(false)
+        .setIsHdAudioCall(false)
+        .setIsForwardedNumber(false)
+        .setShouldShowContactPhoto(false)
+        .setConnectTimeMillis(0)
+        .setIsVoiceMailNumber(false)
+        .setIsRemotelyHeld(false)
+        .setIsBusinessNumber(false)
+        .setSupportsCallOnHold(true)
+        .setSwapToSecondaryButtonState(ButtonState.NOT_SUPPORT)
+        .setIsAssistedDialed(false);
   }
 
-  public static PrimaryCallState createEmptyPrimaryCallStateWithState(
-      int state, String customLabel) {
-    return new PrimaryCallState(
-        state,
-        false, /* isVideoCall */
-        SessionModificationState.NO_REQUEST,
-        new DisconnectCause(DisconnectCause.UNKNOWN),
-        null, /* connectionLabel */
-        null, /* connectionIcon */
-        null, /* gatewayNumber */
-        null, /* callSubject */
-        null, /* callbackNumber */
-        false /* isWifi */,
-        false /* isConference */,
-        false /* isWorkCall */,
-        false /* isHdAttempting */,
-        false /* isHdAudioCall */,
-        false /* isForwardedNumber */,
-        false /* shouldShowContactPhoto */,
-        0,
-        false /* isVoiceMailNumber */,
-        false /* isRemotelyHeld */,
-        false /* isBusinessNumber */,
-        true /* supportsCallOnHold */,
-        ButtonState.NOT_SUPPORT /* swapToSecondaryButtonState */,
-        false /* isAssistedDialed */,
-        customLabel,
-        null /* assistedDialingExtras */);
-  }
+  /** Builder class for primary call state info. */
+  @AutoValue.Builder
+  public abstract static class Builder {
+    public abstract Builder setState(int state);
 
-  public PrimaryCallState(
-      int state,
-      boolean isVideoCall,
-      @SessionModificationState int sessionModificationState,
-      DisconnectCause disconnectCause,
-      String connectionLabel,
-      Drawable connectionIcon,
-      String gatewayNumber,
-      String callSubject,
-      String callbackNumber,
-      boolean isWifi,
-      boolean isConference,
-      boolean isWorkCall,
-      boolean isHdAttempting,
-      boolean isHdAudioCall,
-      boolean isForwardedNumber,
-      boolean shouldShowContactPhoto,
-      long connectTimeMillis,
-      boolean isVoiceMailNumber,
-      boolean isRemotelyHeld,
-      boolean isBusinessNumber,
-      boolean supportsCallOnHold,
-      @ButtonState int swapToSecondaryButtonState,
-      boolean isAssistedDialed,
-      @Nullable String customLabel,
-      @Nullable TransformationInfo assistedDialingExtras) {
-    this.state = state;
-    this.isVideoCall = isVideoCall;
-    this.sessionModificationState = sessionModificationState;
-    this.disconnectCause = disconnectCause;
-    this.connectionLabel = connectionLabel;
-    this.connectionIcon = connectionIcon;
-    this.gatewayNumber = gatewayNumber;
-    this.callSubject = callSubject;
-    this.callbackNumber = callbackNumber;
-    this.isWifi = isWifi;
-    this.isConference = isConference;
-    this.isWorkCall = isWorkCall;
-    this.isHdAttempting = isHdAttempting;
-    this.isHdAudioCall = isHdAudioCall;
-    this.isForwardedNumber = isForwardedNumber;
-    this.shouldShowContactPhoto = shouldShowContactPhoto;
-    this.connectTimeMillis = connectTimeMillis;
-    this.isVoiceMailNumber = isVoiceMailNumber;
-    this.isRemotelyHeld = isRemotelyHeld;
-    this.isBusinessNumber = isBusinessNumber;
-    this.supportsCallOnHold = supportsCallOnHold;
-    this.swapToSecondaryButtonState = swapToSecondaryButtonState;
-    this.isAssistedDialed = isAssistedDialed;
-    if (!TextUtils.isEmpty(customLabel)) {
-      Assert.checkArgument(state == State.CALL_PENDING);
+    public abstract Builder setIsVideoCall(boolean isVideoCall);
+
+    public abstract Builder setSessionModificationState(
+        @SessionModificationState int sessionModificationState);
+
+    public abstract Builder setDisconnectCause(DisconnectCause disconnectCause);
+
+    public abstract Builder setConnectionLabel(String connectionLabel);
+
+    public abstract Builder setConnectionIcon(Drawable connectionIcon);
+
+    public abstract Builder setGatewayNumber(String gatewayNumber);
+
+    public abstract Builder setCallSubject(String callSubject);
+
+    public abstract Builder setCallbackNumber(String callbackNumber);
+
+    public abstract Builder setIsWifi(boolean isWifi);
+
+    public abstract Builder setIsConference(boolean isConference);
+
+    public abstract Builder setIsWorkCall(boolean isWorkCall);
+
+    public abstract Builder setIsHdAttempting(boolean isHdAttempting);
+
+    public abstract Builder setIsHdAudioCall(boolean isHdAudioCall);
+
+    public abstract Builder setIsForwardedNumber(boolean isForwardedNumber);
+
+    public abstract Builder setShouldShowContactPhoto(boolean shouldShowContactPhoto);
+
+    public abstract Builder setConnectTimeMillis(long connectTimeMillis);
+
+    public abstract Builder setIsVoiceMailNumber(boolean isVoiceMailNumber);
+
+    public abstract Builder setIsRemotelyHeld(boolean isRemotelyHeld);
+
+    public abstract Builder setIsBusinessNumber(boolean isBusinessNumber);
+
+    public abstract Builder setSupportsCallOnHold(boolean supportsCallOnHold);
+
+    public abstract Builder setSwapToSecondaryButtonState(
+        @ButtonState int swapToSecondaryButtonState);
+
+    public abstract Builder setIsAssistedDialed(boolean isAssistedDialed);
+
+    public abstract Builder setCustomLabel(String customLabel);
+
+    public abstract Builder setAssistedDialingExtras(TransformationInfo assistedDialingExtras);
+
+    abstract PrimaryCallState autoBuild();
+
+    public PrimaryCallState build() {
+      PrimaryCallState primaryCallState = autoBuild();
+      if (!TextUtils.isEmpty(primaryCallState.customLabel())) {
+        Assert.checkArgument(primaryCallState.state() == State.CALL_PENDING);
+      }
+      return primaryCallState;
     }
-    this.customLabel = customLabel;
-    this.assistedDialingExtras = assistedDialingExtras;
+  }
+
+  public static PrimaryCallState empty() {
+    return PrimaryCallState.builder().build();
   }
 
   @Override
   public String toString() {
     return String.format(
-        Locale.US, "PrimaryCallState, state: %d, connectionLabel: %s", state, connectionLabel);
+        Locale.US, "PrimaryCallState, state: %d, connectionLabel: %s", state(), connectionLabel());
   }
 }
diff --git a/java/com/android/incallui/rtt/impl/RttChatFragment.java b/java/com/android/incallui/rtt/impl/RttChatFragment.java
index 2c8de09..deb205c 100644
--- a/java/com/android/incallui/rtt/impl/RttChatFragment.java
+++ b/java/com/android/incallui/rtt/impl/RttChatFragment.java
@@ -288,11 +288,11 @@
   @Override
   public void setCallState(@NonNull PrimaryCallState primaryCallState) {
     LogUtil.i("RttChatFragment.setCallState", primaryCallState.toString());
-    if (!isTimerStarted && primaryCallState.state == State.ACTIVE) {
+    if (!isTimerStarted && primaryCallState.state() == State.ACTIVE) {
       LogUtil.i(
           "RttChatFragment.setCallState", "starting timer with base: %d", chronometer.getBase());
       chronometer.setBase(
-          primaryCallState.connectTimeMillis
+          primaryCallState.connectTimeMillis()
               - System.currentTimeMillis()
               + SystemClock.elapsedRealtime());
       chronometer.start();