通话记录分析 --- 通话详情 之一 

一.通话记录 视频拨号按钮

1.1.packages\apps\Dialer\res\values-zh-rCN\strings.xml

    <string name="call_log_action_video_call" msgid="7724301709041128296">"视频通话"</string>
    <string name="call_log_action_send_message" msgid="5679719296905285131">"发送短信"</string>
    <string name="call_log_action_details" msgid="701345508704970622">"通话详情"</string>

 1.1.2.packages\apps\Dialer\res\layout\call_log_list_item_actions.xml

    <LinearLayout
        android:id="@+id/video_call_action"
        style="@style/CallLogActionStyle">

        <ImageView
            style="@style/CallLogActionIconStyle"
            android:src="@drawable/ic_videocam_24dp" />

        <TextView
            style="@style/CallLogActionTextStyle"
            android:text="@string/call_log_action_video_call" />

    </LinearLayout>

1.2. 加载控件  

packages\apps\Dialer\src\com\android\dialer\calllog\CallLogListItemViewHolder.java 

    public void inflateActionViewStub() {
            ……
            videoCallButtonView = actionsView.findViewById(R.id.video_call_action);
            videoCallButtonView.setOnClickListener(this);        

 1.3.

// If one of the calls had video capabilities, show the video call button.

//如果其中一个通话具有视频功能,则显示视频通话按钮。

mCallLogCache.isVideoEnabled()->false
canPlaceCallToNumber->true
phoneCallDetailsViews.callTypeIcons.isVideoShown()->false

    private void bindActionButtons() {
        boolean canPlaceCallToNumber = PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation);

        if (!TextUtils.isEmpty(voicemailUri) && canPlaceCallToNumber) {
            callButtonView.setTag(IntentProvider.getReturnCallIntentProvider(number));
            ((TextView) callButtonView.findViewById(R.id.call_action_text))
                    .setText(TextUtils.expandTemplate(
                            mContext.getString(R.string.call_log_action_call),
                            nameOrNumber));
            TextView callTypeOrLocationView = ((TextView) callButtonView.findViewById(
                    R.id.call_type_or_location_text));
            if (callType == Calls.VOICEMAIL_TYPE && !TextUtils.isEmpty(callTypeOrLocation)) {
                callTypeOrLocationView.setText(callTypeOrLocation);
                callTypeOrLocationView.setVisibility(View.VISIBLE);
            } else {
                callTypeOrLocationView.setVisibility(View.GONE);
            }
            callButtonView.setVisibility(View.VISIBLE);
        } else {
            callButtonView.setVisibility(View.GONE);
        }

        // If one of the calls had video capabilities, show the video call button.
        if (mCallLogCache.isVideoEnabled() && canPlaceCallToNumber &&
                phoneCallDetailsViews.callTypeIcons.isVideoShown()) {
            videoCallButtonView.setTag(IntentProvider.getReturnVideoCallIntentProvider(number));
            videoCallButtonView.setVisibility(View.VISIBLE);
        } else {
            videoCallButtonView.setVisibility(View.GONE);
        }

……

A.通话是否具有视频功能

 

B.添加拨号的intent  videoCallButtonView.setTag(IntentProvider.getReturnVideoCallIntentProvider(number));

b.1. packages\apps\Dialer\src\com\android\dialer\calllog\IntentProvider.java

主要看 new IntentProvider() 类中 getIntent 方法

    public static IntentProvider getReturnVideoCallIntentProvider(final String number) {
        return getReturnVideoCallIntentProvider(number, null);
    }

    public static IntentProvider getReturnVideoCallIntentProvider(final String number,
            final PhoneAccountHandle accountHandle) {
        return new IntentProvider() {
            @Override
            public Intent getIntent(Context context) {
                return new CallIntentBuilder(number)
                        .setPhoneAccountHandle(accountHandle)
                        .setCallInitiationType(LogState.INITIATION_CALL_LOG)
                        .setIsVideoCall(true)
                        .build();
            }
        };
    }  

public abstract Intent getIntent(Context context);

没想到IntentProvider 也是个抽象类  public abstract class IntentProvider  {

b.2. packages\apps\Dialer\src\com\android\dialer\util\IntentUtil.java   构建intent   // 普通电话为VideoProfile.STATE_AUDIO_ONLY

    public static class CallIntentBuilder {
        private Uri mUri;
        private int mCallInitiationType;
        private PhoneAccountHandle mPhoneAccountHandle;
        private boolean mIsVideoCall = false;
       ……
        public Intent build() {
            return getCallIntent(
                    mUri,
                    mPhoneAccountHandle,
                    mIsVideoCall ? VideoProfile.STATE_BIDIRECTIONAL : VideoProfile.STATE_AUDIO_ONLY,
                    mCallInitiationType);
        }
    }  

1.4.按钮监听事件 走 else startActivityWithErrorToast

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.primary_action_button && !TextUtils.isEmpty(voicemailUri)) {
            mVoicemailPrimaryActionButtonClicked = true;
            mExpandCollapseListener.onClick(primaryActionView);
        } else if (view.getId() == R.id.call_with_note_action) {
            CallSubjectDialog.start(
                    (Activity) mContext,
                    info.photoId,
                    info.photoUri,
                    info.lookupUri,
                    (String) nameOrNumber /* top line of contact view in call subject dialog */,
                    isBusiness,
                    number,
                    TextUtils.isEmpty(info.name) ? null : displayNumber, /* second line of contact
                                                                           view in dialog. */
                    numberType, /* phone number type (e.g. mobile) in second line of contact view */
                    accountHandle);
        } else {
            final IntentProvider intentProvider = (IntentProvider) view.getTag();
            if (intentProvider != null) {
                final Intent intent = intentProvider.getIntent(mContext);
                // See IntentProvider.getCallDetailIntentProvider() for why this may be null.
                if (intent != null) {
                    DialerUtils.startActivityWithErrorToast(mContext, intent);
                }
            }
        }
    }

1.5.packages\apps\Dialer\src\com\android\dialer\util\DialerUtils.java

 intent.getAction()->android.intent.action.CALL 处理拨号

    public static void startActivityWithErrorToast(Context context, Intent intent, int msgId) {
        try {
            if ((IntentUtil.CALL_ACTION.equals(intent.getAction())
                            && context instanceof Activity)) {
                // All dialer-initiated calls should pass the touch point to the InCallUI
                Point touchPoint = TouchPointManager.getInstance().getPoint();
                if (touchPoint.x != 0 || touchPoint.y != 0) {
                    Bundle extras;
                    // Make sure to not accidentally clobber any existing extras
                    if (intent.hasExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS)) {
                        extras = intent.getParcelableExtra(
                                TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS);
                    } else {
                        extras = new Bundle();
                    }
                    extras.putParcelable(TouchPointManager.TOUCH_POINT, touchPoint);
                    intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
                }

                final boolean hasCallPermission = TelecomUtil.placeCall((Activity) context, intent);
                if (!hasCallPermission) {
                    // TODO: Make calling activity show request permission dialog and handle
                    // callback results appropriately.
                    Toast.makeText(context, "Cannot place call without Phone permission",
                            Toast.LENGTH_SHORT);
                }
            } else {
                context.startActivity(intent);
            }
        } catch (ActivityNotFoundException e) {
            Toast.makeText(context, msgId, Toast.LENGTH_SHORT).show();
        }
    }