1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/*
2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2016 The Android Open Source Project
3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License");
5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License.
6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at
7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *      http://www.apache.org/licenses/LICENSE-2.0
9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian *
10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software
11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS,
12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and
14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License.
15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */
16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.incallui.incall.impl;
18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.Manifest.permission;
20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context;
21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.pm.PackageManager;
22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Build.VERSION;
23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Build.VERSION_CODES;
24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Bundle;
25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Handler;
268d662cae2c05b5e256e7bb826abf05fb9ace133dwangqiimport android.support.annotation.ColorInt;
27ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.NonNull;
28ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.Nullable;
29ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.v4.app.Fragment;
30ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.v4.app.FragmentTransaction;
31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.v4.content.ContextCompat;
32ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telecom.CallAudioState;
33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.telephony.TelephonyManager;
34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.LayoutInflater;
35ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.View;
36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.View.OnClickListener;
37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.ViewGroup;
38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.view.accessibility.AccessibilityEvent;
39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.widget.ImageView;
40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.widget.RelativeLayout;
41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.widget.Toast;
42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.Assert;
43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.FragmentUtils;
44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.LogUtil;
451d62ab209130bdacdb64b2cd824b5ff35817b89fwangqiimport com.android.dialer.compat.ActivityCompat;
462ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanianimport com.android.dialer.logging.DialerImpression;
472ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanianimport com.android.dialer.logging.Logger;
48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.multimedia.MultimediaData;
49e37d60c2e304c599118a59e15ba4991f41cee785wangqiimport com.android.dialer.strictmode.StrictModeUtils;
50938468da6f5c225ebb161a68bd949c9cf3261892Eric Erfanianimport com.android.dialer.util.ViewUtil;
512ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanianimport com.android.dialer.widget.LockableViewPager;
52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.audioroute.AudioRouteSelectorDialogFragment;
53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.audioroute.AudioRouteSelectorDialogFragment.AudioRouteSelectorPresenter;
54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.contactgrid.ContactGridManager;
55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.hold.OnHoldFragment;
56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.impl.ButtonController.SpeakerButtonController;
57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.impl.InCallButtonGridFragment.OnButtonGridCreatedListener;
58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.InCallButtonIds;
59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.InCallButtonIdsExtension;
60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.InCallButtonUi;
61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.InCallButtonUiDelegate;
62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory;
63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.InCallScreen;
64ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.InCallScreenDelegate;
65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.PrimaryCallState;
672ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanianimport com.android.incallui.incall.protocol.PrimaryCallState.ButtonState;
68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.PrimaryInfo;
69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.incallui.incall.protocol.SecondaryInfo;
70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.ArrayList;
71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.List;
72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/** Fragment that shows UI for an ongoing voice call. */
74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic class InCallFragment extends Fragment
75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    implements InCallScreen,
76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        InCallButtonUi,
77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        OnClickListener,
78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        AudioRouteSelectorPresenter,
79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        OnButtonGridCreatedListener {
80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private List<ButtonController> buttonControllers = new ArrayList<>();
82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private View endCallButton;
83fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian  private InCallPaginator paginator;
84fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian  private LockableViewPager pager;
85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private InCallPagerAdapter adapter;
86ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private ContactGridManager contactGridManager;
87ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private InCallScreenDelegate inCallScreenDelegate;
88ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private InCallButtonUiDelegate inCallButtonUiDelegate;
89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private InCallButtonGridFragment inCallButtonGridFragment;
90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Nullable private ButtonChooser buttonChooser;
91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private SecondaryInfo savedSecondaryInfo;
92ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private int voiceNetworkType;
93ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private int phoneType;
94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private boolean stateRestored;
95ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
969050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian  // Add animation to educate users. If a call has enriched calling attachments then we'll
979050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian  // initially show the attachment page. After a delay seconds we'll animate to the button grid.
989050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian  private final Handler handler = new Handler();
999050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian  private final Runnable pagerRunnable =
1009050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian      new Runnable() {
1019050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        @Override
1029050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        public void run() {
1039050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian          pager.setCurrentItem(adapter.getButtonGridPosition());
1049050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        }
1059050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian      };
1069050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian
107ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  private static boolean isSupportedButton(@InCallButtonIds int id) {
108ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return id == InCallButtonIds.BUTTON_AUDIO
109ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || id == InCallButtonIds.BUTTON_MUTE
110ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || id == InCallButtonIds.BUTTON_DIALPAD
111ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || id == InCallButtonIds.BUTTON_HOLD
112ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || id == InCallButtonIds.BUTTON_SWAP
113ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || id == InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO
114ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || id == InCallButtonIds.BUTTON_ADD_CALL
115ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        || id == InCallButtonIds.BUTTON_MERGE
11600623aa60a7908b0709df38632cfa576cb15e33etwyen        || id == InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE
11700623aa60a7908b0709df38632cfa576cb15e33etwyen        || id == InCallButtonIds.BUTTON_SWAP_SIM;
118ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
119ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
120ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
121ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onAttach(Context context) {
122ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    super.onAttach(context);
123ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (savedSecondaryInfo != null) {
124ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      setSecondary(savedSecondaryInfo);
125ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
126ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
127ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
128ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
129ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onCreate(Bundle savedInstanceState) {
130ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    super.onCreate(savedInstanceState);
131ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallButtonUiDelegate =
132ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        FragmentUtils.getParent(this, InCallButtonUiDelegateFactory.class)
133ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            .newInCallButtonUiDelegate();
134ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (savedInstanceState != null) {
135ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      inCallButtonUiDelegate.onRestoreInstanceState(savedInstanceState);
136ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      stateRestored = true;
137ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
138ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
139ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
140ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Nullable
141ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
142ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public View onCreateView(
143ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      @NonNull LayoutInflater layoutInflater,
144ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      @Nullable ViewGroup viewGroup,
145ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      @Nullable Bundle bundle) {
146ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.onCreateView", null);
1472ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian    // Bypass to avoid StrictModeResourceMismatchViolation
1482ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian    final View view =
149e37d60c2e304c599118a59e15ba4991f41cee785wangqi        StrictModeUtils.bypass(
1502ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian            () -> layoutInflater.inflate(R.layout.frag_incall_voice, viewGroup, false));
151ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    contactGridManager =
152ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new ContactGridManager(
153ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            view,
154ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            (ImageView) view.findViewById(R.id.contactgrid_avatar),
155ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            getResources().getDimensionPixelSize(R.dimen.incall_avatar_size),
156ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            true /* showAnonymousAvatar */);
1571d62ab209130bdacdb64b2cd824b5ff35817b89fwangqi    contactGridManager.onMultiWindowModeChanged(ActivityCompat.isInMultiWindowMode(getActivity()));
158ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
159fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian    paginator = (InCallPaginator) view.findViewById(R.id.incall_paginator);
160fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian    pager = (LockableViewPager) view.findViewById(R.id.incall_pager);
1619050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian    pager.setOnTouchListener(
1629050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        (v, event) -> {
1639050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian          handler.removeCallbacks(pagerRunnable);
1649050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian          return false;
1659050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        });
166ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
167ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    endCallButton = view.findViewById(R.id.incall_end_call);
168ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    endCallButton.setOnClickListener(this);
169ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
170ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (ContextCompat.checkSelfPermission(getContext(), permission.READ_PHONE_STATE)
171ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        != PackageManager.PERMISSION_GRANTED) {
172ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
173ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else {
174ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
175ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      voiceNetworkType =
176ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          VERSION.SDK_INT >= VERSION_CODES.N
177ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              ? getContext().getSystemService(TelephonyManager.class).getVoiceNetworkType()
178ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian              : TelephonyManager.NETWORK_TYPE_UNKNOWN;
179ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
1805d8ed9309625302dee3407b320a52f2b7f30227fwangqi    // TODO(a bug): Change to use corresponding phone type used for current call.
181ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    phoneType = getContext().getSystemService(TelephonyManager.class).getPhoneType();
182938468da6f5c225ebb161a68bd949c9cf3261892Eric Erfanian    View space = view.findViewById(R.id.navigation_bar_background);
183938468da6f5c225ebb161a68bd949c9cf3261892Eric Erfanian    space.getLayoutParams().height = ViewUtil.getNavigationBarHeight(getContext());
184938468da6f5c225ebb161a68bd949c9cf3261892Eric Erfanian
185ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return view;
186ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
187ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
188ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
189ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onResume() {
190ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    super.onResume();
191ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallButtonUiDelegate.refreshMuteState();
192ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallScreenDelegate.onInCallScreenResumed();
193ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
194ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
195ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
196ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onViewCreated(@NonNull View view, @Nullable Bundle bundle) {
197ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.onViewCreated", null);
198ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    super.onViewCreated(view, bundle);
199ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallScreenDelegate =
200ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        FragmentUtils.getParent(this, InCallScreenDelegateFactory.class).newInCallScreenDelegate();
201ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Assert.isNotNull(inCallScreenDelegate);
202ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
203ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(new ButtonController.MuteButtonController(inCallButtonUiDelegate));
204ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(new ButtonController.SpeakerButtonController(inCallButtonUiDelegate));
205ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(new ButtonController.DialpadButtonController(inCallButtonUiDelegate));
206ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(new ButtonController.HoldButtonController(inCallButtonUiDelegate));
207ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(new ButtonController.AddCallButtonController(inCallButtonUiDelegate));
208ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(new ButtonController.SwapButtonController(inCallButtonUiDelegate));
209ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(new ButtonController.MergeButtonController(inCallButtonUiDelegate));
21000623aa60a7908b0709df38632cfa576cb15e33etwyen    buttonControllers.add(new ButtonController.SwapSimButtonController(inCallButtonUiDelegate));
211ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(
212ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new ButtonController.UpgradeToVideoButtonController(inCallButtonUiDelegate));
213ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(
214ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new ButtonController.ManageConferenceButtonController(inCallScreenDelegate));
215ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonControllers.add(
216ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        new ButtonController.SwitchToSecondaryButtonController(inCallScreenDelegate));
217ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
218ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallScreenDelegate.onInCallScreenDelegateInit(this);
219ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallScreenDelegate.onInCallScreenReady();
220ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
221ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
222ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
223d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  public void onPause() {
224d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    super.onPause();
225d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian    inCallScreenDelegate.onInCallScreenPaused();
226d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  }
227d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian
228d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian  @Override
22910b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian  public void onDestroyView() {
23010b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian    super.onDestroyView();
231ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallScreenDelegate.onInCallScreenUnready();
232ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
233ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
234ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
235ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onSaveInstanceState(Bundle outState) {
236ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    super.onSaveInstanceState(outState);
237ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallButtonUiDelegate.onSaveInstanceState(outState);
238ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
239ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
240ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
241ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onClick(View view) {
242ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (view == endCallButton) {
243ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      LogUtil.i("InCallFragment.onClick", "end call button clicked");
2442ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian      Logger.get(getContext())
2452ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian          .logImpression(DialerImpression.Type.IN_CALL_DIALPAD_HANG_UP_BUTTON_PRESSED);
246ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      inCallScreenDelegate.onEndCallClicked();
247ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else {
248ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      LogUtil.e("InCallFragment.onClick", "unknown view: " + view);
249ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      Assert.fail();
250ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
251ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
252ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
253ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
254ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setPrimary(@NonNull PrimaryInfo primaryInfo) {
255ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.setPrimary", primaryInfo.toString());
256f94391034e9d591c18d04c0b796d944938201f6aAndroid Dialer    setAdapterMedia(primaryInfo.multimediaData(), primaryInfo.showInCallButtonGrid());
257ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    contactGridManager.setPrimary(primaryInfo);
258ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
259f94391034e9d591c18d04c0b796d944938201f6aAndroid Dialer    if (primaryInfo.shouldShowLocation()) {
260ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Hide the avatar to make room for location
261ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      contactGridManager.setAvatarHidden(true);
262ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
263ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Need to let the dialpad move up a little further when location info is being shown
264ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      View dialpadView = getView().findViewById(R.id.incall_dialpad_container);
2651d62ab209130bdacdb64b2cd824b5ff35817b89fwangqi      ViewGroup.LayoutParams params = dialpadView.getLayoutParams();
266ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (params instanceof RelativeLayout.LayoutParams) {
267ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        ((RelativeLayout.LayoutParams) params).removeRule(RelativeLayout.BELOW);
268ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
269ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      dialpadView.setLayoutParams(params);
270ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
271ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
272ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
2732ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian  private void setAdapterMedia(MultimediaData multimediaData, boolean showInCallButtonGrid) {
274d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    if (adapter == null) {
2752ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian      adapter =
2762ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian          new InCallPagerAdapter(getChildFragmentManager(), multimediaData, showInCallButtonGrid);
277d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      pager.setAdapter(adapter);
278d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else {
279d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      adapter.setAttachments(multimediaData);
280d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    }
281ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
28210b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian    if (adapter.getCount() > 1 && getResources().getInteger(R.integer.incall_num_rows) > 1) {
283fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian      paginator.setVisibility(View.VISIBLE);
284fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian      paginator.setupWithViewPager(pager);
28510b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian      pager.setSwipingLocked(false);
286ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (!stateRestored) {
2879050823ccf6f512e06ad65c8a741cb17cbc4a833Eric Erfanian        handler.postDelayed(pagerRunnable, 4_000);
28810b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian      } else {
28910b34a5ebf12e97ecba0caf3c8e30b476b038a96Eric Erfanian        pager.setCurrentItem(adapter.getButtonGridPosition(), false /* animateScroll */);
290ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
2918369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian    } else {
2928369df095a73a77b3715f8ae7ba06089cebca4ceEric Erfanian      paginator.setVisibility(View.GONE);
293ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
294ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
295ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
296ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
297ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setSecondary(@NonNull SecondaryInfo secondaryInfo) {
298ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.setSecondary", secondaryInfo.toString());
299ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    updateButtonStates();
300ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
301ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (!isAdded()) {
302ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      savedSecondaryInfo = secondaryInfo;
303ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return;
304ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
305ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    savedSecondaryInfo = null;
306ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
307ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Fragment oldBanner = getChildFragmentManager().findFragmentById(R.id.incall_on_hold_banner);
3089e335e2d4fb43b22c7f95b2e9d4e048798e8e239Android Dialer    if (secondaryInfo.shouldShow()) {
309ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      transaction.replace(R.id.incall_on_hold_banner, OnHoldFragment.newInstance(secondaryInfo));
310ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    } else {
311ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (oldBanner != null) {
312ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        transaction.remove(oldBanner);
313ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
314ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
315ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    transaction.setCustomAnimations(R.anim.abc_slide_in_top, R.anim.abc_slide_out_top);
31683d8a62ee2b2262941590ff5ef35986dc1df1fa1yueg    transaction.commitNowAllowingStateLoss();
317ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
318ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
319ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
320ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setCallState(@NonNull PrimaryCallState primaryCallState) {
321ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.setCallState", primaryCallState.toString());
322ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    contactGridManager.setCallState(primaryCallState);
3232ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian    getButtonController(InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY)
32431fe99856b34854bd36a17d02b774095dcfe51a6Android Dialer        .setAllowed(primaryCallState.swapToSecondaryButtonState() != ButtonState.NOT_SUPPORT);
3252ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian    getButtonController(InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY)
32631fe99856b34854bd36a17d02b774095dcfe51a6Android Dialer        .setEnabled(primaryCallState.swapToSecondaryButtonState() == ButtonState.ENABLED);
327ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    buttonChooser =
32831fe99856b34854bd36a17d02b774095dcfe51a6Android Dialer        ButtonChooserFactory.newButtonChooser(
32931fe99856b34854bd36a17d02b774095dcfe51a6Android Dialer            voiceNetworkType, primaryCallState.isWifi(), phoneType);
330ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    updateButtonStates();
331ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
332ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
333ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
334ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setEndCallButtonEnabled(boolean enabled, boolean animate) {
335ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (endCallButton != null) {
336ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      endCallButton.setEnabled(enabled);
337ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
338ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
339ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
340ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
341ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void showManageConferenceCallButton(boolean visible) {
342ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    getButtonController(InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE).setAllowed(visible);
343ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    getButtonController(InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE).setEnabled(visible);
344ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    updateButtonStates();
345ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
346ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
347ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
348ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public boolean isManageConferenceVisible() {
349ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return getButtonController(InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE).isAllowed();
350ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
351ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
352ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
353ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
354ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    contactGridManager.dispatchPopulateAccessibilityEvent(event);
355ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
356ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
357ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
358ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void showNoteSentToast() {
359ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.showNoteSentToast", null);
360ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Toast.makeText(getContext(), R.string.incall_note_sent, Toast.LENGTH_LONG).show();
361ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
362ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
363ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
364ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void updateInCallScreenColors() {}
365ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
366ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
367ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onInCallScreenDialpadVisibilityChange(boolean isShowing) {
368ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.onInCallScreenDialpadVisibilityChange", "isShowing: " + isShowing);
369ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // Take note that the dialpad button isShowing
370ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    getButtonController(InCallButtonIds.BUTTON_DIALPAD).setChecked(isShowing);
371ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
372ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // This check is needed because there is a race condition where we attempt to update
373ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // ButtonGridFragment before it is ready, so we check whether it is ready first and once it is
374ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // ready, #onButtonGridCreated will mark the dialpad button as isShowing.
375ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (inCallButtonGridFragment != null) {
376ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Update the Android Button's state to isShowing.
377ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      inCallButtonGridFragment.onInCallScreenDialpadVisibilityChange(isShowing);
378ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
379ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
380ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
381ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
382ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public int getAnswerAndDialpadContainerResourceId() {
383ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return R.id.incall_dialpad_container;
384ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
385ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
386ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
387ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public Fragment getInCallScreenFragment() {
388ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return this;
389ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
390ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
391ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
392ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void showButton(@InCallButtonIds int buttonId, boolean show) {
393ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.v(
394ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        "InCallFragment.showButton",
395ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        "buttionId: %s, show: %b",
396ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        InCallButtonIdsExtension.toString(buttonId),
397ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        show);
398ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (isSupportedButton(buttonId)) {
399ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      getButtonController(buttonId).setAllowed(show);
4002ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian      if (buttonId == InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO && show) {
4012ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian        Logger.get(getContext())
4022ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian            .logImpression(DialerImpression.Type.UPGRADE_TO_VIDEO_CALL_BUTTON_SHOWN);
4032ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian      }
404ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
405ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
406ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
407ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
408ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void enableButton(@InCallButtonIds int buttonId, boolean enable) {
409ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.v(
410ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        "InCallFragment.enableButton",
411ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        "buttonId: %s, enable: %b",
412ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        InCallButtonIdsExtension.toString(buttonId),
413ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        enable);
414ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (isSupportedButton(buttonId)) {
415ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      getButtonController(buttonId).setEnabled(enable);
416ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
417ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
418ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
419ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
420ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setEnabled(boolean enabled) {
421ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.v("InCallFragment.setEnabled", "enabled: " + enabled);
422ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    for (ButtonController buttonController : buttonControllers) {
423ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      buttonController.setEnabled(enabled);
424ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
425ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
426ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
427ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
428ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setHold(boolean value) {
429ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    getButtonController(InCallButtonIds.BUTTON_HOLD).setChecked(value);
430ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
431ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
432ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
433ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setCameraSwitched(boolean isBackFacingCamera) {}
434ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
435ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
436ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setVideoPaused(boolean isPaused) {}
437ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
438ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
439ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void setAudioState(CallAudioState audioState) {
440ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.setAudioState", "audioState: " + audioState);
441ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    ((SpeakerButtonController) getButtonController(InCallButtonIds.BUTTON_AUDIO))
442ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        .setAudioState(audioState);
443ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    getButtonController(InCallButtonIds.BUTTON_MUTE).setChecked(audioState.isMuted());
444ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
445ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
446ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
447ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void updateButtonStates() {
448ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // When the incall screen is ready, this method is called from #setSecondary, even though the
449ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // incall button ui is not ready yet. This method is called again once the incall button ui is
450ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    // ready though, so this operation is safe and will be executed asap.
451ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    if (inCallButtonGridFragment == null) {
452ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      return;
453ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
454ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    int numVisibleButtons =
455ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        inCallButtonGridFragment.updateButtonStates(
456ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian            buttonControllers, buttonChooser, voiceNetworkType, phoneType);
457ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
458ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    int visibility = numVisibleButtons == 0 ? View.GONE : View.VISIBLE;
459ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    pager.setVisibility(visibility);
460fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian    if (adapter != null
461fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian        && adapter.getCount() > 1
462fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian        && getResources().getInteger(R.integer.incall_num_rows) > 1) {
463fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian      paginator.setVisibility(View.VISIBLE);
464fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian      pager.setSwipingLocked(false);
465fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian    } else {
466fc37b02f5d3381a7882770941e461b13b679b6efEric Erfanian      paginator.setVisibility(View.GONE);
467d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      if (adapter != null) {
468d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        pager.setSwipingLocked(true);
469d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian        pager.setCurrentItem(adapter.getButtonGridPosition());
470d8046e520a866b9948ee9ba47cf642b441ca8e23Eric Erfanian      }
471ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
472ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
473ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
474ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
4758d662cae2c05b5e256e7bb826abf05fb9ace133dwangqi  public void updateInCallButtonUiColors(@ColorInt int color) {
4768d662cae2c05b5e256e7bb826abf05fb9ace133dwangqi    inCallButtonGridFragment.updateButtonColor(color);
4778d662cae2c05b5e256e7bb826abf05fb9ace133dwangqi  }
478ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
479ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
480ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public Fragment getInCallButtonUiFragment() {
481ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return this;
482ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
483ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
484ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
485ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void showAudioRouteSelector() {
486ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    AudioRouteSelectorDialogFragment.newInstance(inCallButtonUiDelegate.getCurrentAudioState())
487ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        .show(getChildFragmentManager(), null);
488ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
489ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
490ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
491ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onAudioRouteSelected(int audioRoute) {
492ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallButtonUiDelegate.setAudioRoute(audioRoute);
493ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
494ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
4952ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian  @Override
4962ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian  public void onAudioRouteSelectorDismiss() {}
4972ca4318cc1ee57dda907ba2069bd61d162b1baefEric Erfanian
498ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @NonNull
499ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
500ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public ButtonController getButtonController(@InCallButtonIds int id) {
501ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    for (ButtonController buttonController : buttonControllers) {
502ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      if (buttonController.getInCallButtonId() == id) {
503ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian        return buttonController;
504ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      }
505ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
506ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    Assert.fail();
507ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return null;
508ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
509ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
510ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
511ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onButtonGridCreated(InCallButtonGridFragment inCallButtonGridFragment) {
512ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.onButtonGridCreated", "InCallUiReady");
513ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    this.inCallButtonGridFragment = inCallButtonGridFragment;
514ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallButtonUiDelegate.onInCallButtonUiReady(this);
515ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    updateButtonStates();
516ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
517ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
518ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
519ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void onButtonGridDestroyed() {
520ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    LogUtil.i("InCallFragment.onButtonGridCreated", "InCallUiUnready");
521ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    inCallButtonUiDelegate.onInCallButtonUiUnready();
522ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    this.inCallButtonGridFragment = null;
523ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
524ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
525ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
526ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public boolean isShowingLocationUi() {
527d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    Fragment fragment = getLocationFragment();
528ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    return fragment != null && fragment.isVisible();
529ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
530ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian
531ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  @Override
532ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  public void showLocationUi(@Nullable Fragment locationUi) {
533d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    boolean isVisible = isShowingLocationUi();
534d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    if (locationUi != null && !isVisible) {
535ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Show the location fragment.
536ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      getChildFragmentManager()
537ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          .beginTransaction()
538ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          .replace(R.id.incall_location_holder, locationUi)
539ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian          .commitAllowingStateLoss();
540d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    } else if (locationUi == null && isVisible) {
541ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian      // Hide the location fragment
542d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      getChildFragmentManager()
543d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          .beginTransaction()
544d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          .remove(getLocationFragment())
545d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian          .commitAllowingStateLoss();
546ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian    }
547ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian  }
548d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
549d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  @Override
550d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
551d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    super.onMultiWindowModeChanged(isInMultiWindowMode);
552d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    if (isInMultiWindowMode == isShowingLocationUi()) {
553d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      LogUtil.i("InCallFragment.onMultiWindowModeChanged", "hide = " + isInMultiWindowMode);
554d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      // Need to show or hide location
555d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian      showLocationUi(isInMultiWindowMode ? null : getLocationFragment());
556d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    }
5571d62ab209130bdacdb64b2cd824b5ff35817b89fwangqi    contactGridManager.onMultiWindowModeChanged(isInMultiWindowMode);
558d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
559d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian
560d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  private Fragment getLocationFragment() {
561d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian    return getChildFragmentManager().findFragmentById(R.id.incall_location_holder);
562d5e47f6da5b08b13ecdfa7f1edc7e12aeb83fab9Eric Erfanian  }
563ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian}
564