From e851821a851b9b97a846a1c8babca5c7e114fc88 Mon Sep 17 00:00:00 2001 From: calderwoodra Date: Tue, 22 Aug 2017 17:14:49 -0700 Subject: Created FakeInCallActivity for making EC w/ images. video (slow/3g): https://drive.google.com/open?id=0B2Hce9qilHmvMnZZbE90TTlNSTQ video (average): https://drive.google.com/open?id=0B2Hce9qilHmvazZNeVJjbU5Db0k video (cancelling): https://drive.google.com/open?id=0B2Hce9qilHmvRi1JUXQ3OHZOYXM Future CLs or updates to this CL will include activity transition improvements and testing. Bug: 38189742 Test: CallComposerActivityIntegrationTest PiperOrigin-RevId: 166137133 Change-Id: Iada3e96c83495fd9a1554b4556be968670513163 --- .../dialer/callcomposer/CallComposerActivity.java | 82 ++++- .../android/dialer/postcall/AndroidManifest.xml | 2 +- java/com/android/incallui/CallCardPresenter.java | 2 + java/com/android/incallui/InCallActivity.java | 2 + .../incallui/callpending/AndroidManifest.xml | 32 ++ .../incallui/callpending/CallPendingActivity.java | 342 +++++++++++++++++++++ .../res/layout/pending_incall_screen.xml | 22 ++ .../incallui/incall/impl/InCallFragment.java | 7 +- .../incallui/incall/impl/InCallPagerAdapter.java | 29 +- .../incallui/incall/protocol/PrimaryCallState.java | 6 +- .../incallui/incall/protocol/PrimaryInfo.java | 4 + 11 files changed, 508 insertions(+), 22 deletions(-) create mode 100644 java/com/android/incallui/callpending/AndroidManifest.xml create mode 100644 java/com/android/incallui/callpending/CallPendingActivity.java create mode 100644 java/com/android/incallui/callpending/res/layout/pending_incall_screen.xml diff --git a/java/com/android/dialer/callcomposer/CallComposerActivity.java b/java/com/android/dialer/callcomposer/CallComposerActivity.java index e6e55134b..d470ad2d9 100644 --- a/java/com/android/dialer/callcomposer/CallComposerActivity.java +++ b/java/com/android/dialer/callcomposer/CallComposerActivity.java @@ -75,9 +75,11 @@ import com.android.dialer.multimedia.MultimediaData; import com.android.dialer.protos.ProtoParsers; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.DialerUtils; +import com.android.dialer.util.UriUtils; import com.android.dialer.util.ViewUtil; import com.android.dialer.widget.DialerToolbar; import com.android.dialer.widget.LockableViewPager; +import com.android.incallui.callpending.CallPendingActivity; import com.google.protobuf.InvalidProtocolBufferException; import java.io.File; @@ -119,6 +121,14 @@ public class CallComposerActivity extends AppCompatActivity LogUtil.i("CallComposerActivity.sessionStartedTimedOutRunnable", "session never started"); setFailedResultAndFinish(); }; + private final Runnable placeTelecomCallRunnable = + () -> { + LogUtil.i("CallComposerActivity.placeTelecomCallRunnable", "upload timed out."); + placeTelecomCall(); + }; + // Counter for the number of message sent updates received from EnrichedCallManager + private int messageSentCounter; + private boolean pendingCallStarted; private DialerContact contact; private Long sessionId = Session.NO_SESSION_ID; @@ -239,7 +249,13 @@ public class CallComposerActivity extends AppCompatActivity protected void onResume() { super.onResume(); getEnrichedCallManager().registerStateChangedListener(this); - if (sessionId == Session.NO_SESSION_ID) { + if (pendingCallStarted) { + // User went into incall ui and pressed disconnect before the image was done uploading. + // Kill the activity and cancel the telecom call. + timeoutHandler.removeCallbacks(placeTelecomCallRunnable); + setResult(RESULT_OK); + finish(); + } else if (sessionId == Session.NO_SESSION_ID) { LogUtil.i("CallComposerActivity.onResume", "creating new session"); sessionId = getEnrichedCallManager().startCallComposerSession(contact.getNumber()); } else if (getEnrichedCallManager().getSession(sessionId) == null) { @@ -257,12 +273,16 @@ public class CallComposerActivity extends AppCompatActivity } @Override - protected void onPause() { - super.onPause(); + protected void onDestroy() { + super.onDestroy(); getEnrichedCallManager().unregisterStateChangedListener(this); - timeoutHandler.removeCallbacks(sessionStartedTimedOut); + timeoutHandler.removeCallbacksAndMessages(null); } + /** + * This listener is registered in onResume and removed in onDestroy, meaning that calls to this + * method can come after onStop and updates to UI could cause crashes. + */ @Override public void onEnrichedCallStateChanged() { refreshUiForCallComposerState(); @@ -297,8 +317,18 @@ public class CallComposerActivity extends AppCompatActivity case Session.STATE_CLOSED: setFailedResultAndFinish(); break; - case Session.STATE_MESSAGE_FAILED: case Session.STATE_MESSAGE_SENT: + if (++messageSentCounter == 3) { + // When we compose EC with images, there are 3 steps: + // 1. Message sent with no data + // 2. Image uploaded + // 3. url sent + // Once we receive 3 message sent updates, we know that we can proceed with the call. + timeoutHandler.removeCallbacks(placeTelecomCallRunnable); + placeTelecomCall(); + } + break; + case Session.STATE_MESSAGE_FAILED: case Session.STATE_NONE: default: break; @@ -394,18 +424,36 @@ public class CallComposerActivity extends AppCompatActivity return session != null && session.getState() == Session.STATE_STARTED; } - private void placeRCSCall(MultimediaData.Builder builder) { + @VisibleForTesting + public void placeRCSCall(MultimediaData.Builder builder) { MultimediaData data = builder.build(); LogUtil.i("CallComposerActivity.placeRCSCall", "placing enriched call, data: " + data); Logger.get(this).logImpression(DialerImpression.Type.CALL_COMPOSER_ACTIVITY_PLACE_RCS_CALL); + getEnrichedCallManager().sendCallComposerData(sessionId, data); - TelecomUtil.placeCall( - this, - new CallIntentBuilder(contact.getNumber(), CallInitiationType.Type.CALL_COMPOSER).build()); - setResult(RESULT_OK); + maybeShowPrivacyToast(data); + if (data.hasImageData() + && ConfigProviderBindings.get(this).getBoolean("enable_delayed_ec_images", true) + && !TelecomUtil.isInCall(this)) { + timeoutHandler.postDelayed(placeTelecomCallRunnable, getRCSTimeoutMillis()); + startActivity( + CallPendingActivity.getIntent( + this, + contact.getNameOrNumber(), + contact.getNumber(), + contact.getNumberLabel(), + UriUtils.getLookupKeyFromUri(Uri.parse(contact.getContactUri())), + Uri.parse(contact.getPhotoUri()), + sessionId)); + pendingCallStarted = true; + } else { + placeTelecomCall(); + } + } + + private void maybeShowPrivacyToast(MultimediaData data) { SharedPreferences preferences = DialerUtils.getDefaultSharedPreferenceForDeviceProtectedStorageContext(this); - // Show a toast for privacy purposes if this is the first time a user uses call composer. if (preferences.getBoolean(KEY_IS_FIRST_CALL_COMPOSE, true)) { int privacyMessage = @@ -416,6 +464,18 @@ public class CallComposerActivity extends AppCompatActivity toast.show(); preferences.edit().putBoolean(KEY_IS_FIRST_CALL_COMPOSE, false).apply(); } + } + + @VisibleForTesting + public long getRCSTimeoutMillis() { + return ConfigProviderBindings.get(this).getLong("ec_image_upload_timeout", 15_000); + } + + private void placeTelecomCall() { + TelecomUtil.placeCall( + this, + new CallIntentBuilder(contact.getNumber(), CallInitiationType.Type.CALL_COMPOSER).build()); + setResult(RESULT_OK); finish(); } diff --git a/java/com/android/dialer/postcall/AndroidManifest.xml b/java/com/android/dialer/postcall/AndroidManifest.xml index 7e69d3368..a09750564 100644 --- a/java/com/android/dialer/postcall/AndroidManifest.xml +++ b/java/com/android/dialer/postcall/AndroidManifest.xml @@ -15,7 +15,7 @@ --> + package="com.android.dialer.postcall"> + + + + + + diff --git a/java/com/android/incallui/callpending/CallPendingActivity.java b/java/com/android/incallui/callpending/CallPendingActivity.java new file mode 100644 index 000000000..554d02165 --- /dev/null +++ b/java/com/android/incallui/callpending/CallPendingActivity.java @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2017 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.incallui.callpending; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.telecom.CallAudioState; +import android.telecom.TelecomManager; +import com.android.dialer.common.LogUtil; +import com.android.dialer.enrichedcall.EnrichedCallComponent; +import com.android.dialer.multimedia.MultimediaData; +import com.android.incallui.audiomode.AudioModeProvider; +import com.android.incallui.call.DialerCall.State; +import com.android.incallui.incall.bindings.InCallBindings; +import com.android.incallui.incall.protocol.ContactPhotoType; +import com.android.incallui.incall.protocol.InCallButtonIds; +import com.android.incallui.incall.protocol.InCallButtonUi; +import com.android.incallui.incall.protocol.InCallButtonUiDelegate; +import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory; +import com.android.incallui.incall.protocol.InCallScreen; +import com.android.incallui.incall.protocol.InCallScreenDelegate; +import com.android.incallui.incall.protocol.InCallScreenDelegateFactory; +import com.android.incallui.incall.protocol.PrimaryCallState; +import com.android.incallui.incall.protocol.PrimaryInfo; +import java.io.FileNotFoundException; +import java.io.InputStream; + +/** + * Activity useful for showing the incall ui without an actual call being placed. + * + *

The UI currently displays the following: + * + *

    + *
  • Contact info + *
  • "Dialing..." call state + *
  • Enriched calling data + *
+ * + * If the user presses the back or disconnect buttons, {@link #finish()} is called. + */ +public class CallPendingActivity extends FragmentActivity + implements InCallButtonUiDelegateFactory, InCallScreenDelegateFactory { + + private static final String TAG_IN_CALL_SCREEN = "tag_in_call_screen"; + private static final String ACTION_FINISH_BROADCAST = + "dialer.intent.action.CALL_PENDING_ACTIVITY_FINISH"; + + private static final String EXTRA_SESSION_ID = "extra_session_id"; + private static final String EXTRA_NUMBER = "extra_number"; + private static final String EXTRA_NAME = "extra_name"; + private static final String EXTRA_LABEL = "extra_LABEL"; + private static final String EXTRA_LOOKUP_KEY = "extra_LOOKUP_KEY"; + private static final String EXTRA_PHOTO_URI = "extra_photo_uri"; + + private final BroadcastReceiver finishReceiver = + new BroadcastReceiver() { + @Override + public void onReceive(Context arg0, Intent intent) { + LogUtil.i("CallPendingActivity.onReceive", "finish broadcast received"); + String action = intent.getAction(); + if (action.equals(ACTION_FINISH_BROADCAST)) { + finish(); + } + } + }; + + private InCallButtonUiDelegate inCallButtonUiDelegate; + private InCallScreenDelegate inCallScreenDelegate; + + public static Intent getIntent( + Context context, + String name, + String number, + String label, + String lookupKey, + Uri photoUri, + long sessionId) { + Intent intent = new Intent(context, CallPendingActivity.class); + intent.putExtra(EXTRA_NAME, name); + intent.putExtra(EXTRA_NUMBER, number); + intent.putExtra(EXTRA_LABEL, label); + intent.putExtra(EXTRA_LOOKUP_KEY, lookupKey); + intent.putExtra(EXTRA_PHOTO_URI, photoUri); + intent.putExtra(EXTRA_SESSION_ID, sessionId); + return intent; + } + + public static Intent getFinishBroadcast() { + return new Intent(ACTION_FINISH_BROADCAST); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.pending_incall_screen); + registerReceiver(finishReceiver, new IntentFilter(ACTION_FINISH_BROADCAST)); + } + + @Override + protected void onStart() { + super.onStart(); + InCallScreen inCallScreen = InCallBindings.createInCallScreen(); + getSupportFragmentManager() + .beginTransaction() + .add(R.id.main, inCallScreen.getInCallScreenFragment(), TAG_IN_CALL_SCREEN) + .commit(); + } + + @Override + protected void onResume() { + super.onResume(); + setupInCallScreen(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(finishReceiver); + } + + private void setupInCallScreen() { + InCallScreen inCallScreen = + (InCallScreen) getSupportFragmentManager().findFragmentByTag(TAG_IN_CALL_SCREEN); + inCallScreen.setPrimary(createPrimaryInfo()); + inCallScreen.setCallState(PrimaryCallState.createEmptyPrimaryCallStateWithState(State.DIALING)); + inCallScreen.setEndCallButtonEnabled(true, true); + } + + private PrimaryInfo createPrimaryInfo() { + MultimediaData multimediaData = + EnrichedCallComponent.get(this) + .getEnrichedCallManager() + .getSession(getSessionId()) + .getMultimediaData(); + + Drawable photo = null; + try { + // TODO(calderwoodra) move to background thread + Uri photoUri = getPhotoUri(); + InputStream is = getContentResolver().openInputStream(photoUri); + photo = Drawable.createFromStream(is, photoUri.toString()); + } catch (FileNotFoundException e) { + LogUtil.e("CallPendingActivity.createPrimaryInfo", "Contact photo not found", e); + } + + String name = getName(); + String number = getNumber(); + + // DialerCall with caller that is a work contact. + return new PrimaryInfo( + number, + name, + name != null && name.equals(number), + null /* location */, + getPhoneLabel(), + photo, + ContactPhotoType.CONTACT, + false /* isSipCall */, + true /* isContactPhotoShown */, + false /* isWorkCall */, + false /* isSpam */, + false /* answeringDisconnectsOngoingCall */, + false /* shouldShowLocation */, + getLookupKey(), + multimediaData, + false /*showInCallButtonGrid */, + TelecomManager.PRESENTATION_ALLOWED); + } + + @Override + public InCallButtonUiDelegate newInCallButtonUiDelegate() { + if (inCallButtonUiDelegate != null) { + return inCallButtonUiDelegate; + } + return inCallButtonUiDelegate = + new InCallButtonUiDelegate() { + + @Override + public void onInCallButtonUiReady(InCallButtonUi inCallButtonUi) { + inCallButtonUi.showButton(InCallButtonIds.BUTTON_DIALPAD, true); + inCallButtonUi.showButton(InCallButtonIds.BUTTON_MUTE, true); + inCallButtonUi.showButton(InCallButtonIds.BUTTON_AUDIO, true); + inCallButtonUi.showButton(InCallButtonIds.BUTTON_ADD_CALL, true); + + inCallButtonUi.enableButton(InCallButtonIds.BUTTON_DIALPAD, false); + inCallButtonUi.enableButton(InCallButtonIds.BUTTON_MUTE, false); + inCallButtonUi.enableButton(InCallButtonIds.BUTTON_AUDIO, false); + inCallButtonUi.enableButton(InCallButtonIds.BUTTON_ADD_CALL, false); + } + + @Override + public void onInCallButtonUiUnready() {} + + @Override + public void onSaveInstanceState(Bundle outState) {} + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) {} + + @Override + public void refreshMuteState() {} + + @Override + public void addCallClicked() {} + + @Override + public void muteClicked(boolean checked, boolean clickedByUser) {} + + @Override + public void mergeClicked() {} + + @Override + public void holdClicked(boolean checked) {} + + @Override + public void swapClicked() {} + + @Override + public void showDialpadClicked(boolean checked) {} + + @Override + public void changeToVideoClicked() {} + + @Override + public void switchCameraClicked(boolean useFrontFacingCamera) {} + + @Override + public void toggleCameraClicked() {} + + @Override + public void pauseVideoClicked(boolean pause) {} + + @Override + public void toggleSpeakerphone() {} + + @Override + public CallAudioState getCurrentAudioState() { + return AudioModeProvider.getInstance().getAudioState(); + } + + @Override + public void setAudioRoute(int route) {} + + @Override + public void onEndCallClicked() {} + + @Override + public void showAudioRouteSelector() {} + + @Override + public Context getContext() { + return CallPendingActivity.this; + } + }; + } + + @Override + public InCallScreenDelegate newInCallScreenDelegate() { + if (inCallScreenDelegate != null) { + return inCallScreenDelegate; + } + return inCallScreenDelegate = + new InCallScreenDelegate() { + + @Override + public void onInCallScreenDelegateInit(InCallScreen inCallScreen) {} + + @Override + public void onInCallScreenReady() {} + + @Override + public void onInCallScreenUnready() {} + + @Override + public void onEndCallClicked() { + finish(); + } + + @Override + public void onSecondaryInfoClicked() {} + + @Override + public void onCallStateButtonClicked() {} + + @Override + public void onManageConferenceClicked() {} + + @Override + public void onShrinkAnimationComplete() {} + + @Override + public void onInCallScreenResumed() {} + + @Override + public void onInCallScreenPaused() {} + }; + } + + private long getSessionId() { + return getIntent().getLongExtra(EXTRA_SESSION_ID, -1); + } + + private String getNumber() { + return getIntent().getStringExtra(EXTRA_NUMBER); + } + + private String getName() { + return getIntent().getStringExtra(EXTRA_NAME); + } + + private String getPhoneLabel() { + return getIntent().getStringExtra(EXTRA_LABEL); + } + + private String getLookupKey() { + return getIntent().getStringExtra(EXTRA_LOOKUP_KEY); + } + + private Uri getPhotoUri() { + return getIntent().getParcelableExtra(EXTRA_PHOTO_URI); + } +} diff --git a/java/com/android/incallui/callpending/res/layout/pending_incall_screen.xml b/java/com/android/incallui/callpending/res/layout/pending_incall_screen.xml new file mode 100644 index 000000000..398042b03 --- /dev/null +++ b/java/com/android/incallui/callpending/res/layout/pending_incall_screen.xml @@ -0,0 +1,22 @@ + + + + + diff --git a/java/com/android/incallui/incall/impl/InCallFragment.java b/java/com/android/incallui/incall/impl/InCallFragment.java index 7e39ceb40..f9abf2044 100644 --- a/java/com/android/incallui/incall/impl/InCallFragment.java +++ b/java/com/android/incallui/incall/impl/InCallFragment.java @@ -241,7 +241,7 @@ public class InCallFragment extends Fragment @Override public void setPrimary(@NonNull PrimaryInfo primaryInfo) { LogUtil.i("InCallFragment.setPrimary", primaryInfo.toString()); - setAdapterMedia(primaryInfo.multimediaData); + setAdapterMedia(primaryInfo.multimediaData, primaryInfo.showInCallButtonGrid); contactGridManager.setPrimary(primaryInfo); if (primaryInfo.shouldShowLocation) { @@ -267,9 +267,10 @@ public class InCallFragment extends Fragment } } - private void setAdapterMedia(MultimediaData multimediaData) { + private void setAdapterMedia(MultimediaData multimediaData, boolean showInCallButtonGrid) { if (adapter == null) { - adapter = new InCallPagerAdapter(getChildFragmentManager(), multimediaData); + adapter = + new InCallPagerAdapter(getChildFragmentManager(), multimediaData, showInCallButtonGrid); pager.setAdapter(adapter); } else { adapter.setAttachments(multimediaData); diff --git a/java/com/android/incallui/incall/impl/InCallPagerAdapter.java b/java/com/android/incallui/incall/impl/InCallPagerAdapter.java index d4b04feff..ead35344f 100644 --- a/java/com/android/incallui/incall/impl/InCallPagerAdapter.java +++ b/java/com/android/incallui/incall/impl/InCallPagerAdapter.java @@ -21,6 +21,7 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.PagerAdapter; +import com.android.dialer.common.Assert; import com.android.dialer.multimedia.MultimediaData; import com.android.incallui.sessiondata.MultimediaFragment; @@ -28,28 +29,44 @@ import com.android.incallui.sessiondata.MultimediaFragment; public class InCallPagerAdapter extends FragmentStatePagerAdapter { @Nullable private MultimediaData attachments; + private final boolean showInCallButtonGrid; - public InCallPagerAdapter(FragmentManager fragmentManager, @Nullable MultimediaData attachments) { + public InCallPagerAdapter( + FragmentManager fragmentManager, + @Nullable MultimediaData attachments, + boolean showInCallButtonGrid) { super(fragmentManager); this.attachments = attachments; + this.showInCallButtonGrid = showInCallButtonGrid; } @Override public Fragment getItem(int position) { - if (position == getButtonGridPosition()) { + if (!showInCallButtonGrid) { + // TODO(calderwoodra): handle fragment invalidation for when the data changes. + return MultimediaFragment.newInstance( + attachments, true /* isInteractive */, false /* showAvatar */, false /* isSpam */); + + } else if (position == getButtonGridPosition()) { return InCallButtonGridFragment.newInstance(); + } else { - // TODO(calderwoodra): handle fragment invalidation for when the data changes. - return MultimediaFragment.newInstance(attachments, true, false, false); + return MultimediaFragment.newInstance( + attachments, true /* isInteractive */, false /* showAvatar */, false /* isSpam */); } } @Override public int getCount() { + int count = 0; + if (showInCallButtonGrid) { + count++; + } if (attachments != null && attachments.hasData()) { - return 2; + count++; } - return 1; + Assert.checkArgument(count > 0, "InCallPager adapter doesn't have any pages."); + return count; } public void setAttachments(@Nullable MultimediaData attachments) { diff --git a/java/com/android/incallui/incall/protocol/PrimaryCallState.java b/java/com/android/incallui/incall/protocol/PrimaryCallState.java index 791f22ea7..1afa66a91 100644 --- a/java/com/android/incallui/incall/protocol/PrimaryCallState.java +++ b/java/com/android/incallui/incall/protocol/PrimaryCallState.java @@ -66,8 +66,12 @@ public class PrimaryCallState { // TODO: Convert to autovalue. b/34502119 public static PrimaryCallState createEmptyPrimaryCallState() { + return createEmptyPrimaryCallStateWithState(DialerCall.State.IDLE); + } + + public static PrimaryCallState createEmptyPrimaryCallStateWithState(int state) { return new PrimaryCallState( - DialerCall.State.IDLE, + state, false, /* isVideoCall */ SessionModificationState.NO_REQUEST, new DisconnectCause(DisconnectCause.UNKNOWN), diff --git a/java/com/android/incallui/incall/protocol/PrimaryInfo.java b/java/com/android/incallui/incall/protocol/PrimaryInfo.java index 761dd9a81..7fe0a0f6a 100644 --- a/java/com/android/incallui/incall/protocol/PrimaryInfo.java +++ b/java/com/android/incallui/incall/protocol/PrimaryInfo.java @@ -41,6 +41,7 @@ public class PrimaryInfo { // Used for consistent LetterTile coloring. @Nullable public final String contactInfoLookupKey; @Nullable public final MultimediaData multimediaData; + public final boolean showInCallButtonGrid; public final int numberPresentation; // TODO: Convert to autovalue. b/34502119 @@ -61,6 +62,7 @@ public class PrimaryInfo { false, null, null, + true, -1); } @@ -80,6 +82,7 @@ public class PrimaryInfo { boolean shouldShowLocation, @Nullable String contactInfoLookupKey, @Nullable MultimediaData multimediaData, + boolean showInCallButtonGrid, int numberPresentation) { this.number = number; this.name = name; @@ -96,6 +99,7 @@ public class PrimaryInfo { this.shouldShowLocation = shouldShowLocation; this.contactInfoLookupKey = contactInfoLookupKey; this.multimediaData = multimediaData; + this.showInCallButtonGrid = showInCallButtonGrid; this.numberPresentation = numberPresentation; } -- cgit v1.2.3