Android R Settings关于屏保/PowerManagerService欺骗系统不让其进入休眠状态
old
//屏保设置界面
./packages/apps/Settings/src/com/android/settings/dream/DreamSettings.java
//和PowerManagerService 建立联系
./frameworks/base/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
//系统时钟屏保 继承了DreamService
./packages/apps/DeskClock/src/com/android/deskclock/Screensaver.java
./packages/apps/DeskClock/src/com/android/deskclock/ScreensaverActivity.java
public static final String SCREENSAVER_ENABLED = "screensaver_enabled";
adb shell settings get secure screensaver_enabled
0 false(never)
如何替换activityt退出(finish)的动画
private void textFinish() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//finish();
finishAndRemoveTask();//使用这个
}
}, 0);
}
//复写finishAndRemoveTask
@Override
public void finishAndRemoveTask() {
super.finishAndRemoveTask();
overridePendingTransition(0, R.anim.dream_activity_close_exit);
}
//R.anim.dream_activity_close_exit
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="100" />
android 屏保 (PowerManager & DreamService)
android 系统休眠过程四个状态,分别是SCREEN_BRIGHT,SCREEN_DIM,SCREEN_DREAM,SLEEP
思路1:不让系统进入后面两个状态,保持在SCREEN_DREAM,然后发送广播,操作屏幕背光--->我把它叫做假休眠(fake_sleep_mode)
(或者保持在SCREEN_DREAM后,拉起一个服务,在界面上添加一个的window,window上面布局随意,点击之后移除)
+++ b/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
@@ -140,6 +140,8 @@ public final class PowerManagerService extends SystemService
private static final int MSG_CHECK_FOR_LONG_WAKELOCKS = 4;
// Message: Sent when an attentive timeout occurs to update the power state.
private static final int MSG_ATTENTIVE_TIMEOUT = 5;
+ // Message: enter fake sleep mode
+ private static final int MSG_FAKE_SLEEP_MODE = 6;//add text
// Dirty bit: mWakeLocks changed
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -1722,6 +1724,9 @@ public final class PowerManagerService extends SystemService
}
}
+ //fake sleep mode flag
+ private int fake_sleep_init = 0;//add text
+
private void updateUserActivitySummaryLocked(long now, int dirty) {
...
if (Integer.MAX_VALUE == screenOffTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
//Slog.d(TAG, "set mUserActivitySummary USER_ACTIVITY_SCREEN_BRIGHT never sleep " + nextTimeout);
}
if (mUserActivitySummary != 0 && nextTimeout >= 0) {
scheduleUserInactivityTimeout(nextTimeout);
}
} else {
mUserActivitySummary = 0;
}
//add text
if(mUserActivitySummary == 1 && fake_sleep_init > 0){
fake_sleep_init = 0;
Slog.d(TAG, "fake_sleep_init: reset");
}
//add text
...
}
@SuppressWarnings("deprecation")
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
+ ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
}
//add text
int fake_sleep_mode = SystemProperties.getInt("xxx.sys.fake_sleep_xxx", 0);
if (fake_sleep_mode == 0) {
if (fake_sleep_init == 0) {
Message fake_msg = mHandler.obtainMessage(MSG_FAKE_SLEEP_MODE);
fake_msg.setAsynchronous(true);
mHandler.sendMessage(fake_msg);
fake_sleep_init++;
}
return false;
}
//add text
if (eventTime < mLastWakeTime
|| getWakefulnessLocked() == WAKEFULNESS_ASLEEP
|| getWakefulnessLocked() == WAKEFULNESS_DOZING
|| !mSystemReady
|| !mBootCompleted) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
try {
reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,
Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));
Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)
+ " (uid " + uid + ")...");
mLastSleepTime = eventTime;
mLastSleepReason = reason;
mSandmanSummoned = true;
mDozeStartInProgress = true;
setWakefulnessLocked(WAKEFULNESS_DOZING, reason, eventTime);
...
}
private final class PowerManagerHandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY_TIMEOUT:
handleUserActivityTimeout();
break;
...
//add text
case MSG_FAKE_SLEEP_MODE:
//发送广播去关闭背光
Slog.d(TAG, "Fake sleep mode , entering clock screen...");
Intent intent = new Intent("sys.android.fake.sleep.action");
intent.setPackage("com.android.settings");
mContext.sendBroadcastAsUser(intent,UserHandle.ALL);
break;
//add text
Android 系统全局监听touch事件,在背光关闭的情况下.
./frameworks/base/core/java/android/view/WindowManagerPolicyConstants.java
// TODO: move this to a more appropriate place.
interface PointerEventListener {
/**
* 1. onPointerEvent will be called on the service.UiThread.
* 2. motionEvent will be recycled after onPointerEvent returns so if it is needed later a
* copy() must be made and the copy must be recycled.
**/
void onPointerEvent(MotionEvent motionEvent);
}
+++ b/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1149,7 +1149,7 @@ public class WindowManagerService extends IWindowManager.Stub
String[] args, ShellCallback callback, ResultReceiver result) {
new WindowManagerShellCommand(this).exec(this, in, out, err, args, callback, result);
}
-
+ private static Context t_context;
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
@@ -1159,6 +1159,7 @@ public class WindowManagerService extends IWindowManager.Stub
mGlobalLock = atm.getGlobalLock();
mAtmService = atm;
mContext = context;
+ t_context = context;
mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
mAllowBootMessages = showBootMsgs;
mOnlyCore = onlyCore;
@@ -6805,6 +6806,8 @@ public class WindowManagerService extends IWindowManager.Stub
MousePositionTracker mMousePositionTracker = new MousePositionTracker();
+ private static int x_init = 0;//模拟当前背光状态
private static class MousePositionTracker implements PointerEventListener {
private boolean mLatestEventWasMouse;
private float mLatestMouseX;
...
} else {
synchronized (this) {
mLatestEventWasMouse = false;
+ //add text
+ if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && x_init == 0){
+ android.util.Log.d("tag","motionEvent---ACTION_DOWN.");
+ mContext.sendBroadcast(new Intent("sys.android.fake.sleep.awake.action"));//发送广播点亮背光
+ x_init++;
+ }
+ //add text
}
}
}
./frameworks/base/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java:39:
class SystemGesturesPointerEventListener implements PointerEventListener {
./frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java:6808:
private static class MousePositionTracker implements PointerEventListener {
./frameworks/base/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java:37:
public class TaskTapPointerEventListener implements PointerEventListener {
add Dialog/add Window
//add text
private static TimeLayoutDialog mDialog;
private void createTextDialog() {
TimeLayoutDialog dialog = new TimeLayoutDialog(mContext);
mDialog = dialog;
mDialog.show();
}
static final class TimeLayoutDialog extends Dialog {
private final Context TContext;
TimeLayoutDialog(Context context) {
super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
TContext = context;
Window window = getWindow();
window.requestFeature(Window.FEATURE_NO_TITLE);
window.getDecorView();
window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
window.setLayout(MATCH_PARENT, MATCH_PARENT);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.addFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
window.getAttributes().setFitInsetsTypes(0 /* types */);
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
window.getDecorView().setSystemUiVisibility(uiOptions);
initializeLayout();
}
private void initializeLayout() {
setContentView(com.android.systemui.R.layout.global_actions_time);
ViewGroup black_view = findViewById(com.android.systemui.R.id.time_action_root);
black_view.setClickable(true);
black_view.setOnClickListener(v -> {
if (mDialog != null) mDialog.dismiss();
});
TextClock timeClock = findViewById(com.android.systemui.R.id.tc_timeText);
setTimeFormat(timeClock, false);
}
private CharSequence get24ModeFormat(boolean includeSeconds) {
return DateFormat.getBestDateTimePattern(Locale.getDefault(), includeSeconds ? "Hms" : "Hm");
}
private CharSequence get12ModeFormat(float amPmRatio, boolean includeSeconds) {
String pattern = android.text.format.DateFormat.getBestDateTimePattern(Locale.getDefault(),
includeSeconds ? "hmsa" : "hma");
if (amPmRatio <= 0) {
pattern = pattern.replaceAll("a", "").trim();
}
// Replace spaces with "Hair Space"
pattern = pattern.replaceAll(" ", "\u200A");
// Build a spannable so that the am/pm will be formatted
int amPmPos = pattern.indexOf('a');
if (amPmPos == -1) {
return pattern;
}
final Spannable sp = new SpannableString(pattern);
sp.setSpan(new RelativeSizeSpan(amPmRatio), amPmPos, amPmPos + 1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
sp.setSpan(new StyleSpan(Typeface.NORMAL), amPmPos, amPmPos + 1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
sp.setSpan(new TypefaceSpan("sans-serif"), amPmPos, amPmPos + 1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sp;
}
private void setTimeFormat(TextClock clock, boolean includeSeconds) {
if (clock != null) {
// Get the best format for 12 hours mode according to the locale
clock.setFormat12Hour(get12ModeFormat(0.4f /* amPmRatio */, includeSeconds));
// Get the best format for 24 hours mode according to the locale
clock.setFormat24Hour(get24ModeFormat(includeSeconds));
}
}
}
//add text
//adout R.layout.global_actions_time's widget
<TextClock
android:id="@+id/tc_timeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="18dp"
android:format12Hour="hh:mm"
android:format24Hour="HH:mm"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="85sp"
android:textStyle="italic" />
<TextClock
android:id="@+id/tc_dateText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:format12Hour="E,MMM dd"
android:format24Hour="E,MMM dd"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="25sp"
android:textStyle="italic" />
repair bug
上面的方案导致的bug:
persist.xxx.fake_sleep_enable 为true时 , 影响到了正常power键短按灭亮屏的流程.
分析:
当时为了不让系统进入sleep,在PMS::goToSleepNoUpdateLocked
返回了false(做了拦截),但是power的灭屏流程也会经过这里,
导致bug的出现.
解决:
还是在原有方案的基础上改进,多添加一个SystemProperties.set("hello.xxx.power_xxx_sleep", "true")
的变量进行判断,
系统按压power时,将它置为true,不拦截,走正常的灭屏流程,当设备亮屏时,置为false,继续拦截.
private void powerPress(long eventTime, boolean interactive, int count) {
...
Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive
+ " count=" + count + " beganFromNonInteractive=" + mBeganFromNonInteractive +
" mShortPressOnPowerBehavior=" + mShortPressOnPowerBehavior);
}
powerPress: eventTime=3705285 interactive=true count=1 beganFromNonInteractive=false mShortPressOnPowerBehavior=1
private boolean goToSleepFromPowerButton(long eventTime, int flags) {...}
实际修改之后操作发现:
正常的息屏休眠,走updatePowerStateLocked,
但是如果先按power键灭屏,在亮屏,之后就发现发现息屏休眠流程不走goToSleepNoUpdateLocked,原因是插了usb连接了adb,用了AS的虚拟投屏(具体原因不知道),反正断了adb,就正常了.也是个乌龙...
具体也没去细查了,换了一个地方让其在界面上添加一个的window/dialog.
下面就是goToSleepNoUpdateLocked
的堆栈:
2024-09-05 17:04:32.636 507-547 WindowManager system_server D java.lang.Throwable
at com.android.server.power.PowerManagerService.goToSleepNoUpdateLocked(PowerManagerService.java:1743)
at com.android.server.power.PowerManagerService.updateWakefulnessLocked(PowerManagerService.java:2598)
at com.android.server.power.PowerManagerService.updatePowerStateLocked(PowerManagerService.java:1956)
at com.android.server.power.PowerManagerService.handleUserActivityTimeout(PowerManagerService.java:2515)
at com.android.server.power.PowerManagerService.access$3600(PowerManagerService.java:127)
at com.android.server.power.PowerManagerService$PowerManagerHandlerCallback.handleMessage(PowerManagerService.java:4459)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:223)
at android.os.HandlerThread.run(HandlerThread.java:67)
at com.android.server.ServiceThread.run(ServiceThread.java:44)
2024-09-05 17:04:00.009 507-507 WindowManager system_server D java.lang.Throwable
at com.android.server.power.PowerManagerService.goToSleepNoUpdateLocked(PowerManagerService.java:1743)
at com.android.server.power.PowerManagerService.updateWakefulnessLocked(PowerManagerService.java:2598)
at com.android.server.power.PowerManagerService.updatePowerStateLocked(PowerManagerService.java:1956)
at com.android.server.power.PowerManagerService.removeWakeLockLocked(PowerManagerService.java:1441)
at com.android.server.power.PowerManagerService.releaseWakeLockInternal(PowerManagerService.java:1409)
at com.android.server.power.PowerManagerService.access$4700(PowerManagerService.java:127)
at com.android.server.power.PowerManagerService$BinderService.releaseWakeLock(PowerManagerService.java:4840)
at android.os.PowerManager$WakeLock.release(PowerManager.java:2548)
at android.os.PowerManager$WakeLock.release(PowerManager.java:2518)
at com.android.server.AlarmManagerService$DeliveryTracker.updateTrackingLocked(AlarmManagerService.java:4628)
at com.android.server.AlarmManagerService$DeliveryTracker.alarmComplete(AlarmManagerService.java:4671)
at com.android.server.AlarmManagerService$3.lambda$doAlarm$0$AlarmManagerService$3(AlarmManagerService.java:1545)
at com.android.server.-$$Lambda$AlarmManagerService$3$jIkPWjqS66vG6aFVQoHxR2w4HPE.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at com.android.server.SystemServer.run(SystemServer.java:629)
at com.android.server.SystemServer.main(SystemServer.java:415)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:925)
diff:
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
private void updateUserActivitySummaryLocked(long now, int dirty) {
...
if (Integer.MAX_VALUE == screenOffTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
//Slog.d(TAG, "set mUserActivitySummary USER_ACTIVITY_SCREEN_BRIGHT never sleep " + nextTimeout);
}
if (mUserActivitySummary != 0 && nextTimeout >= 0) {
scheduleUserInactivityTimeout(nextTimeout);
}
} else {
mUserActivitySummary = 0;
}
//add text
if(mUserActivitySummary == 1 && fake_sleep_init > 0){
fake_sleep_init = 0;
Slog.d(TAG, "fake_sleep_init: reset");
}
boolean fake_sleep_mode = SystemProperties.getBoolean("persist.xxx.fake_sleep_xxxx", false);
if(fake_sleep_mode ){
if (mUserActivitySummary == 4 && fake_sleep_init == 0) {
Message fake_msg = mHandler.obtainMessage(MSG_FAKE_SLEEP_MODE);
fake_msg.setAsynchronous(true);
mHandler.sendMessage(fake_msg);
fake_sleep_init++;
}
}
//add text
...
}
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
+ ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
}
//add text
boolean power_sleep_mode = SystemProperties.getBoolean("hello.xxx.power_xxx_sleep", false);
boolean fake_sleep_mode = SystemProperties.getBoolean("persist.xxx.fake_sleep_xxx", false);
if (fake_sleep_mode && !power_sleep_mode) {
return false;
}
//add text
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
private boolean goToSleepFromPowerButton(long eventTime, int flags) {
...
//add text
boolean fake_sleep_mode = SystemProperties.getBoolean("persist.xxx.fake_sleep_xxx", false);
if (fake_sleep_mode){
SystemProperties.set("hello.xxx.power_xxx_sleep", "true");
Intent fake_wakeup_intent = new Intent("xxx.xx.xx.wakeup.action");
fake_wakeup_intent.setPackage("com.xx.xx");
mContext.sendBroadcast(fake_wakeup_intent);
}
//add text
...
goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, flags);
return true;
}
private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason,
String details) {
...
//add text
boolean fake_sleep_mode = SystemProperties.getBoolean("persist.sys.fake_sleep_enable", false);
if (fake_sleep_mode){
SystemProperties.set("hello.xxx.power_xxx_sleep", "false");
}
//add text
mPowerManager.wakeUp(wakeTime, reason, details);
...
return true;
}
亮屏流程:
PowerManagerService::wakeUp(...)-->wakeUpInternal()-->wakeUpNoUpdateLocked()[更新验证和灭屏状态更新]...
system_server主线程执行PhoneWindowManager#startedWakingUp()方法,通知WMS开始亮屏
-->system_server主线程发送亮屏广播-->向DMS(DisplayManagerService)请求Display状态和亮度
-->DMS返回请求状态后,system_server主线程执行PhoneWindowManager::finishedWakingUp()通知WMS模块完成亮屏
灭屏流程(power key press):
PowerManagerService::goToSleep(...)-->goToSleepInternal()-->goToSleepNoUpdateLocked()-->updatePowerStateLocked()
-->reallyGoToSleepNoUpdateLocked()
-->Notifier::handleEarlyInteractiveChange(){
synchronized (mLock) {
if (mInteractive) {
......
} else {
// Going to sleep...
// 通知WMS开始灭屏
final int why = translateOffReason(mInteractiveChangeReason);
mHandler.post(new Runnable() {
@Override
public void run() {
mPolicy.startedGoingToSleep(why);
}
});
}
}
}
Android R PowerManagerService 亮屏流程
Android R PowerManagerService模块(4) 灭屏流程
Android 11.0 Power 键亮屏灭屏流程分析
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee