文章目录
- 需求-场景
- 参考资料
- 界面引导
- 源码分析
- 需求实现
需求-场景
Android机器实现息屏方式同时,实现屏保功能。如果是屏保,定时进入屏保。
需求场景来源
1)Android产品自带息屏时间,可以选择息屏时间,时间到后自动进入息屏状态。
2)切换一种模式,如果是屏保模式,那么时间到后进入屏保。
3)更多的需求是自定义屏保功能,实现客制化需求。 暂不考虑 相关资料可参考
延伸知识点
很多上电不带电池工控产品,不用考虑电池电量问题。息屏模式下屏幕黑的给人感觉不太好。
息屏情况下,亮屏逻辑有两种,点触亮屏和按键亮屏。【点触也是将屏幕触摸功能打开,亮度熄灭逻辑】。
如果机器产品没有触摸亮屏功能,亮屏幕必须按键亮屏,比较麻烦。
实现屏保功能,息屏时间到时候直接进入屏保,提升交互体验。
息屏关闭屏幕亮度+进入屏保界不关闭屏幕亮度+是否点触亮屏 各有优劣,不同需求和用户习惯场景都有自身存在的价值。
参考资料
Android 10 如何自定义屏保功能:
Android 屏保开关:
Android 系统默认屏保:
Android R DreamManagerService分析:
息屏显示实现
Android - PowerManagerService 启动:
publishBinderService和publishLocalService区别:
Android系統中的LocalService:
相关资源需要看一看,了解基本的知识内容,同时在解决问题的过程中针对性的再次看看相关资料参考,会有很大的帮助的。
界面引导
比如我们需要实现的界面如下,屏保模式、屏保时间、屏幕模式
屏保功能在 设置->显示->屏保 可以选择屏保,界面如下
如果选择了屏保则立即进入选择的屏保
源码分析
StartNowPreferenceController
从设置界面,立即启动屏保界面查看源码
fise4@ubuntu-PowerEdge-R730:~/Android/mt6769-alps-release-s0.mp1.rc/alps-release-s0.mp1.rc$ find . -name StartNowPreferenceController.java
./packages/apps/Settings/src/com/android/settings/dream/StartNowPreferenceController.java
./vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/dream/StartNowPreferenceController.java
/**
* Controller that used to enable screen saver
*/
public class StartNowPreferenceController extends SettingsMainSwitchPreferenceController {
private final DreamBackend mBackend;
private final MetricsFeatureProvider mMetricsFeatureProvider;
public StartNowPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mBackend = DreamBackend.getInstance(context);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void updateState(Preference preference) {
mSwitchPreference.setChecked(false);
mSwitchPreference.setEnabled(mBackend.getWhenToDreamSetting() != DreamBackend.NEVER);
}
@Override
public boolean isChecked() {
return false;
}
@Override
public boolean setChecked(boolean isChecked) {
if (isChecked) {
if (mSwitchPreference != null) {
mMetricsFeatureProvider.logClickedPreference(mSwitchPreference,
mSwitchPreference.getExtras().getInt(DashboardFragment.CATEGORY));
}
mBackend.startDreaming();
}
return true;
}
}
核心代码:
@Override
public boolean setChecked(boolean isChecked) {
if (isChecked) {
if (mSwitchPreference != null) {
mMetricsFeatureProvider.logClickedPreference(mSwitchPreference,
mSwitchPreference.getExtras().getInt(DashboardFragment.CATEGORY));
}
mBackend.startDreaming();
}
return true;
}
DreamDreamBackend.java
/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);
}
}
所以,立即进入屏保最终调用方法 mDreamManager.dream()方法
mDreamManager 定义:
private final IDreamManager mDreamManager;
//获取DreamManager的实例:使用getSystemService()方法并 来获取DreamManager的实例。
mDreamManager = IDreamManager.Stub.asInterface(
ServiceManager.getService(DreamService.DREAM_SERVICE));
DreamManagerService.java
==>\frameworks\base\core\java\android\service\dreams\IDreamManager.aidl
==>/frameworks/base/services/core/java/com/android/server/dreams/DreamManagerService.java
@Override // Binder call
public void dream() {
checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
final long ident = Binder.clearCallingIdentity();
try {
requestDreamInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private void requestDreamInternal() {
// Ask the power manager to nap. It will eventually call back into
// startDream() if/when it is appropriate to start dreaming.
// Because napping could cause the screen to turn off immediately if the dream
// cannot be started, we keep one eye open and gently poke user activity.
long time = SystemClock.uptimeMillis();
mPowerManager.userActivity(time, true /*noChangeLights*/);
mPowerManager.nap(time);
}
屏保的立即开启 居然进入到了PowerManagerService 里面
mPowerManager 定义和初始化地方:
PowerManager mPowerManager;
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
PowerManagerService
nap 方法跟踪
./frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
nap ->dreamDisplayGroup ->updatePowerStateLocked->
@Override // Binder call
public void nap(long eventTime) {
if (eventTime > mClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
dreamDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private void dreamDisplayGroup(int groupId, long eventTime, int uid) {
synchronized (mLock) {
if (