AAOS CarPowerManager

文章目录

提供什么服务? 如何提供的?

  • 作用是什么?

电源管理, 车上面的状态可能有很多中,比如在车库,停车,短时间停车等等。每种模式可能需要的功耗策略都不一样。

就需要一个模块对车的各个部分进行控制。

  • 基本原理

车辆的状态停车、熄火等等状态通过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
  1. mRegisteredPowerPolicies构造,主要是构造两个默认的regular的powerPolicy

    一个policy 的id是kSystemPolicyIdAllOn,这里所有component都是on的状态。

    一个polocy的id是kSystemPolicyIdInitialOn,这里打开kInitialOnComponents里面定义的Component。

  2. mPreemptivePowerPolicies的构造,这个是抢占式的powerPolicy。

    也是创建两个powerPolicy 分别为 kSystemPolicyIdNoUserInteraction、kSystemPolicyIdSuspendToRam

    两个policy都有默认的

  3. 从文件中读取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
  1. vhal的连接 获取vehicle的服务,连接不上时候 会间隔200ms进行尝试,最多尝试25次。也就是1s连接不上就直接返回失败了。
  2. 配置默认的powerpolicy, 这个powerpolicy是之前init从文件power_policy.xml中读取到的。
  3. 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;
            }
        }
相关推荐
程序员老刘19 分钟前
Google突然“变脸“,2026年要给全球开发者上“紧箍咒“?
android·flutter·客户端
Tans523 分钟前
Androidx Lifecycle 源码阅读笔记
android·android jetpack·源码阅读
雨白1 小时前
实现双向滑动的 ScalableImageView(下)
android
峥嵘life1 小时前
Android Studio新版本编译release版本apk实现
android·ide·android studio
studyForMokey3 小时前
【Android 消息机制】Handler
android
敲代码的鱼哇3 小时前
跳转原生系统设置插件 支持安卓/iOS/鸿蒙UTS组件
android·ios·harmonyos
翻滚丷大头鱼3 小时前
android View详解—动画
android
我是好小孩3 小时前
[Android]RecycleView的item用法
android
胖虎14 小时前
Android Studio 读取本地文件(以 ZIP 为例)
android·ide·android studio·本地文件·读取本地文件
出海小纸条4 小时前
Google Play 跨应用脚本漏洞(Cross-App Scripting)
android