Android13 基座充电屏保

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

通过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 activityif (!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 {@Overridepublic 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_DREAMINGif (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.mzph.cn/news/843309.shtml

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

相关文章

LeetCode hot100-50-G

124. 二叉树中的最大路径和二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。路径和 是路径中各节点值的总和。给你一个二叉树的根…

linux input 驱动

使用文档 设备树修改 新增一个 LED 节点 arch/arm/boot/dts/arm/vexpress-v2p-ca9.dts my_pl_led {compatible = "arm, cortex-a9-led";status = "okay";};设备树编译 make dtbs日志 DTC arch/arm/boot/dts/arm/vexpress

AI视频换脸!最快的方法,100%成功,完全免费,无需配置、打开即用

这是一款百分百完全免费&#xff0c;超级好用又简单的AI视频换脸工具&#xff0c;不仅效果非常不错而且支持CPU和GPU解码&#xff0c;即使电脑上没有独立显卡&#xff0c;你也可以通过电脑上的CPU要进解码&#xff0c;虽然我之前给他介绍好几个有关AI视频&#xff0c;比如像这个…

通关!游戏设计之道Day17

音乐里的音符 音乐能给任何娱乐体验增色不少。 主题公园景区&#xff0c;电影或电子游戏都少不了它。 在考虑音乐设计时&#xff0c;你需要弄清楚的第一个问题是&#xff1a;“我想要什么类型的音乐&#xff1f;” 关于这个问题&#xff0c;确切的答案有两个&#xff1a;用…

46. 全排列 - 力扣(LeetCode)

基础知识要求&#xff1a; Java&#xff1a;方法、集合、泛型、Arrays工具类、数组、for循环、if判断 Python&#xff1a; 方法、列表、for循环、if判断 题目&#xff1a; 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案…

网络原理-HTTPS协议

在前面说到HTTP中,我们通过抓包,可以看到许多信息内容,其中往往会包含一些敏感信息,这些都是明文传输,当我们的请求被黑客或者不法分子截获后,那就很危险了,因此衍生出了HTTPS协议来对传输数据进行加密。 一、加密原理 基本原理如下&#xff1a; 明文 密钥 > 密文 密文…

【一竞技DOTA2】RAMZES666替补参加裂变联赛

1、根据主办方文件,RAMZES666将继续作为Tundra战队替补参加裂变联赛。该比赛为欧洲线上赛,于5月27日-30日举行,总奖金8万美元。 除此之外,Nigma战队在上个月宣布四号位Matthew离队后,也选择启用老队员GH参赛。而在本月初让ah fu转回教练、携替补Thiolicor出战PGL瓦拉几亚的Secr…

远程户外监控组网方案,工业4G路由器ZR2000

户外监控无人值守4G工业路由器组网应用涉及工业自动化、数据传输和远程监控的重要领域。在户外没有光纤的情况下&#xff0c;想要让监控或传感器等设备联网&#xff0c;仅需一台4G工业路由器即可解决。以下是关于远程监控户外组网的详细分析与应用&#xff1a; 物联网应用场景 …

【2024系统架构设计】回顾历史,查缺补漏篇 ④

前言 hello,大家好: 💡💡💡 我们一起来备考软考高级系统架构设计师吧,本专栏提供综合知识、案例科目、论文(论点和部分示例范文)等内容,包括知识点总结和记忆小妙招哦。 🚀🚀🚀 可以减少资料查找和收集的时间,提高效率,我们一起集中精力学习干货吧! 💡…

开源浪潮与闭源堡垒:大模型未来的双重奏

从数据隐私、商业应用和社区参与等方面来看&#xff0c;开源大模型和闭源大模型各有优劣势。开源模型在透明度、社区协作和成本效益方面具有优势&#xff0c;而闭源模型在安全性、合规性和商业竞争力方面表现出色。因此&#xff0c;我更倾向于认为&#xff0c;未来的大模型发展…

#php的pecl工具#

pecl&#xff08;php拓展社区库&#xff0c;pear拓展版本&#xff09;是一个官方的php扩展仓库&#xff0c;提供了众多优秀的php扩展供开发人员使用,作用主要是给php安装php扩展 1:安装PECL 首先&#xff0c;需要确保已安装PHP和PECL。PECL通常随着PHP一起安装&#xff0c;但…

【Python】 Python中__slots__的妙用:提升性能与内存管理

基本原理 在Python中&#xff0c;每个类默认都会继承自object类&#xff0c;而object类在Python中是一个动态类&#xff0c;允许动态地添加属性和方法。这种灵活性使得Python在某些情况下非常强大和灵活&#xff0c;但同时也带来了一些性能和内存使用上的开销。 为了解决这个…

互联网十万个为什么之什么是容器?

容器是一种虚拟化技术&#xff0c;用于将应用程序及其所有依赖项打包在一起&#xff0c;以便在不同的计算环境中进行移植和运行。容器提供了一种隔离的运行环境&#xff0c;使不同应用程序能够在独立的文件系统、网络和进程空间等独立运行环境中运行&#xff0c;提升了安全性和…

Spring:事务

1. 简介 spring对jdbc进行封装&#xff0c;简化对数据库的操作 2. HelloWorld 1. 搭建模块 2.加入依赖 <dependencies><!--spring jdbc Spring 持久化层支持jar包--><dependency><groupId>org.springframework</groupId><artifactId>s…

设计模式 22 访问者模式 Visitor Pattern

设计模式 22 访问者模式 Visitor Pattern 1.定义 访问者模式是一种行为型设计模式&#xff0c;它允许你在不改变已有类结构的情况下&#xff0c;为一组对象添加新的操作。它将算法与对象结构分离&#xff0c;使你能够在不修改现有类的情况下&#xff0c;为这些类添加新的操作。…

Flink系列一:flink光速入门 (^_^)

引入 spark和flink的区别&#xff1a;在上一个spark专栏中我们了解了spark对数据的处理方式&#xff0c;在 Spark 生态体系中&#xff0c;对于批处理和流处理采用了不同的技术框架&#xff0c;批处理由 Spark-core,SparkSQL 实现&#xff0c;流处理由 Spark Streaming 实现&am…

什么是深拷贝和浅拷贝?

浅拷贝 浅拷贝是指将一个对象复制到另一个变量中&#xff0c;但是复制的是对象的地址&#xff0c;而不是对对象本身进行复制。原始对象的引用和复制对象的引用时期上是共享同一个内存地址的。 所以我们修改了复制引用指向的对象中的属性或方法&#xff0c;原始引用指向的对象…

metersphere发送kafka消息

上传jar包 设置前置脚本 import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerRecord; import java.util.Properties;// Kafka 生产者配置 Properties props new Properties(); props.put("bootstrap.servers&qu…

JavaWeb_SpringBootWeb

先通过一个小练习简单了解以下SpringBootWeb。 小练习&#xff1a; 需求&#xff1a;使用SpringBoot开发一个Web应用&#xff0c;浏览器发起请求/hello后&#xff0c;给浏览器返回字符串"Hello World~"。 步骤&#xff1a; 1.创建SpringBoot项目&#xff0c;勾选We…

如何合并git分支

在一些情况下我得git仓库会进行一些技术分支的测试&#xff0c;我也不确定这种方案的效果会比原本的更好需要试一下&#xff0c;这种情况下我们创建一个分支进行开发&#xff0c;开发完成后确定采用这种方案再把这一分支合并到主分支。 1. 切换到主分支 git checkout master 其…