Android Dialer源码分析之去电流程

2023-05-16

Android的拨号流程,从拨号盘的点击拨号按钮开始,
DialpadFragment.java

  @Override
  public void onClick(View view) {
    int resId = view.getId();
    if (resId == R.id.dialpad_floating_action_button) {
      view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
      handleDialButtonPressed();
    } 
    ....
  }
private void handleDialButtonPressed() {
	...
	final String number = digits.getText().toString();
	...
    PreCall.start(getContext(), new CallIntentBuilder(number, CallInitiationType.Type.DIALPAD));
    ...
  }
  static void start(Context context, CallIntentBuilder builder) {
    DialerUtils.startActivityWithErrorToast(context, getIntent(context, builder));
  }
  public static void startActivityWithErrorToast(Context context, Intent intent) {
	...	
    startActivityWithErrorToast(context, intent, R.string.activity_not_available);
  }
public static void startActivityWithErrorToast(
      final Context context, final Intent intent, int msgId) {
    try {
      if ((Intent.ACTION_CALL.equals(intent.getAction()))) {
        Point touchPoint = TouchPointManager.getInstance().getPoint();
        if (touchPoint.x != 0 || touchPoint.y != 0) {
          Bundle 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);
        }
		...
        placeCallOrMakeToast(context, intent);
        ...
      } else {
        context.startActivity(intent);
      }
    } catch (ActivityNotFoundException e) {
      Toast.makeText(context, msgId, Toast.LENGTH_SHORT).show();
    }
  }
  private static void placeCallOrMakeToast(Context context, Intent intent) {
    ExtensionManager.getDialerOthersExtension().setPrecallInfo(context, intent);
    final boolean hasCallPermission = TelecomUtil.placeCall(context, intent);
    if (!hasCallPermission) {
      Toast.makeText(context, "Cannot place call without Phone permission", Toast.LENGTH_SHORT)
          .show();
    }
  }

TelecomUtil.java

  public static boolean placeCall(Context context, Intent intent) {
    if (hasCallPhonePermission(context)) {
      getTelecomManager(context).placeCall(intent.getData(), intent.getExtras());
      return true;
    }
    return false;
  }

TelecomManager.java

public void placeCall(Uri address, Bundle extras) {
    ITelecomService service = getTelecomService();
    if (service != null) {
	    ...
        try {
            service.placeCall(address, extras == null ? new Bundle() : extras,
                    mContext.getOpPackageName(), mContext.getAttributionTag());
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecomService#placeCall", e);
        }
    }
}

TelecomServiceImpl.java

@Override
public void placeCall(Uri handle, Bundle extras, String callingPackage,
        String callingFeatureId) {
		...

        mUserCallIntentProcessorFactory.create(mContext, userHandle)
                .processIntent(
                        intent, callingPackage, isSelfManaged ||
                                (hasCallAppOp && hasCallPermission),
                        true /* isLocalInvocation */);
       ...               
}

UserCallIntentProcessor.java

public void processIntent(Intent intent, String callingPackageName,
            boolean canCallNonEmergency, boolean isLocalInvocation) {
        ...
        String action = intent.getAction();
        if (Intent.ACTION_CALL.equals(action) ||
                Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
                Intent.ACTION_CALL_EMERGENCY.equals(action)) {
            processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency,
                    isLocalInvocation);
        }
        ...
    }
private void processOutgoingCallIntent(Intent intent, String callingPackageName,
            boolean canCallNonEmergency, boolean isLocalInvocation) {
        ...
        sendIntentToDestination(intent, isLocalInvocation, callingPackageName);
    }

private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation,
            String callingPackage) {
    ...
    TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
    tm.handleCallIntent(intent, callingPackage);
    ...
}

public void handleCallIntent(Intent intent, String callingPackageProxy) {
	...
    getTelecomService().handleCallIntent(intent, callingPackageProxy);
    ...
}

TelecomServiceImpl.java

@Override
public void handleCallIntent(Intent intent, String callingPackage) {
	...
    mCallIntentProcessorAdapter.processOutgoingCallIntent(mContext,
            mCallsManager, intent, callingPackage);
	...
}
@Override
public void processOutgoingCallIntent(Context context, CallsManager callsManager,
        Intent intent, String callingPackage) {
    CallIntentProcessor.processOutgoingCallIntent(context, callsManager, intent,
            callingPackage, mDefaultDialerCache);
}
static void processOutgoingCallIntent(
            Context context,
            CallsManager callsManager,
            Intent intent,
            String callingPackage,
            DefaultDialerCache defaultDialerCache) {
        ...
        CompletableFuture<Call> callFuture = callsManager
                .startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser,
                        intent, callingPackage);

		...
    }

CallsManager.java

  public CompletableFuture<Call> startOutgoingCall(Uri handle,
          PhoneAccountHandle requestedAccountHandle,
          Bundle extras, UserHandle initiatingUser, Intent originalIntent,
          String callingPackage) {
		...
      return startOutgoingCall(callee, requestedAccountHandle, extras, initiatingUser,
              originalIntent, callingPackage, false);
  }

private CompletableFuture<Call> startOutgoingCall(List<Uri> participants,
        PhoneAccountHandle requestedAccountHandle,
        Bundle extras, UserHandle initiatingUser, Intent originalIntent,
        String callingPackage, boolean isConference) {
        ...
        call = new Call(.....)
        ...
        addCall(callToPlace);
        ...
****
```java
@VisibleForTesting
public void addCall(Call call) {
  	...
   call.addListener(this);
   mCalls.add(call);

   // Specifies the time telecom finished routing the call. This is used by the dialer for
   // analytics.
   Bundle extras = call.getIntentExtras();
   extras.putLong(TelecomManager.EXTRA_CALL_TELECOM_ROUTING_END_TIME_MILLIS,
           SystemClock.elapsedRealtime());

   updateCanAddCall();
   updateHasActiveRttCall();
   updateExternalCallCanPullSupport();
   // onCallAdded for calls which immediately take the foreground (like the first call).
   for (CallsManagerListener listener : mListeners) {
   		...
       listener.onCallAdded(call);
		...
   }
	...
}

InCallController.java

@Override
    public void onCallAdded(Call call) {
    	...
       addCall(call);
		...
		IInCallService inCallService = entry.getValue();
       inCallService.addCall(sanitizeParcelableCallForService(info, parcelableCall));
		...
    }

InCallServiceBinder

@Override
public void addCall(ParcelableCall call) {
    mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
}

InCallService.java

case MSG_ADD_CALL:
    mPhone.internalAddCall((ParcelableCall) msg.obj);
    break;

final void internalAddCall(ParcelableCall parcelableCall) {
	...
    call.internalUpdate(parcelableCall, mCallByTelecomCallId);
    ...
}

final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
	...
	if (stateChanged) {
       fireStateChanged(mState);
    }
    if (detailsChanged) {
       fireDetailsChanged(mDetails);
    }
	...
}

private void fireStateChanged(final int newState) {
    for (CallbackRecord<Callback> record : mCallbackRecords) {
        final Call call = this;
        final Callback callback = record.getCallback();
        record.getHandler().post(new Runnable() {
            @Override
            public void run() {
                callback.onStateChanged(call, newState);
            }
        });
    }
}

DialerCall.java

@Override
public void onStateChanged(Call call, int newState) {
	...
  stateUpdate();
  	...
}
private void stateUpdate() {
    ...
   for (DialerCallListener listener : listeners) {
     listener.onDialerCallUpdate();
   }
	...
  }

DialerCallListenerImpl

@Override
public void onDialerCallUpdate() {
  Trace.beginSection("CallList.onDialerCallUpdate");
  onUpdateCall(call);
  notifyGenericListeners();
  Trace.endSection();
}

private void notifyGenericListeners() {
  for (Listener listener : listeners) {
    listener.onCallListChange(this);
  }
}

InCallPresenter.java

  @Override
  public void onCallListChange(CallList callList) {
  	...
	newState = startOrFinishUi(newState);
	...
  }

private InCallState startOrFinishUi(InCallState newState) {
	...
	showInCall(...)
	...
}

  public void showInCall(boolean showDialpad, boolean newOutgoingCall) {
    LogUtil.i("InCallPresenter.showInCall", "Showing InCallActivity");
    context.startActivity(
        InCallActivity.getIntent(context, showDialpad, newOutgoingCall, false));
  }

至此,InCallActivity将会启动到并显示UI


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android Dialer源码分析之去电流程 的相关文章

随机推荐

  • 计算机网络自考2020,2020年8月自考02141计算机网络技术真题及答案

    以下是湖南自考生网为考生们整理的 2020年8月自考02141计算机网络技术真题及答案 xff0c 考生可通过自考历年真题练习更有把握的面对考试 xff0c 对题型更加熟悉 xff0c 从而取得更佳的成绩 供考生参考 2020年8月高等教育
  • DLL丢失一键修复

    DLL丢失一键修复 今天不小心删了DLL相关的库 xff0c 费了好久才搞好 xff0c 记录一下 原因 xff1a 删除了win10中的这些库 解决办法 xff1a 使用一键修复工具 DLL丢失一键修复工具 xff1a 获取工具
  • springmvc的配置文件详解

    springmvc xml需要配置的东西 配置controller扫描包 使用组件扫描器省去在spring容器配置每个Controller类的繁琐 使用context component scan自动扫描标记 64 Controller的控
  • Bug随手记----关于java.lang.IllegalStateException: The following classes could not be excluded because the

    Consider the following If you want an embedded database H2 HSQL or Derby please put it on the classpath If you have data
  • linux:Systemd使用(systemctl)

    系统服务管理工具systemd是为了便于linux用户操作系统服务的管理 xff0c systemd提供了systemctl命令工具进行systemd的各项操作 Systemd的版本 systemd version systemd和syst
  • C++面试宝典:进程间通讯方式概述

    1 管道 我们来看一条 Linux 的语句 netstat tulnp grep 8080 学过 Linux 命名的估计都懂这条语句的含义 xff0c 其中 是管道的意思 xff0c 它的作用就是把前一条命令的输出作为后一条命令的输入 在这
  • ubuntu16.04LTS更换阿里源

    sudo gedit etc apt sources list 替换 xff1a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 deb cdrom Ubuntu 16 04 LTS Xenial
  • a++多线程下出现消失的请求现象

    a 43 43 多线程下出现消失的请求现象 a 43 43 多线程下出现消失的请求现象是一个常见的多线程运行结果错误的例子 我们先来看一下a 43 43 代码执行图 xff1a 按照我们想让它执行的顺序执行 xff0c 结果应该是3 但在多
  • 2013年十佳优秀主席将获得传智播客.NET学院培训名额

    2013年CSDN高校俱乐部十佳优秀主席将会免费获得价值9580元的传智播客 NET学院免费培训名额 培训时间为2015年之前有效 优秀主席评选截止日期为10月底 截止日期之前请提交你的评选内容 评选内容是俱乐部介绍 自我介绍和俱乐部活动介
  • MySQL各数据类型的特点

    MySQL各数据类型的特点 常用的整数类型 常见误区 int n 是设置数据最大的显示宽度 xff0c 所占的存储空间不会改变 常用的浮点类型 123456789 987654321 61 decimal 18 9 占用9个字节 涉及财务等
  • Redis持久化——RDB、AOF

    Redis持久化 RDB AOF 什么是持久化 redis所有数据都保存在内存中 xff0c 对数据的更新异步保存到磁盘上 在Redis中持久化的方式有两种 xff0c 一种是快照持久化 xff0c 一种是AOF持久化 xff0c 各有各的
  • Redis主从复制—看完这篇你就懂了

    Redis主从复制 主从复制 xff0c 是指将一台Redis服务器的数据 xff0c 复制到其他的Redis服务器 前者称为主节点 master leader xff0c 后者称为从节点 slave follower xff1b 数据的复
  • 轻松搞定单例模式以及线程安全等问题

    单例模式 单例模式 xff08 Singleton Pattern xff09 是 Java 中最简单的设计模式之一 这种类型的设计模式属于创建型模式 xff0c 它提供了一种创建对象的最佳方式 这种模式涉及到一个单一的类 xff0c 该类
  • 设计模式之原型模式

    原型模式 定义 xff1a 指原型实例指定创建对象的种类 xff0c 并且通过拷贝这些原型创建新的对象 不需要知道任何创建的细节 xff0c 不需要调用构造函数类型 xff1a 创建型 适用的场景 类初始化消耗较多资源 xff08 比较重的
  • 设计模式之外观模式

    外观模式 概念介绍 定义与类型 定义 xff1a 又叫门面模式 xff0c 提供了一个统一的接口 xff0c 用来访问子系统中的一群接口外观模式定义了一个高层接口 xff0c 这个接口使得子系统更容易被访问或者使用类型 xff1a 结构型
  • Mac无法连接本地Linux服务器 无法ping通

    遇到的问题 xff1a 虚拟机是从Win环境下复制到Mac上的 xff0c 在Win电脑下可以直接使用Xshell远程连接 xff0c 但在Mac下 xff0c 无法连接而且Ping不通 虚拟机使用的是CentOS 7版本 解决方案 查看M
  • gazebo视角设置问题

    How can I make my objects robot appear in image raw topic when using Gazebo camera plugin Initial view after gazebo star
  • DISM命令使用小结

    DISM命令使用小结 文章目录 DISM命令使用小结操作WIM镜像说明演示 操作系统映像说明添加功能启用本地策略启用Hyper V 操作WIM镜像 说明 REM 制作镜像并添加一个分卷 dism capture image imagefil
  • ZYNQ7000-AXI GPIO详解

    摘要 AXI GPIO是ZYNQ的一个IP核 xff0c 它能够将PS侧的AXI4 Lite接口转成PL侧的IO口 xff0c 可解决PS侧IO口不够用的问题 本文就AXI GPIO的概念 作用 配置与使用做了详细说明 xff0c 展示了示
  • Android Dialer源码分析之去电流程

    Android的拨号流程 xff0c 从拨号盘的点击拨号按钮开始 xff0c DialpadFragment java span class token annotation punctuation 64 Override span spa