Android 自动灭屏系统休眠,修改Android 休眠逻辑使系统关屏而不进入休眠

近日接到一个比较诡异的产品需求,在我看来需要修改Android PMS。

具体需求如下:

要求在某一Activity界面在灭屏之后也能监听屏幕的手势事件,在我看来这种手势事件需求应该放在TP的驱动中来完成是最合理的,但是无奈硬件选型已过,而且手势不能完全支持我们的产品需求,无奈放弃底层的思路,开始改上层的电源管理逻辑。

首先说一下我修改的思路和逻辑,PMS在走休眠流程的时候,判断一下topActivity是不是该特殊需求的Activity,然后再决定走不走常规休眠流程,如果是,则发一个广播给activity,让该activity去持有亮屏的wakelock,同时强行操作背光的亮度节点,直接关屏;不过不是,就走常规的休眠流程喽~~~

再者,就是上一步提到系统进入休眠的代码段了,一种是PowerKey直接触发,一种是Timeout计时。

下边上我修改的PMS的代码部分:

diff --git a/frameworks/base/services/java/com/android/server/power/PowerManagerService.java b/frameworks/base/services/java/com/android/server/power/PowerManagerService.java

index 8dc0c7a..3e69a57 100755

--- a/frameworks/base/services/java/com/android/server/power/PowerManagerService.java+++ b/frameworks/base/services/java/com/android/server/power/PowerManagerService.java@@ -29,6 +29,7 @@ import com.android.server.display.DisplayManagerService;

import com.android.server.dreams.DreamManagerService;

import android.Manifest;

+import android.content.ComponentName;import android.content.BroadcastReceiver;

import android.content.ContentResolver;

import android.content.Context;

@@ -66,6 +67,8 @@ import android.util.TimeUtils;

import android.view.WindowManagerPolicy;

import android.view.Display;

+import android.app.ActivityManager;

+

import java.io.FileDescriptor;

import java.io.IOException;

import java.io.PrintWriter;

@@ -88,6 +91,9 @@ public final class PowerManagerService extends IPowerManager.Stub

implements Watchdog.Monitor {

private static final String TAG = "PowerManagerService";

+ static final String VINCI_MEDIA_PLAY_ACTIVITY = "ConnectActivity";

+ static boolean hasVinciWakelock = false;

+

private static final boolean DEBUG = true;

private static final boolean DEBUG_SPEW = DEBUG && true;

@@ -941,6 +947,8 @@ public final class PowerManagerService extends IPowerManager.Stub

applyWakeLockFlagsOnAcquireLocked(wakeLock);

mDirty |= DIRTY_WAKE_LOCKS;

updatePowerStateLocked();

+ if (tag != null && tag.contains("VINCI"))

+ hasVinciWakelock = true;

}

}

@@ -1011,6 +1019,8 @@ public final class PowerManagerService extends IPowerManager.Stub

applyWakeLockFlagsOnReleaseLocked(wakeLock);

mDirty |= DIRTY_WAKE_LOCKS;

updatePowerStateLocked();

+ if (wakeLock.mTag != null && (wakeLock.mTag).contains("VINCI"))

+ hasVinciWakelock = false;

}

}

@@ -1684,6 +1694,8 @@ public final class PowerManagerService extends IPowerManager.Stub

default:

Slog.i(TAG, "Going to sleep by user request...");

reason = PowerManager.GO_TO_SLEEP_REASON_USER;

+

+ if(ifSendNoSleepBroadcast()) return false;

break;

}

@@ -1727,6 +1739,21 @@ public final class PowerManagerService extends IPowerManager.Stub

return true;

}

+ private boolean ifSendNoSleepBroadcast() {

+ ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);

+ ComponentName cn = am.getRunningTasks(Integer.MAX_VALUE).get(0).topActivity;

+ if (null != cn && (cn.getClassName()).contains(VINCI_MEDIA_PLAY_ACTIVITY)) {

+ //not true sleep

+ Intent noSleepAction = new Intent("VINCI_MEDIA_PLAY_NOSLEEP_ACTION");

+ if (mContext != null) {

+ mContext.sendBroadcast(noSleepAction);

+ Log.e(TAG, "======I will send broadcast to top activity.\n");

+ return true;

+ }

+ }

+ return false;

+ }

+

@Override // Binder call

public void nap(long eventTime) {

if (eventTime > SystemClock.uptimeMillis()) {

@@ -1799,18 +1826,22 @@ public final class PowerManagerService extends IPowerManager.Stub

// Phase 0: Basic state updates.

updateIsPoweredLocked(mDirty);

+ Slog.e(TAG, "after updateIsPoweredLocked ======\n");updateStayOnLocked(mDirty);

+ Slog.e(TAG, "after updateStayOnLocked ======\n");

// Phase 1: Update wakefulness.

// Loop because the wake lock and user activity computations are influenced

// by changes in wakefulness.

final long now = SystemClock.uptimeMillis();

int dirtyPhase2 = 0;

+ Slog.e(TAG, "updatePowerStateLocked before for loop ======\n");for (;;) {

int dirtyPhase1 = mDirty;

dirtyPhase2 |= dirtyPhase1;

mDirty = 0;

+ Slog.e(TAG, "in for loop ======\n");updateWakeLockSummaryLocked(dirtyPhase1);

updateUserActivitySummaryLocked(now, dirtyPhase1);

if (!updateWakefulnessLocked(dirtyPhase1)) {

@@ -2136,6 +2167,7 @@ else

Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);

msg.setAsynchronous(true);

mHandler.sendMessageAtTime(msg, nextTimeout);

+ Slog.e(TAG, "PMS send MSG_USER_ACTIVITY_TIMEOUT broadcast======\n");}

} else {

mUserActivitySummary = 0;

@@ -2181,6 +2213,8 @@ else

Slog.d(TAG, "handleUserActivityTimeout");

}

+ if(!hasVinciWakelock && ifSendNoSleepBroadcast()) return;

+

mDirty |= DIRTY_USER_ACTIVITY;

updatePowerStateLocked();

} else {

WakeLock申请注册部分:

pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

mWakelock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "VINCI Wakelock");

filter.addAction("VINCI_MEDIA_PLAY_NOSLEEP_ACTION");

将上述三句添加至onCreate方法。

逻辑跟我之前所说的思路吻合, ifSendNoSleepBroadcast()这个方法的目的就是判断是否发送广播的时机,有两处改动中调用了,分别是PowerKey和Timeout两种情况的休眠代码段。hasVinciWakelock该值用来标示当前Activity有没有持有亮屏的wakelock,判断的条件是根据if (wakeLock.mTag != null && (wakeLock.mTag).contains("VINCI"))来,这就要求activity在申请锁的时候添加的tag字段和此处判断一致。

第二部,我们来看activity对屏幕及wake lock的处理逻辑添加。

} else if (mediaAction.equals(action)) {

try {

Process pcs = Runtime.getRuntime().exec("lcd value");

// 获取shell返回流

BufferedInputStream in = new BufferedInputStream(pcs.getInputStream());

// 字符流转换字节流

BufferedReader br = new BufferedReader(new InputStreamReader(in));

// 这里也可以输出文本日志

String lineStr;

while ((lineStr = br.readLine()) != null) {

result = lineStr;

}

br.close();

in.close();

Log.e(TAG, "==================" + result);

if (0 < Integer.valueOf(result).intValue()) {

if (!hasWakelock) {

Runtime.getRuntime().exec("lcd off");

Log.e(TAG, "exec lcd off\n");

mWakelock.acquire();

Log.e(TAG, "have wakelock\n");

hasWakelock = true;

}

} else {

if (hasWakelock) {

Runtime.getRuntime().exec("lcd on");

Log.e(TAG, "exec lcd on\n");

mWakelock.release();

Log.e(TAG, "wakelock release\n");

hasWakelock = false;

}

}

} catch (Exception e) {}

}

这里边涉及对一个lcd脚本的操作,稍后附上该脚本内容,切换屏幕亮度的值结合是否持有wakelock联合判断,因此需要处理脚本返回的亮度值,从而关屏或者恢复关屏之前的亮度值。

最后,附上脚本的内容,lcd命名的脚本,放置system/bin下即可。

#!/system/bin/sh

echo $1

light_path=/sys/class/leds/lcd-backlight/brightness

if [ $1 == "on" ];then

echo "lcd on"

echo 255 > $light_path

elif [ $1 == "off" ];then

echo "lcd off"

echo 0 > $light_path

elif [ $1 == "value" ];then

echo `cat $light_path`

fi

核心点:理清PMS休眠的流程逻辑,wakelcok相关操作,最后当然是shell脚本功底了。

大功告成~~~需要联测验证是否能达到需求哦,谨以此文,做工作记录,方便日后查验,供有类似需求的同仁参考。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值