为了增强用户隐私,Android 9 引入了若干行为变更,如限制后台应用访问设备传感器、限制通过 Wi-Fi 扫描检索到的信息,以及与通话、手机状态和 Wi-Fi 扫描相关的新权限规则和权限组。无论采用哪一种目标 SDK 版本,这些变更都会影响运行于 Android 9 上的所有应用。后台对传感器的访问受限,Android 9 限制后台应用访问用户输入和传感器数据的能力。 如果您的应用在运行 Android 9 设备的后台运行,系统将对您的应用采取以下限制:
如果您的应用需要在运行 Android 9 的设备上检测传感器事件,请使用前台服务。
这些规则的更新主要受影响的服务为,sensorservices,audioservices,cameraservices
如果应用刚从前台切换到后台,那么我们会等一分钟,等一分钟设计者的目的是为了,让当前进程有时间去进行收尾工作,然后我们才让该进程进入IDLE状态。在这里做了一个delay处理,时间到了后会调用idleUids(),最后会停止idle状态下,该UID所关联的服务。
下面以audioservices为例来说明sensorservices,audioservices,cameraservices是如何受到影响的。简单描述就是具体就是audioservices在首次被调用的时候是向 ActivityManagerService 注册 UidObserver, 把 AudioPolicyService 的 onUidActive/ onUidIdle 注册过去,这样 Uid State 变化的时候, 执行对应的 setRecordSilenced,这个会导致不能达到录音的效果,具体的可以看截图中的英文部分。
1.注册监听
在服务首次被调用的时候进行注册
注册的时候监听3种状态
// Flag for registerUidObserver: report uid gone
UID_OBSERVER_GONE = 1<<1,
// Flag for registerUidObserver: report uid has become idle
UID_OBSERVER_IDLE = 1<<2,
// Flag for registerUidObserver: report uid has become active
UID_OBSERVER_ACTIVE = 1<<3
这三状态分别对应三个方法
2.通知UID状态变化
进程状态发生变化通知进入IDLE,更新服务线程状态
updateOomAdjLocked-->dispatchUidsChanged()--> dispatchUidsChangedForObserver—>observer.onUidIdle
3.反注册
析构的时候反注册
4.后台启动服务限制
异常范例:
E AndroidRuntime: java.lang.IllegalStateException: Not allowed to start service Intent {
act=com.oneplus.security.network.calibrate.action.fetch_and_save
cmp=com.oneplus.security/.network.calibrate.AutoSaveNativeTrafficUsageService (has extras)
}: app is in background uid UidRecord{15a9620 u11s1000 SVC bg:+1m24s75ms idle change:idle procs:14 seq(0,0,0)}
服务启动流程:startService(ContextImpl)-->startServiceCommon(ContextImpl)--
>startService(AMS)-->startServiceLocked(ActiveServices)-->getAppStartModeLocked
不是所有的后台进程都不允许启动服务,因此要进行过滤,过滤规则
特例:
a.如果是常驻应用,允许启动服务
b.不是常驻应用但是在background whitelisted允许启动:BLUETOOTH_UID
c.battery whitelist也允许启动
通用规则:
d.如果以上条件都不满足则走后台通用的限制策略,进行后台权限检查
上面讲的是服务,同样的广播也有类似的情况
r.queue.processNextBroadcastLocked(AMS)-->processNextBroadcastLocked(BroadcastQueue.java)-->mService.getAppStartModeLocked
这里相对于就直接走到通用规则匹配,没有了特殊权限应用的过滤了