13d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer/*
2bfa1ab18a847f1e3b60c2e3fca35d0d923d7fa61Yuzhou * Copyright (C) 2018 The Android Open Source Project
33d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer *
43d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Licensed under the Apache License, Version 2.0 (the "License");
53d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * you may not use this file except in compliance with the License.
63d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * You may obtain a copy of the License at
73d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer *
83d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer *      http://www.apache.org/licenses/LICENSE-2.0
93d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer *
103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Unless required by applicable law or agreed to in writing, software
113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * distributed under the License is distributed on an "AS IS" BASIS,
123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * See the License for the specific language governing permissions and
143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * limitations under the License.
153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer */
163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerpackage com.android.car.dialer;
173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.ContentResolver;
193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.Context;
203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.res.Resources;
213d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.graphics.Color;
223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.os.Bundle;
233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.os.Handler;
243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.support.v4.app.Fragment;
253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.telecom.Call;
263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.telecom.CallAudioState;
273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.text.TextUtils;
283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.text.format.DateUtils;
293d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.util.Log;
3017d5ac7d0b429687765e940279726623f5f5f823Anthony Chenimport android.util.SparseArray;
313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.KeyEvent;
323d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.LayoutInflater;
333d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.MotionEvent;
343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.View;
353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.ViewGroup;
363d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.animation.AccelerateDecelerateInterpolator;
373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.animation.Animation;
383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.view.animation.Transformation;
393d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.widget.ImageButton;
403d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.widget.ImageView;
413d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.widget.TextView;
4217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
439c60bc83bd37ae212e66f2e27b821cebbe7beeb2Rakesh Iyerimport com.android.car.apps.common.FabDrawable;
443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport com.android.car.dialer.telecom.TelecomUtils;
453d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport com.android.car.dialer.telecom.UiCall;
463d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport com.android.car.dialer.telecom.UiCallManager;
471a3bec341419ad5741f4efc23bfd5144dccf56e1Anthony Chenimport com.android.car.dialer.ui.CircleBitmapDrawable;
483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
493d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport java.util.Arrays;
503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport java.util.List;
5117d5ac7d0b429687765e940279726623f5f5f823Anthony Chenimport java.util.Objects;
523d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen/**
5417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen * A fragment that displays information about an on-going call with options to hang up.
5517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen */
567b0a0db49db40e7f5e83c14194a21aaa5dde8dc1Yuzhou@Deprecated
57bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhoupublic class OngoingCallFragment extends Fragment implements CallListener {
5817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private static final String TAG = "OngoingCall";
5917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private static final SparseArray<Character> mDialpadButtonMap = new SparseArray<>();
603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    static {
623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.one, '1');
633d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.two, '2');
643d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.three, '3');
653d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.four, '4');
663d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.five, '5');
673d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.six, '6');
683d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.seven, '7');
693d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.eight, '8');
703d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.nine, '9');
713d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.zero, '0');
723d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.star, '*');
733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mDialpadButtonMap.put(R.id.pound, '#');
743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
7617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private final Handler mHandler = new Handler();
7717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
783d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private UiCall mLastRemovedCall;
793d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private UiCallManager mUiCallManager;
803d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private View mRingingCallControls;
813d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private View mActiveCallControls;
823d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageButton mEndCallButton;
833d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageButton mUnholdCallButton;
843d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageButton mMuteButton;
853d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageButton mToggleDialpadButton;
863d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageButton mSwapButton;
873d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageButton mMergeButton;
883d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageButton mAnswerCallButton;
893d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageButton mRejectCallButton;
903d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private TextView mNameTextView;
913d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private TextView mSecondaryNameTextView;
923d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private TextView mStateTextView;
933d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private TextView mSecondaryStateTextView;
943d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageView mLargeContactPhotoView;
953d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private ImageView mSmallContactPhotoView;
963d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private View mDialpadContainer;
973d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private View mSecondaryCallContainer;
983d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private View mSecondaryCallControls;
993d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private String mLoadedNumber;
1003d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private CharSequence mCallInfoLabel;
1013d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private UiBluetoothMonitor mUiBluetoothMonitor;
1023d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
10317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    static OngoingCallFragment newInstance(UiCallManager callManager,
10417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            UiBluetoothMonitor btMonitor) {
1056ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan        OngoingCallFragment fragment = new OngoingCallFragment();
1066ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan        fragment.mUiCallManager = callManager;
1076ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan        fragment.mUiBluetoothMonitor = btMonitor;
1086ed89513a64aeaadc55268607e556c8299d4d6b4Srinivas Visvanathan        return fragment;
109a16cb24e5b5690af55597ad5c8540a7c90ae146aSrinivas Visvanathan    }
110a16cb24e5b5690af55597ad5c8540a7c90ae146aSrinivas Visvanathan
1113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    @Override
1123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    public void onCreate(Bundle savedInstanceState) {
1133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        super.onCreate(savedInstanceState);
1143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
1153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    @Override
1173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    public void onDestroy() {
1183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        super.onDestroy();
1193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mHandler.removeCallbacks(mUpdateDurationRunnable);
1203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mHandler.removeCallbacks(mStopDtmfToneRunnable);
1213d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mLoadedNumber = null;
1223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
1233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    @Override
1253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    public View onCreateView(LayoutInflater inflater, ViewGroup container,
12617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            Bundle savedInstanceState) {
1273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        View view = inflater.inflate(R.layout.ongoing_call, container, false);
12817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        initializeViews(view);
12917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        initializeClickListeners();
13017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
13117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        List<View> dialpadViews = Arrays.asList(
132676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.one),
133676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.two),
134676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.three),
135676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.four),
136676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.five),
137676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.six),
138676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.seven),
139676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.eight),
140676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.nine),
141676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.zero),
142676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                mDialpadContainer.findViewById(R.id.pound),
14317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                mDialpadContainer.findViewById(R.id.star));
144676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer
145676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        // In touch screen, we need to adjust the InCall card for the narrow screen to show the
146676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        // full dial pad.
14717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        for (View dialpadView : dialpadViews) {
148676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer            dialpadView.setOnTouchListener(mDialpadTouchListener);
149676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer            dialpadView.setOnKeyListener(mDialpadKeyListener);
1503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
1513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
15217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        updateCalls();
15317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
15417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        return view;
15517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    }
15617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
15717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private void initializeViews(View parent) {
15817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mRingingCallControls = parent.findViewById(R.id.ringing_call_controls);
15917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mActiveCallControls = parent.findViewById(R.id.active_call_controls);
16017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mEndCallButton = parent.findViewById(R.id.end_call);
16117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mUnholdCallButton = parent.findViewById(R.id.unhold_call);
16217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mMuteButton = parent.findViewById(R.id.mute);
16317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mToggleDialpadButton = parent.findViewById(R.id.toggle_dialpad);
16417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mDialpadContainer = parent.findViewById(R.id.dialpad_container);
16517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mNameTextView = parent.findViewById(R.id.name);
16617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSecondaryNameTextView = parent.findViewById(R.id.name_secondary);
16717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mStateTextView = parent.findViewById(R.id.info);
16817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSecondaryStateTextView = parent.findViewById(R.id.info_secondary);
16917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mLargeContactPhotoView = parent.findViewById(R.id.large_contact_photo);
17017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSmallContactPhotoView = parent.findViewById(R.id.small_contact_photo);
17117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSecondaryCallContainer = parent.findViewById(R.id.secondary_call_container);
17217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSecondaryCallControls = parent.findViewById(R.id.secondary_call_controls);
17317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSwapButton = parent.findViewById(R.id.swap);
17417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mMergeButton = parent.findViewById(R.id.merge);
17517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mAnswerCallButton = parent.findViewById(R.id.answer_call_button);
17617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mRejectCallButton = parent.findViewById(R.id.reject_call_button);
17717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
17817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        Context context = getContext();
17917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        FabDrawable drawable = new FabDrawable(context);
18017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        drawable.setFabAndStrokeColor(context.getColor(R.color.phone_call));
18117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mAnswerCallButton.setBackground(drawable);
18217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
18317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        drawable = new FabDrawable(context);
18417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        drawable.setFabAndStrokeColor(context.getColor(R.color.phone_end_call));
18517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mEndCallButton.setBackground(drawable);
18617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
18717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        drawable = new FabDrawable(context);
18817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        drawable.setFabAndStrokeColor(context.getColor(R.color.phone_call));
18917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mUnholdCallButton.setBackground(drawable);
19017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    }
19117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
19217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private void initializeClickListeners() {
1936f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mAnswerCallButton.setOnClickListener((unusedView) -> {
1946f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            UiCall call = mUiCallManager.getCallWithState(Call.STATE_RINGING);
1956f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            if (call == null) {
1966f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                Log.w(TAG, "There is no incoming call to answer.");
1976f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                return;
1983d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
1996f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            mUiCallManager.answerCall(call);
2003d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        });
2013d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2026f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mRejectCallButton.setOnClickListener((unusedView) -> {
2036f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            UiCall call = mUiCallManager.getCallWithState(Call.STATE_RINGING);
2046f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            if (call == null) {
2056f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                Log.w(TAG, "There is no incoming call to reject.");
2066f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                return;
2073d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
2086f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            mUiCallManager.rejectCall(call, false, null);
2093d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        });
2103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2116f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mEndCallButton.setOnClickListener((unusedView) -> {
2126f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            UiCall call = mUiCallManager.getPrimaryCall();
2136f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            if (call == null) {
2146f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                Log.w(TAG, "There is no active call to end.");
2156f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                return;
2163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
2176f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            mUiCallManager.disconnectCall(call);
2183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        });
2193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2206f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mUnholdCallButton.setOnClickListener((unusedView) -> {
2216f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            UiCall call = mUiCallManager.getPrimaryCall();
2226f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            if (call == null) {
2236f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                Log.w(TAG, "There is no active call to unhold.");
2246f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                return;
2253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
2266f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            mUiCallManager.unholdCall(call);
2273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        });
2283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
22917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mMuteButton.setOnClickListener(
23017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                (unusedView) -> mUiCallManager.setMuted(!mUiCallManager.getMuted()));
2313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2326f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mSwapButton.setOnClickListener((unusedView) -> {
2336f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            UiCall call = mUiCallManager.getPrimaryCall();
2346f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            if (call == null) {
2356f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                Log.w(TAG, "There is no active call to hold.");
2366f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                return;
2376f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            }
2386f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            if (call.getState() == Call.STATE_HOLDING) {
2396f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                mUiCallManager.unholdCall(call);
2406f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            } else {
2416f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                mUiCallManager.holdCall(call);
2423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
2433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        });
2443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2456f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mMergeButton.setOnClickListener((unusedView) -> {
2466f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            UiCall call = mUiCallManager.getPrimaryCall();
24717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            UiCall secondaryCall = mUiCallManager.getSecondaryCall();
24817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            if (call == null || secondaryCall == null) {
2496f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                Log.w(TAG, "There aren't two call to merge.");
2506f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                return;
2513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
2526f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan
25317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            mUiCallManager.conference(call, secondaryCall);
2543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        });
2553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2566f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mToggleDialpadButton.setOnClickListener((unusedView) -> {
2576f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            if (mToggleDialpadButton.isActivated()) {
2586f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                closeDialpad();
2596f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            } else {
2606f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                openDialpad(true /*animate*/);
2613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
2623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        });
2633d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
2643d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2653d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    @Override
2663d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    public void onDestroyView() {
2673d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        super.onDestroyView();
2683d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
2693d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2703d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    @Override
2713d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    public void onStart() {
2723d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        super.onStart();
2733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        trySpeakerAudioRouteIfNecessary();
2743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
2753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
27617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private void updateCalls() {
27717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (Log.isLoggable(TAG, Log.DEBUG)) {
27817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            Log.d(TAG, "updateCalls(); Primary call: " + mUiCallManager.getPrimaryCall()
27917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    + "; Secondary call:" + mUiCallManager.getSecondaryCall());
28017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        }
28117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
2823d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mHandler.removeCallbacks(mUpdateDurationRunnable);
2833d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
28417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        UiCall primaryCall = mUiCallManager.getPrimaryCall();
28517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        CharSequence disconnectCauseLabel = mLastRemovedCall == null
28617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                ? null : mLastRemovedCall.getDisconnectCause();
28717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (primaryCall == null && !TextUtils.isEmpty(disconnectCauseLabel)) {
2883d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            closeDialpad();
2893d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            setStateText(disconnectCauseLabel);
2903d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return;
29117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        }
29217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
29317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (primaryCall == null || primaryCall.getState() == Call.STATE_DISCONNECTED) {
2943d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            closeDialpad();
2953d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            setStateText(getString(R.string.call_state_call_ended));
2963d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mRingingCallControls.setVisibility(View.GONE);
2973d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mActiveCallControls.setVisibility(View.GONE);
2983d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return;
29917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        }
30017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
30117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (primaryCall.getState() == Call.STATE_RINGING) {
3023d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mRingingCallControls.setVisibility(View.VISIBLE);
3033d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mActiveCallControls.setVisibility(View.GONE);
3043d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        } else {
3053d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mRingingCallControls.setVisibility(View.GONE);
3063d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mActiveCallControls.setVisibility(View.VISIBLE);
3073d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
3083d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
30917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        loadContactPhotoForPrimaryNumber(primaryCall.getNumber());
3103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
31117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        String displayName = TelecomUtils.getDisplayName(getContext(), primaryCall);
3123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mNameTextView.setText(displayName);
3133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mNameTextView.setVisibility(TextUtils.isEmpty(displayName) ? View.GONE : View.VISIBLE);
3143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
31517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        Context context = getContext();
31617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        switch (primaryCall.getState()) {
3173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            case Call.STATE_NEW:
3183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                // Since the content resolver call is only cached when a contact is found,
3193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                // this should only be called once on a new call to avoid jank.
3203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                // TODO: consider moving TelecomUtils.getTypeFromNumber into a CursorLoader
32117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                mCallInfoLabel = TelecomUtils.getTypeFromNumber(context, primaryCall.getNumber());
3223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            case Call.STATE_CONNECTING:
3233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            case Call.STATE_DIALING:
3243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            case Call.STATE_SELECT_PHONE_ACCOUNT:
3253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            case Call.STATE_HOLDING:
3263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            case Call.STATE_DISCONNECTED:
3273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                mHandler.removeCallbacks(mUpdateDurationRunnable);
3283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                String callInfoText = TelecomUtils.getCallInfoText(context,
32917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                        primaryCall, mCallInfoLabel);
3303d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                setStateText(callInfoText);
3313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                break;
3323d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            case Call.STATE_ACTIVE:
333a16cb24e5b5690af55597ad5c8540a7c90ae146aSrinivas Visvanathan                if (mUiBluetoothMonitor.isHfpConnected()) {
3343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    mHandler.post(mUpdateDurationRunnable);
3353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                }
3363d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                break;
3373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            case Call.STATE_RINGING:
3383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                Log.w(TAG, "There should not be a ringing call in the ongoing call fragment.");
3393d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                break;
3403d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            default:
34117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                Log.w(TAG, "Unhandled call state: " + primaryCall.getState());
3423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
3433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
3443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        // If it is a voicemail call, open the dialpad (with no animation).
34517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (Objects.equals(primaryCall.getNumber(), TelecomUtils.getVoicemailNumber(context))) {
346676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer            openDialpad(false /*animate*/);
347676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer            mToggleDialpadButton.setVisibility(View.GONE);
3483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        } else {
3493d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mToggleDialpadButton.setVisibility(View.VISIBLE);
3503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
3513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
3523d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        // Handle the holding case.
35317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (primaryCall.getState() == Call.STATE_HOLDING) {
3543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mEndCallButton.setVisibility(View.GONE);
3553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mUnholdCallButton.setVisibility(View.VISIBLE);
3563d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mMuteButton.setVisibility(View.INVISIBLE);
3573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mToggleDialpadButton.setVisibility(View.INVISIBLE);
3583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        } else {
3593d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mEndCallButton.setVisibility(View.VISIBLE);
3603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mUnholdCallButton.setVisibility(View.GONE);
3613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mMuteButton.setVisibility(View.VISIBLE);
3623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mToggleDialpadButton.setVisibility(View.VISIBLE);
3633d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
3643d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
36517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        updateSecondaryCall(primaryCall, mUiCallManager.getSecondaryCall());
3663d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
3673d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
36817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private void updateSecondaryCall(UiCall primaryCall, UiCall secondaryCall) {
36917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (primaryCall == null || secondaryCall == null) {
37017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            mSecondaryCallContainer.setVisibility(View.GONE);
37117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            mSecondaryCallControls.setVisibility(View.GONE);
37217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            return;
3733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
37417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
37517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSecondaryCallContainer.setVisibility(View.VISIBLE);
37617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
37717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (primaryCall.getState() == Call.STATE_ACTIVE
37817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                && secondaryCall.getState() == Call.STATE_HOLDING) {
37917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            mSecondaryCallControls.setVisibility(View.VISIBLE);
38017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        } else {
38117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            mSecondaryCallControls.setVisibility(View.GONE);
3823d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
38317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
38417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        Context context = getContext();
38517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSecondaryNameTextView.setText(TelecomUtils.getDisplayName(context, secondaryCall));
38617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mSecondaryStateTextView.setText(
38717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                TelecomUtils.callStateToUiString(context, secondaryCall.getState()));
38817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
38917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        loadContactPhotoForSecondaryNumber(secondaryCall.getNumber());
3903d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
3913d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
3923d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    /**
39317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     * Loads the contact photo associated with the given number and sets it in the views that
39417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     * correspond with a primary number.
39517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     */
39617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private void loadContactPhotoForPrimaryNumber(String primaryNumber) {
39717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        // Don't reload the image if the number is the same.
39817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        if (Objects.equals(primaryNumber, mLoadedNumber)) {
39917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            return;
40017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        }
40117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
40217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        final ContentResolver cr = getContext().getContentResolver();
40317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        BitmapWorkerTask.BitmapRunnable runnable = new BitmapWorkerTask.BitmapRunnable() {
40417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            @Override
40517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            public void run() {
40617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                if (mBitmap != null) {
40717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    Resources r = getResources();
40817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    mSmallContactPhotoView.setImageDrawable(new CircleBitmapDrawable(r, mBitmap));
40917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    mLargeContactPhotoView.setImageBitmap(mBitmap);
41017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    mLargeContactPhotoView.clearColorFilter();
41117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                } else {
41217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    mSmallContactPhotoView.setImageResource(R.drawable.logo_avatar);
41317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    mLargeContactPhotoView.setImageResource(R.drawable.ic_avatar_bg);
41417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                }
41517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            }
41617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        };
41717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mLoadedNumber = primaryNumber;
41817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        BitmapWorkerTask.loadBitmap(cr, mLargeContactPhotoView, primaryNumber, runnable);
41917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    }
42017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
42117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    /**
42217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     * Loads the contact photo associated with the given number and sets it in the views that
42317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     * correspond to a secondary number.
42417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     */
42517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private void loadContactPhotoForSecondaryNumber(String secondaryNumber) {
42617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        BitmapWorkerTask.BitmapRunnable runnable = new BitmapWorkerTask.BitmapRunnable() {
42717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            @Override
42817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            public void run() {
42917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                if (mBitmap != null) {
43017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    mLargeContactPhotoView.setImageBitmap(mBitmap);
43117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                } else {
43217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    mLargeContactPhotoView.setImageResource(R.drawable.logo_avatar);
43317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                }
43417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            }
43517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        };
43617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
43717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        Context context = getContext();
43817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        BitmapWorkerTask.loadBitmap(context.getContentResolver(), mLargeContactPhotoView,
43917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                secondaryNumber, runnable);
44017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
44117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        int scrimColor = context.getColor(R.color.phone_secondary_call_scrim);
44217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mLargeContactPhotoView.setColorFilter(scrimColor);
44317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    }
44417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
44517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private void setStateText(CharSequence stateText) {
44617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mStateTextView.setText(stateText);
44717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        mStateTextView.setVisibility(TextUtils.isEmpty(stateText) ? View.GONE : View.VISIBLE);
44817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    }
44917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
45017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    /**
45117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     * If the phone is using bluetooth, then do nothing. If the phone is not using bluetooth:
45217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     * <p>
45317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     * <ol>
45417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     *     <li>If the phone supports bluetooth, use it.
45517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     *     <li>If the phone doesn't support bluetooth and support speaker, use speaker
45617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     *     <li>Otherwise, do nothing. Hopefully no phones won't have bt or speaker.
45717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen     * </ol>
4583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     */
4593d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private void trySpeakerAudioRouteIfNecessary() {
4603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (mUiCallManager == null) {
4613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return;
4623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
4633d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
4643d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        int supportedAudioRouteMask = mUiCallManager.getSupportedAudioRouteMask();
4653d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        boolean supportsBluetooth = (supportedAudioRouteMask & CallAudioState.ROUTE_BLUETOOTH) != 0;
4663d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        boolean supportsSpeaker = (supportedAudioRouteMask & CallAudioState.ROUTE_SPEAKER) != 0;
4673d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        boolean isUsingBluetooth =
4683d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                mUiCallManager.getAudioRoute() == CallAudioState.ROUTE_BLUETOOTH;
4693d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
4703d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (supportsBluetooth && !isUsingBluetooth) {
4713d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mUiCallManager.setAudioRoute(CallAudioState.ROUTE_BLUETOOTH);
4723d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        } else if (!supportsBluetooth && supportsSpeaker) {
4733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mUiCallManager.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
4743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
4753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
4763d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
4773d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private void openDialpad(boolean animate) {
4783d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (mToggleDialpadButton.isActivated()) {
4793d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return;
4803d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
4813d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mToggleDialpadButton.setActivated(true);
482676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        // This array of of size 2 because getLocationOnScreen returns (x,y) coordinates.
483676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        int[] location = new int[2];
484676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        mToggleDialpadButton.getLocationOnScreen(location);
4853d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
486676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        // The dialpad should be aligned with the right edge of mToggleDialpadButton.
487676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        int startingMargin = location[1] + mToggleDialpadButton.getWidth();
4883d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
489676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        ViewGroup.MarginLayoutParams layoutParams =
490676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer                (ViewGroup.MarginLayoutParams) mDialpadContainer.getLayoutParams();
4913d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
492676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        if (layoutParams.getMarginStart() != startingMargin) {
493676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer            layoutParams.setMarginStart(startingMargin);
494676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer            mDialpadContainer.setLayoutParams(layoutParams);
4953d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
496676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer
497676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        Animation anim = new DialpadAnimation(getContext(), false /* reverse */, animate);
498676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        mDialpadContainer.startAnimation(anim);
4993d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
5003d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5013d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private void closeDialpad() {
5023d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (!mToggleDialpadButton.isActivated()) {
5033d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return;
5043d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
5053d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        mToggleDialpadButton.setActivated(false);
506676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        Animation anim = new DialpadAnimation(getContext(), true /* reverse */);
507676781bf09b69966f83ba99c1b7ee0c7d6ae00e4Rakesh Iyer        mDialpadContainer.startAnimation(anim);
5083d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
5093d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private final View.OnTouchListener mDialpadTouchListener = new View.OnTouchListener() {
5113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        @Override
5133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        public boolean onTouch(View v, MotionEvent event) {
5143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            Character digit = mDialpadButtonMap.get(v.getId());
5153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (digit == null) {
5163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                Log.w(TAG, "Unknown dialpad button pressed.");
5173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                return false;
5183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
5193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (event.getAction() == MotionEvent.ACTION_DOWN) {
5203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                v.setPressed(true);
52117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                mUiCallManager.playDtmfTone(mUiCallManager.getPrimaryCall(), digit);
5223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                return true;
5233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            } else if (event.getAction() == MotionEvent.ACTION_UP) {
5243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                v.setPressed(false);
5253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                v.performClick();
52617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                mUiCallManager.stopDtmfTone(mUiCallManager.getPrimaryCall());
5273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                return true;
5283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
5293d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5303d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return false;
5313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
5323d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    };
5333d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private final View.OnKeyListener mDialpadKeyListener = new View.OnKeyListener() {
5353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        @Override
5363d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        public boolean onKey(View v, int keyCode, KeyEvent event) {
5373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            Character digit = mDialpadButtonMap.get(v.getId());
5383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (digit == null) {
5393d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                Log.w(TAG, "Unknown dialpad button pressed.");
5403d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                return false;
5413d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
5423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (event.getKeyCode() != KeyEvent.KEYCODE_DPAD_CENTER) {
5443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                return false;
5453d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
5463d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5473d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (event.getAction() == KeyEvent.ACTION_DOWN) {
5483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                v.setPressed(true);
54917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                mUiCallManager.playDtmfTone(mUiCallManager.getPrimaryCall(), digit);
5503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                return true;
5513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            } else if (event.getAction() == KeyEvent.ACTION_UP) {
5523d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                v.setPressed(false);
55317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                mUiCallManager.stopDtmfTone(mUiCallManager.getPrimaryCall());
5543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                return true;
5553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
5563d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return false;
5583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
5593d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    };
5603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private final Runnable mUpdateDurationRunnable = new Runnable() {
5623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        @Override
5633d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        public void run() {
56417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            UiCall primaryCall = mUiCallManager.getPrimaryCall();
56517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            if (primaryCall.getState() != Call.STATE_ACTIVE) {
5663d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                return;
5673d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
5683d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            String callInfoText = TelecomUtils.getCallInfoText(getContext(),
56917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    primaryCall, mCallInfoLabel);
5703d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            setStateText(callInfoText);
5713d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mHandler.postDelayed(this /* runnable */, DateUtils.SECOND_IN_MILLIS);
5723d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
5733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
5743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    };
5753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
57617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen    private final Runnable mStopDtmfToneRunnable =
57717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            () -> mUiCallManager.stopDtmfTone(mUiCallManager.getPrimaryCall());
57817d5ac7d0b429687765e940279726623f5f5f823Anthony Chen
579bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    @Override
580bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    public void onAudioStateChanged(boolean isMuted, int route, int supportedRouteMask) {
581bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        if (Log.isLoggable(TAG, Log.DEBUG)) {
582bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou            Log.d(TAG, String.format(
583bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou                "onAudioStateChanged(); isMuted: %b, audioRoute: %d, supportedAudioRouteMask: %d",
584bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou                isMuted, route, supportedRouteMask));
585bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        }
586bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        mMuteButton.setActivated(isMuted);
587bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        trySpeakerAudioRouteIfNecessary();
588bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    }
589bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou
590bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    @Override
591bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    public void onCallStateChanged(UiCall call, int state) {
592bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        if (Log.isLoggable(TAG, Log.DEBUG)) {
593bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou            Log.d(TAG, String.format("onCallStateChanged(); call: %s, state: %s", call, state));
594bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        }
595bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        updateCalls();
596bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    }
597bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou
598bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    @Override
599bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    public void onCallUpdated(UiCall call) {
600bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        if (Log.isLoggable(TAG, Log.DEBUG)) {
601bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou            Log.d(TAG, "onCallUpdated(); call: " + call);
602bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        }
603bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        updateCalls();
604bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    }
605bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou
606bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    @Override
607bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    public void onCallAdded(UiCall call) {
608bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        if (Log.isLoggable(TAG, Log.DEBUG)) {
609bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou            Log.d(TAG, "onCallAdded(); call: " + call);
610bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        }
611bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        updateCalls();
612bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        trySpeakerAudioRouteIfNecessary();
613bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    }
614bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou
615bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    @Override
616bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    public void onCallRemoved(UiCall call) {
617bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        if (Log.isLoggable(TAG, Log.DEBUG)) {
618bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou            Log.d(TAG, "onCallRemoved(); call: " + call);
619bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        }
620bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        mLastRemovedCall = call;
621bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou        updateCalls();
622bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou    }
623bb51ff67f2973488079684ca58924a1c4b712dabJohnny Zhou
6243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private final class DialpadAnimation extends Animation {
6253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        private static final int DURATION = 300;
6263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        private static final float MAX_SCRIM_ALPHA = 0.6f;
6273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
6283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        private final int mStartingTranslation;
6293d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        private final int mScrimColor;
6303d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        private final boolean mReverse;
6313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
63217d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        DialpadAnimation(Context context, boolean reverse) {
6333d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            this(context, reverse, true);
6343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
6353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
63617d5ac7d0b429687765e940279726623f5f5f823Anthony Chen        DialpadAnimation(Context context, boolean reverse, boolean animate) {
6373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            setDuration(animate ? DURATION : 0);
6383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            setInterpolator(new AccelerateDecelerateInterpolator());
63917d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            mStartingTranslation = context.getResources().getDimensionPixelOffset(
64017d5ac7d0b429687765e940279726623f5f5f823Anthony Chen                    R.dimen.in_call_card_dialpad_translation_x);
64117d5ac7d0b429687765e940279726623f5f5f823Anthony Chen            mScrimColor = context.getColor(R.color.phone_theme);
6423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mReverse = reverse;
6433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
6443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
6453d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        @Override
6463d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        protected void applyTransformation(float interpolatedTime, Transformation t) {
6473d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (mReverse) {
6483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                interpolatedTime = 1f - interpolatedTime;
6493d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
6503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            int translationX = (int) (mStartingTranslation * (1f - interpolatedTime));
6513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mDialpadContainer.setTranslationX(translationX);
6523d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mDialpadContainer.setAlpha(interpolatedTime);
6533d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (interpolatedTime == 0f) {
6543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                mDialpadContainer.setVisibility(View.GONE);
6553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            } else {
6563d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                mDialpadContainer.setVisibility(View.VISIBLE);
6573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
6583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            float alpha = 255f * interpolatedTime * MAX_SCRIM_ALPHA;
6593d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mLargeContactPhotoView.setColorFilter(Color.argb((int) alpha, Color.red(mScrimColor),
6603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    Color.green(mScrimColor), Color.blue(mScrimColor)));
6613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
6623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mSecondaryNameTextView.setAlpha(1f - interpolatedTime);
6633d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            mSecondaryStateTextView.setAlpha(1f - interpolatedTime);
6643d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
6653d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
6663d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer}
667