2.4camera多进程互斥控制

12 篇文章 23 订阅

上一节我们提到过handleEvictionsLocked方法是处理相机进程互斥的。这是一个比较重要的方法,随着现在安卓设备的发力点集中到相机上,同一个应用内的多相机的调用,甚至是不同应用打开不同相机的需求都开始出现,从Framework层面来说就是这里在进行管理。

根据相机使用的经历,我们应该有以下几个经验

  1. 两个应用不能同时打开一个camera;
  2. 同一个应用,根据平台不同(高通、MTK),不一定能同时打开两个camera;
  3. 分屏模式下两个应用分别打开不同的相机,哪个应用获得焦点,那个应用的相机可以活动,另一个无法活动。

造成这些现象的就是handleEvictionsLocked方法。

handleEvictionsLocked方法中的处理逻辑

方法首先判断API1的情况,前面章节提到过mediaRecoder会产生client需要单独判断。如果相机已经打开,就判断是否是API1并且binder相同,binder相同意味着是同一个进程,那么久可以正常打开,返回client,否则提示。

接下来获取所有活动进程的优先级,并将优先级更新到mActiveClientManager中。

mActiveClientManager对象是CameraClientManager类型的,继承了ClientManager、BasicClient和ClientEventListener,其中BasicClient和ClientEventListener都是CameraService的内部类。

Listener监听client的add和remove操作。BasicClient定义了CameraClient的一些基本操作,CameraDeviceClientBase类继承了BasicClient,所以这个类实际上是所有CameraClient的父类。

ClientManager类是对client进行管理的类,内部定义了一个client的描述类ClientDescriptor,包括key(这个key实际上就是camera id,在冲突处理中将全使用key来表示)、value、cost、ownerId、priority和conflicting等属性。ClientManager类就围绕被add进来的client进行属性的get、set等操作。

在更新过优先级之后,就去获取Camera的状态,在上一节中已经介绍了CameraState,这里不再复述。值得一提的是,所有相机的状态在camera service启动的时候就已经被获取了,所以在CameraService中直接调用getCameraState方法就可以得到指定id的状态。

接下来根据前面两步获取到的优先级、CameraState等信息构建clientDescriptor对象。

然后查找与这个clientDescriptor冲突的client,返回的是一个vector队列。此后方法进入到冲突处理阶段。

1.如果冲突的client在这个队列中,就不能打开相机,给出提示,方法返回。

2. 如果当前client不在evicted冲突队列中,说明当前应用与其他应用已经打开的相机存在冲突,但是当前相机应用优先级高,cameraservice会将之前被其他应用打开的相机关闭。

最后在冲突处理后,就是mServiceLock.unlock -> evictedClients disconnect -> evictedClients clear ->mServiceLock.lock的操作流程,清空连接,方法返回就不再细述。

ClientManager中的冲突处理逻辑

       在handleEvictionsLocked方法中,我们只是提到了mActiveClientManager.wouldEvict(clientDescriptor)的作用是查找冲突的client,接下来分析是如何查找的。wouldEvict直接调用的wouldEvictLocked方法,所以只要分析这个方法就可以 。

方法首先进行优先级判断,确定最高优先级的归属。

接下来便利所有client,判断冲突,并添加到冲突list中。判断条件是1.id相同则冲突,2. isConflicting检查底层冲突。

如果已经存在较高优先级的client,就把当前client加入到冲突list中,意味着当前client不能打开camera。

如果满足:

1)存在冲突,且已有client优先级低,

2)不存在冲突,但是totalCost大于maxCost,并且当前client优先级不低于已有client,且当前client与已有client不是同一进程或者为同一进程但优先级不是最高,

的判断条件,则将已经存在的client加入到list中,意味着当前client打开时,已存在的client因为冲突而需要关闭。

最后,判断当前优先级低,并且底层冲突或者超出了最大cost且当前cost大于0,也加入到list中。

这样与当前client冲突的就都加入到了list中。

然后判断当前client自身是否可以打开。

如果当前client优先级不是最高,且超过最大cost,加入到list中,代表当前client不能打开。

至此所有的冲突都已经判断完毕,并添加到list中返回。

结论

通过上面的分析可以看到冲突的关键条件是:

  1. id相同必然冲突;
  2. totalCost超过最大maxCost必然冲突;
  3. 底层冲突(isConflicting为true)。

 

出现这三种的任意一种都会发生冲突,而决定哪个相机可以打开的决定性条件只有一个:

  1. 优先级,发生冲突优先级低的无法打开。

 

所以反向而言,想要在多进程打开不同相机的前提条件就是:

  1. isConflicting为false;
  2. tatalCost不大于maxCost;

只要满足这两个条件,就能两个进程同时打开Camera。

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值