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;
            }
        }
相关推荐
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone5 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen5 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone5 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui