Android13 基座充电屏保

news2024/12/27 17:08:35

屏幕保护有两个设置可选:默认为插入基座充电时

通过DreamBackend启用屏保,并且保存选择的时机

//QSSI.13\packages\apps\Settings\src\com\android\settings\dream\WhenToDreamPicker.java
@Override
protected boolean setDefaultKey(String key) {
    mBackend.setWhenToDream(DreamSettings.getSettingFromPrefKey(key));
    return true;
}
//QSSI.13\frameworks\base\packages\SettingsLib\src\com\android\settingslib\dream\DreamBackend.java
//启用屏保:
public void startDreaming() {
    logd("startDreaming()");
    if (mDreamManager == null) {
        return;
    }
    try {
        mDreamManager.dream();
    } catch (RemoteException e) {
        Log.w(TAG, "Failed to dream", e);
    }
}
//记录启用时机
public void setWhenToDream(@WhenToDream int whenToDream) {
    setEnabled(whenToDream != NEVER);

    switch (whenToDream) {
        case WHILE_CHARGING:
            setActivatedOnDock(false);
            setActivatedOnSleep(true);
            break;

        case WHILE_DOCKED:
            setActivatedOnDock(true);
            setActivatedOnSleep(false);
            break;

        case EITHER:
            setActivatedOnDock(true);
            setActivatedOnSleep(true);
            break;

        case NEVER:
        default:
            break;
    }
}

public void setActivatedOnDock(boolean value) {
    logd("setActivatedOnDock(%s)", value);
    setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, value);
}

public void setActivatedOnSleep(boolean value) {
    logd("setActivatedOnSleep(%s)", value);
    setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, value);
}

DreamBackend是对屏保管理的类,最终会通过IDreamManager来执行到DreamManagerService

启动屏保时,先获取系统安装的所有屏保,通过下列代码可以得到我们自己的开发的屏保

PackageManager pm = mContext.getPackageManager();
Intent dreamIntent = new Intent(DreamService.SERVICE_INTERFACE);
List<ResolveInfo> resolveInfos = pm.queryIntentServices(dreamIntent,
       PackageManager.GET_META_DATA);

然后再将屏保设置我们自己开发的

//QSSI.13\frameworks\base\services\core\java\com\android\server\dreams\DreamManagerService.java
public void setActiveDream(ComponentName dream) {
        logd("setActiveDream(%s)", dream);
        if (mDreamManager == null)
            return;
        try {
            ComponentName[] dreams = { dream };
            mDreamManager.setDreamComponents(dream == null ? null : dreams);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to set active dream to " + dream, e);
        }
    }

如果没有设置,系统会有一个默认的屏保,使用以下方法可以获取默认屏保

//QSSI.13\frameworks\base\services\core\java\com\android\server\dreams\DreamManagerService.java
public ComponentName getDefaultDream() {
        if (mDreamManager == null)
            return null;
        try {
            return mDreamManager.getDefaultDreamComponent();
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get default dream", e);
            return null;
        }
    }

然后用户有任何操作,屏保都会停止,实现逻辑是在DreamService里面的

//QSSI.13\frameworks\base\core\java\android\service\dreams\DreamService.java
/** {@inheritDoc} */
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    // TODO: create more flexible version of mInteractive that allows clicks
    // but finish()es on any other kind of activity
    if (!mInteractive && event.getActionMasked() == MotionEvent.ACTION_UP) {
        if (mDebug) Slog.v(mTag, "Waking up on touchEvent");
        wakeUp();
        return true;
    }
    return mWindow.superDispatchTouchEvent(event);
}
public final void wakeUp() {
    wakeUp(false);
}

private void wakeUp(boolean fromSystem) {
    if (mDebug) {
        Slog.v(mTag, "wakeUp(): fromSystem=" + fromSystem + ", mWaking=" + mWaking
                + ", mFinished=" + mFinished);
    }

    if (!mWaking && !mFinished) {
        mWaking = true;

        if (mActivity != null) {
            // During wake up the activity should be translucent to allow the application
            // underneath to start drawing. Normally, the WM animation system takes care of
            // this, but here we give the dream application some time to perform a custom exit
            // animation. If it uses a view animation, the WM doesn't know about it and can't
            // make the activity translucent in the normal way. Therefore, here we ensure that
            // the activity is translucent during wake up regardless of what animation is used
            // in onWakeUp().
            mActivity.convertToTranslucent(null, null);
        }

        // As a minor optimization, invoke the callback first in case it simply
        // calls finish() immediately so there wouldn't be much point in telling
        // the system that we are finishing the dream gently.
        onWakeUp();

        // Now tell the system we are waking gently, unless we already told
        // it we were finishing immediately.
        if (!fromSystem && !mFinished) {
            if (mActivity == null) {
                Slog.w(mTag, "WakeUp was called before the dream was attached.");
            } else {
                try {
                    mDreamManager.finishSelf(mDreamToken, false /*immediate*/);
                } catch (RemoteException ex) {
                    // system server died
                }
            }
        }
    }
}

屏保实现充电显示的逻辑在PowerManagerService里面

//QSSI.13\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
系统设置启用和时机
//是否打开屏保
mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
        Settings.Secure.SCREENSAVER_ENABLED,
        mDreamsEnabledByDefaultConfig ? 1 : 0,
        UserHandle.USER_CURRENT) != 0);
//仅充电时设置此值为1                 
mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
        Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
        mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
        UserHandle.USER_CURRENT) != 0);
  //基座充电时,此值为1
mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
        Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
        mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
        UserHandle.USER_CURRENT) != 0);
        

PowerManagerService里面主要是处理电源相关的逻辑,所以updatePowerStateLocked()方法会时时调用,更新电源状态,然后根据不同状态进行不同处理

private void updatePowerStateLocked() {
    if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) {
        return;
    }
    if (!Thread.holdsLock(mLock)) {
        Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
    mUpdatePowerStateInProgress = true;
    try {
        // Phase 0: Basic state updates.
        updateIsPoweredLocked(mDirty);
        updateStayOnLocked(mDirty);
        updateScreenBrightnessBoostLocked(mDirty);

        // Phase 1: Update wakefulness.
        // Loop because the wake lock and user activity computations are influenced
        // by changes in wakefulness.
        final long now = mClock.uptimeMillis();
        int dirtyPhase2 = 0;
        for (;;) {
            int dirtyPhase1 = mDirty;
            dirtyPhase2 |= dirtyPhase1;
            mDirty = 0;

            updateWakeLockSummaryLocked(dirtyPhase1);
            updateUserActivitySummaryLocked(now, dirtyPhase1);
            updateAttentiveStateLocked(now, dirtyPhase1);
            if (!updateWakefulnessLocked(dirtyPhase1)) {
                break;
            }
        }

        // Phase 2: Lock profiles that became inactive/not kept awake.
        updateProfilesLocked(now);

        // Phase 3: Update power state of all PowerGroups.
        final boolean powerGroupsBecameReady = updatePowerGroupsLocked(dirtyPhase2);

        // Phase 4: Update dream state (depends on power group ready signal).
        updateDreamLocked(dirtyPhase2, powerGroupsBecameReady);

        // Phase 5: Send notifications, if needed.
        finishWakefulnessChangeIfNeededLocked();

        // Phase 6: Update suspend blocker.
        // Because we might release the last suspend blocker here, we need to make sure
        // we finished everything else first!
        updateSuspendBlockerLocked();
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
        mUpdatePowerStateInProgress = false;
    }
}

private boolean updateWakefulnessLocked(int dirty) {
    ....
      if (shouldNapAtBedTimeLocked()) {
            //判断是否需要屏保
            changed = dreamPowerGroupLocked(powerGroup, time,
                    Process.SYSTEM_UID, /* allowWake= */ false);
        } 
        ...
}

@GuardedBy("mLock")
private boolean shouldNapAtBedTimeLocked() {
    return mDreamsActivateOnSleepSetting
            || (mDreamsActivateOnDockSetting
                    && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
}

在updatePowerStateLocked方法里面,会更新屏保状态,调用updateDreamLocked方法

private void updateDreamLocked(int dirty, boolean powerGroupBecameReady) {
    if ((dirty & (DIRTY_WAKEFULNESS
            | DIRTY_USER_ACTIVITY
            | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED
            | DIRTY_ATTENTIVE
            | DIRTY_WAKE_LOCKS
            | DIRTY_BOOT_COMPLETED
            | DIRTY_SETTINGS
            | DIRTY_IS_POWERED
            | DIRTY_STAY_ON
            | DIRTY_PROXIMITY_POSITIVE
            | DIRTY_BATTERY_STATE)) != 0 || powerGroupBecameReady) {
        if (areAllPowerGroupsReadyLocked()) {
            scheduleSandmanLocked();
        }
    }
}

scheduleSandmanLocked方法里面会发送一个消息

private void scheduleSandmanLocked() {
    if (!mSandmanScheduled) {
        mSandmanScheduled = true;
        for (int idx = 0; idx < mPowerGroups.size(); idx++) {
            final PowerGroup powerGroup = mPowerGroups.valueAt(idx);
            if (powerGroup.supportsSandmanLocked()) {
                Message msg = mHandler.obtainMessage(MSG_SANDMAN);
                msg.arg1 = powerGroup.getGroupId();
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
            }
        }
    }
}

在PowerManagerHandler里面处理MSG_SANDMAN消息

private final class PowerManagerHandlerCallback implements Handler.Callback {
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_USER_ACTIVITY_TIMEOUT:
                handleUserActivityTimeout();
                break;
            case MSG_SANDMAN:
                handleSandman(msg.arg1);
                break;
            case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
                handleScreenBrightnessBoostTimeout();
                break;
            case MSG_CHECK_FOR_LONG_WAKELOCKS:
                checkForLongWakeLocks();
                break;
            case MSG_ATTENTIVE_TIMEOUT:
                handleAttentiveTimeout();
                break;
        }

        return true;
    }
}

主要处理逻辑是在handleSandman里面

private void handleSandman(int groupId) { // runs on handler thread
    // Handle preconditions.
    final boolean startDreaming;
    final int wakefulness;
    synchronized (mLock) {
        mSandmanScheduled = false;
        if (!mPowerGroups.contains(groupId)) {
            // Group has been removed.
            return;
        }
        final PowerGroup powerGroup = mPowerGroups.get(groupId);
        wakefulness = powerGroup.getWakefulnessLocked();
         //  首先判断是否可以启动屏保
        // 如果可以启动屏保且当前锁状态为WAKEFULNESS_NAPPING时,由表示需要启动屏保
        if (powerGroup.isSandmanSummonedLocked() && powerGroup.isReadyLocked()) {
            startDreaming = canDreamLocked(powerGroup) || canDozeLocked(powerGroup);
            powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ false);
        } else {
            startDreaming = false;
        }
    }

    // Start dreaming if needed.
    // We only control the dream on the handler thread, so we don't need to worry about
    // concurrent attempts to start or stop the dream.
    final boolean isDreaming;
    if (mDreamManager != null) {
        // Restart the dream whenever the sandman is summoned.
         //启动屏保
        if (startDreaming) {
            mDreamManager.stopDream(/* immediate= */ false,
                    "power manager request before starting dream" /*reason*/);
            mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING,
                    "power manager request" /*reason*/);
        }
        isDreaming = mDreamManager.isDreaming();
    } else {
        isDreaming = false;
    }

    // At this point, we either attempted to start the dream or no attempt will be made,
    // so stop holding the display suspend blocker for Doze.
    mDozeStartInProgress = false;

    // Update dream state.
    synchronized (mLock) {
        if (!mPowerGroups.contains(groupId)) {
            // Group has been removed.
            return;
        }

        // Remember the initial battery level when the dream started.
         //如果屏保正在运行且相关设置允许启动屏保,将状态设置为WAKEFULNESS_DREAMING
        if (startDreaming && isDreaming) {
            mDreamsBatteryLevelDrain = 0;
            if (wakefulness == WAKEFULNESS_DOZING) {
                Slog.i(TAG, "Dozing...");
            } else {
                Slog.i(TAG, "Dreaming...");
            }
        }

        // If preconditions changed, wait for the next iteration to determine
        // whether the dream should continue (or be restarted).
        final PowerGroup powerGroup = mPowerGroups.get(groupId);
        if (powerGroup.isSandmanSummonedLocked()
                || powerGroup.getWakefulnessLocked() != wakefulness) {
            return; // wait for next cycle
        }
....

    // Stop dream.
    if (isDreaming) {
        mDreamManager.stopDream(/* immediate= */ false, "power manager request" /*reason*/);
    }
}

从代码可以看出mWakefulness变量与是否启动屏保密切相关,当启动屏保时,mWakefulness状态发生变化

@GuardedBy("mLock")
int recalculateGlobalWakefulnessLocked() {
    int deviceWakefulness = WAKEFULNESS_ASLEEP;
    for (int i = 0; i < mPowerGroups.size(); i++) {
        final int wakefulness = mPowerGroups.valueAt(i).getWakefulnessLocked();
        if (wakefulness == WAKEFULNESS_AWAKE) {
            return WAKEFULNESS_AWAKE;
        } else if (wakefulness == WAKEFULNESS_DREAMING
                && (deviceWakefulness == WAKEFULNESS_ASLEEP
                || deviceWakefulness == WAKEFULNESS_DOZING)) {
                    //此状态下,屏保会被启动
            deviceWakefulness = WAKEFULNESS_DREAMING;
        } else if (wakefulness == WAKEFULNESS_DOZING
                && deviceWakefulness == WAKEFULNESS_ASLEEP) {
            deviceWakefulness = WAKEFULNESS_DOZING;
        }
    }

    return deviceWakefulness;
}

在停止屏保时,会依次调用handleDreamFinishedLocked –>wakeUpNoUpdateLocked

在wakeUpNoUpdateLocked方法里面,mWakefulness 状态发生变化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1707040.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数组和特殊矩阵的压缩存储

文章目录 一维数组二维数组特殊矩阵对称矩阵三角矩阵三对角矩阵稀疏矩阵三元组法十字链表法 一维数组 以一维数组A[0...n-1]为例&#xff0c;其存储结构关系式为 LOC ⁡ ( a i ) LOC ⁡ ( a 0 ) i L ( 0 ⩽ i < n ) \operatorname{LOC}\left(a_i\right)\operatorname{LO…

AI手语研究数据集;视频转视频翻译和风格化功能如黏土动画;AI检测猫咪行为;开放源码的AI驱动搜索引擎Perplexica

✨ 1: Prompt2Sign 多语言手语数据集&#xff0c;便捷高效用于手语研究。 Prompt2Sign 是一个全面的多语言手语数据集&#xff0c;旨在通过工具自动获取和处理网络上的手语视频。该数据集具有高效、轻量的特点&#xff0c;旨在减少先前手语数据集的不足之处。该数据集目前包含…

基于springboot+vue的公司资产网站(全套)

一、系统架构 前端&#xff1a;vue2 | element-ui 后端&#xff1a;springboot | mybatis 环境&#xff1a;jdk1.8 | mysql | maven | node 二、代码及数据库 三、功能介绍 01. 管理后台-登录 02. 管理后台-首页 03. 管理后台-个人中心-修改密码 04. 管理后台-个人…

CentOS7 部署单机版 ElasticSearch + Logstash

一、部署ElasticSearch Elasticsearch部署参考下面文章&#xff1a; CentOS7 部署单机版 elasticsearch-CSDN博客文章浏览阅读285次&#xff0c;点赞6次&#xff0c;收藏3次。ElasticSearch&#xff0c;用于检索、聚合分析和大数据存储https://blog.csdn.net/weixin_44295677…

N1912A P 系列双通道功率计

N1912A 双通道功率计 产品综述 <<<P 系列双通道功率计>>> Keysight N1912A P 系列双通道功率计可以提供峰值功率、峰均比、平均功率、上升时间、下降时间 NS 脉冲宽度测量。 “ 功能特点 30 MHz 视频带宽 能够以高达 100 MSa/s 的采样率执行单次实时捕…

从华为云OBS到AWS云上S3:迁移及相关事项

随着云计算的快速发展&#xff0c;企业越来越倾向于将数据存储和管理移到云端。华为云的对象存储服务&#xff08;OBS&#xff09;和亚马逊云服务&#xff08;AWS&#xff09;上的简单存储服务&#xff08;S3&#xff09;是两个备受欢迎的选择。对于那些考虑从华为云OBS迁移到A…

OrangePi AIpro 变身 Android 打包机

主板基本信息介绍 OrangePi AIpro&#xff0c;是香橙派联合华为精心打造&#xff0c;建设人工智能新生态而设计的一款开发板&#xff0c;这次为大家分享下我上手的这款 OrangePi AIpro 8GB&#xff08;算力达8TOPS&#xff09; 的一些小小的经验。 基本参数如下&#xff1a; …

【亲测有效】发现了适用于Mac用户的ChatGPT客户端登陆方法

项目场景&#xff1a; Mac用户的ChatGPT客户端登陆 问题描述 无法使用 解决方案&#xff1a; 1.下载登陆ChatGPT客户端 https://persistent.oaistatic.com/sidekick/public/C...https://persistent.oaistatic.com/sidekick/public/ChatGPT_Desktop_public_latest.dmg 2.登陆…

设计模式 21 备忘录模式 Memento Pattern

设计模式 21 备忘录模式 Memento Pattern 1.定义 备忘录模式是一种行为型设计模式&#xff0c;它允许你将一个对象的状态保存到一个独立的“备忘录”对象中&#xff0c;并在之后恢复到该状态。 2.内涵 主要用于以下场景&#xff1a; 需要保存对象状态以备恢复&#xff1a; 当…

Kubernetes集群调度

一.List-Watch 1.调度约束 Kubernetes 是通过 List-Watch **** 的机制进行每个组件的协作&#xff0c;保持数据同步的&#xff0c;每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件&#xff0c;向 APIServer 发送命令&#xff0c;在 Node 节点上面建立 P…

【OCPP】ocpp1.6协议第3.13章节SmartCharging介绍及翻译

目录 3.13 SmartCharging智能充电-概述 智能充电的目标 关键功能 消息类型 负载管理 动态电量配置 总结 3.13 SmartCharging智能充电-译文 3.13.1 Charging Profile Purpose充电配置的目的 3.13.2 Stacking charging profile堆叠充电配置 3.13.3 Combining charging profile pu…

如何在线转换图片的格式?一键修改图片格式的方法

图片是日常生活和工作中的一种常用的内容展示类型&#xff0c;在使用图片的时候不同用途需要使用的图片格式也是不同的&#xff0c;比如我们手中有一张jpg格式图片&#xff0c;但是平台上传要求格式是png&#xff0c;那么怎样才能将jpg转png格式呢&#xff1f;下面将教大家图片…

前端面试:项目细节重难点问题分享

面试官提问&#xff1a;我现在给你出一个项目实际遇到的问题&#xff1a;由于后端比较忙&#xff0c;所以我们这边的列表数据排序需要前端最近实现&#xff0c;那你会怎么实现排序呢&#xff1f; 答&#xff1a;我的回答&#xff1a;确实&#xff0c;数据都是由后端实现的&…

2024年上半年软件设计师试题及答案(回忆版)--选择题

基础知识选择题 基础知识选择题 1,2,3][4,5,6][1,2,3,4,5,6] &#xff08;总&#xff1a;1分&#xff09; &#xff08;注意&#xff1a;括号内的是截止当前题目总分&#xff09; vlan不能隔绝内外网 &#xff08;2分&#xff09; 链路层使用交换机&#xff0c;…

关于已配好java环境但双击无法打开jar包的解决方案

如果你已经装好了 java 环境直接跳到最后看解决方法即可 先说一下你安装的 java 环境&#xff0c;如果完全是默认选项安装&#xff0c;则会安装 jdk 和 jre&#xff0c;并且在安装 jre 时还需要安装目录下为空&#xff0c;其实 jre 的安装是多余的&#xff0c;因为安装的 jdk 里…

Integer包装类

面试题&#xff1a; 自动装箱:把基本数据类型会自动的变成其对应的包装类 自动拆箱:把包装类自动的变成其对象的基本数据类型 package Integer;public class Demo {public static void main(String[] args) {Integer i 10;String binaryString Integer.toBinaryString(i);Str…

pyqt QLineEdit单行文本框控件

pyqt QLineEdit单行文本框控件 介绍效果代码 介绍 QLineEdit 是 PyQt中的一个控件&#xff0c;用于输入和编辑单行文本。它允许用户输入和编辑一行纯文本&#xff0c;并提供了许多有用的功能&#xff0c;如文本验证、密码输入&#xff08;显示为点或星号&#xff09;、自动完成…

ICode国际青少年编程竞赛- Python-6级训练场-递归入门

ICode国际青少年编程竞赛- Python-6级训练场-递归入门 1、 def recur(n):# 边界条件if n<1:return# 额外动作Dev.step(n)Dev.turnRight()# 递归调用recur(n-1)recur(8)2、 def recur(n):# 边界条件if n<1:return# 额外动作Dev.step(n)Dev.turnLeft()# 递归调用recur(n-1)…

一些Spring的理解

说说你对Spring的理解 首先Spring是一个生态&#xff1a;可以构建企业级应用程序所需的一切基础设施 但是&#xff0c;通常Spring指的就是Spring Framework&#xff0c;它有两大核心&#xff1a; IOC和DI 它的核心就是一个对象管理工厂容器&#xff0c;Spring工厂用于生产Bea…

初识STM32单片机-TIM定时器

初识STM32单片机-TIM定时器 一、定时器概述二、定时器类型2.1 基本定时器(TIM6和TIM7)2.2 通用定时器(TIM2、TIM3、TIM4和TIM5)2.3 高级定时器(TIM1和TIM8) 三、定时中断基本结构和时基单元工作时序3.1 定时器基本结构3.2 预分频器时序3.3 计数器时序3.3.1 计数器有无预装时序(…