文章目录
-
-
- [提供什么服务? 如何提供的?](#提供什么服务? 如何提供的?)
- 基础的carpowerpolicyd的服务
-
提供什么服务? 如何提供的?
- 作用是什么?
电源管理, 车上面的状态可能有很多中,比如在车库,停车,短时间停车等等。每种模式可能需要的功耗策略都不一样。
就需要一个模块对车的各个部分进行控制。
- 基本原理
车辆的状态停车、熄火等等状态通过vehicle hal 通知到carpowerservice, 在service 中去控制各个模块的on off。
(音频模块的on off 是通过设置stric mode 的方式 控制carauioservice, 具体就是不是safe 和emergency的音频流类型 请求焦点都会失败,也就是这些类型的声音类型都播放不出来)
基础的carpowerpolicyd的服务
- 对应的carpowerpolicyd.rc文件
属于early_hal. service名字为carpowerpolicyd - 对应的main函数
启动CarPowerPolicyServer,传递是外部创建好的looper,启动调用iniit进行初始化。
init包括PolicyManager的init、componetHandlder的注册、然后将服务注册到serviceMananger。最后调用ConnetcToVhal。
mHandlerLooper = looper;
mPolicyManager.init();
mComponentHandler.init();
mSilentModeHandler.init();
connectToVhal();
- PolicyManager的init
-
mRegisteredPowerPolicies构造,主要是构造两个默认的regular的powerPolicy
一个policy 的id是kSystemPolicyIdAllOn,这里所有component都是on的状态。
一个polocy的id是kSystemPolicyIdInitialOn,这里打开kInitialOnComponents里面定义的Component。
-
mPreemptivePowerPolicies的构造,这个是抢占式的powerPolicy。
也是创建两个powerPolicy 分别为 kSystemPolicyIdNoUserInteraction、kSystemPolicyIdSuspendToRam
两个policy都有默认的
-
从文件中读取powerpolicy配置
是从/vendor/etc/automotive/power_policy.xml读取配置,其中配置是按照具体的policy id 和 模块的open 和on
读取的配置存储在
mRegisteredPowerPolicies 和 mPolicyGroups。
其中mRegisteredPowerPolicies存储 policy的名字policy_id_other_untouched和具体的policy。
mPolicyGroups存储policyGroup的名字
- connect to vhal
- vhal的连接 获取vehicle的服务,连接不上时候 会间隔200ms进行尝试,最多尝试25次。也就是1s连接不上就直接返回失败了。
- 配置默认的powerpolicy, 这个powerpolicy是之前init从文件power_policy.xml中读取到的。
- subscribe
VehicleProperty::POWER_POLICY_GROUP_REQ
VehicleProperty::POWER_POLICY_REQ
这两个属性,当vhal有这两个属性变化的时间上报的时候,获取属性的值,并设置对应的powerpolicy。
其存储的xml
<powerPolicy version="1.0">
<policyGroups>
<policyGroup id="mixed_policy_group">
<defaultPolicy state="WaitForVHAL" id="policy_id_other_on"/>
<noDefaultPolicy state="On"/>
</policyGroup>
</policyGroups>
<policy id="policy_id_other_untouched">
<otherComponents behavior="untouched"/>
<component id="POWER_COMPONENT_AUDIO">on</component>
<component id="POWER_COMPONENT_DISPLAY">on</component>
<component id="POWER_COMPONENT_BLUETOOTH">on</component>
<component id="POWER_COMPONENT_WIFI">on</component>
<component id="POWER_COMPONENT_VOICE_INTERACTION">on</component>
<component id="POWER_COMPONENT_VISUAL_INTERACTION">on</component>
<component id="POWER_COMPONENT_TRUSTED_DEVICE_DETECTION">on</component>
</policies>
</powerPolicy>
CarPowerManagerService 与其他服务和 HAL 协调电源状态。CPMS 实现上述状态机,并在发生电源状态转换时向每个观察者发送通知。carPower服务会通过VHAL 和硬件的MCU进行通信。
### 整体的框架
carPowerManager(java/c++) ------> CarPowerManagerService
跟CarAudioSevice框架类型,提供给外部的carPowerMananger,(java和c++两套接口)。
然后通过AIDL调用到CarPowerManangerService 中。
- 常用接口 设置carPowerPolicy的监听
carAudioService 根据电源的状态做相应的处理。
获取service 然后设置监听。 当power policy发生变化的时候回调到onPolicyChanged
在onPolicyChanged 中 将音频关闭,通过CarAudioService设置标志位,让不是safe 和 emergancy
的音频 请求焦点都失败。
同样 在 CarMediaService 中也会监听powerchange的事件,对于powerpolicy中componet状态变化进行处理。 比如component off状态的,设置状态为pause。在播放的MediaSession进行暂停。
void startListeningForPolicyChanges() {
if (mCarPowerManagementService == null) {
Slog.w(TAG, "Cannot find CarPowerManagementService");
mCarAudioService.setAudioEnabled(/* isAudioEnabled= */ true);
return;
}
CarPowerPolicyFilter filter = new CarPowerPolicyFilter.Builder()
.setComponents(AUDIO).build();
mCarPowerManagementService.addPowerPolicyListener(filter, mChangeListener);
initializePowerState();
}
private final ICarPowerPolicyListener mChangeListener =
new ICarPowerPolicyListener.Stub() {
@Override
public void onPolicyChanged(CarPowerPolicy policy,
CarPowerPolicy accumulatedPolicy) {
synchronized (mLock) {
if (mIsAudioEnabled != accumulatedPolicy.isComponentEnabled(AUDIO)) {
updateAudioPowerStateLocked(accumulatedPolicy);
}
}
}
};
@GuardedBy("mLock")
private void updateAudioPowerStateLocked(CarPowerPolicy policy) {
mIsAudioEnabled = policy.isComponentEnabled(AUDIO);
Slog.w(TAG, "Policy mIsAudioEnabled" + mIsAudioEnabled);
mCarAudioService.setAudioEnabled(mIsAudioEnabled);
}
}
void setAudioEnabled(boolean isAudioEnabled) {
if (Slogf.isLoggable(CarLog.TAG_AUDIO, Log.DEBUG)) {
Slogf.d(CarLog.TAG_AUDIO, "Setting isAudioEnabled to %b", isAudioEnabled);
}
mFocusHandler.setRestrictFocus(/* isFocusRestricted= */ !isAudioEnabled);
if (mUseCarVolumeGroupMuting) {
mCarVolumeGroupMuting.setRestrictMuting(/* isMutingRestricted= */ !isAudioEnabled);
}
// TODO(b/176258537) if not using group volume, then set master mute accordingly
}
carAudioFocus.java
void setRestrictFocus(boolean isFocusRestricted) {
synchronized (mLock) {
mIsFocusRestricted = isFocusRestricted;
if (mIsFocusRestricted) {
abandonNonCriticalFocusLocked();
}
}
}
public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
int response;
AudioPolicy policy;
AudioFocusInfo replacedDelayedAudioFocusInfo = null;
synchronized (mLock) {
policy = mAudioPolicy;
response = evaluateFocusRequestLocked(afi);
}
// Post our reply for delivery to the original focus requester
mAudioManager.setFocusRequestResult(afi, response, policy);
logFocusEvent("onAudioFocusRequest for client " + afi.getClientId()
+ " with gain type " + focusEventToString(afi.getGainRequest())
+ " resulted in " + focusRequestResponseToString(response));
}
private int evaluateFocusRequestLocked(AudioFocusInfo afi) {
Slog.i(TAG, "Evaluating + focusEventToString(afi.getGainRequest())
+ " request for client " + afi.getClientId()
+ " with usage " + afi.getAttributes().usageToString());
Slog.i(TAG, "mIsFocusRestricted " + mIsFocusRestricted);
if (mIsFocusRestricted) {
int audioContext = CarAudioContext.getContextForAttributes(afi.getAttributes());
if (!isCriticalAudioContext(audioContext)) {
Slog.i(TAG, "audioContext " + audioContext + "request failed");
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
}
}