Android4.4 灭屏kill第三方app

时间:2021-12-30 14:34:15

在android4.4上添加功能当手机短按power键,灭屏的时候。kill三方的app进程。

在我之前的博客中分析过,按键处理,会从InputManager的native层,先到PhoneWindowManager的interceptKeyBeforeQueueing函数,先对按键进行处理,比如power键,会禁止把这Event传给应用。

下来我们来看下源码实现:

@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
..........
int result;
if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) {
// When the screen is on or if the key is injected pass the key to the application.
result = ACTION_PASS_TO_USER;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
result = 0;
if (down && isWakeKey && isWakeKeyWhenScreenOff(keyCode) && !mRejectShortPressPowerKey) {
result |= ACTION_WAKE_UP;
sendBootCompleted();//新加,杀了进程之后,起开的时候发一个开机广播,防止有些应用是根据这个广播启动的
}
}
...........


case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn, event.getDownTime(),
isImmersiveMode(mLastSystemUiFlags));
if (isScreenOn && !mPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mPowerKeyTriggered = true;
mPowerKeyTime = event.getDownTime();
interceptScreenshotChord();
}

ITelephony telephonyService = getTelephonyService();
boolean hungUp = false;
if (telephonyService != null) {
try {
if (telephonyService.isRinging()) {
// Pressing Power while there's a ringing incoming
// call should silence the ringer.
telephonyService.silenceRinger();
} else if ((mIncallPowerBehavior
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
&& telephonyService.isOffhook()) {
// Otherwise, if "Power button ends call" is enabled,
// the Power button will hang up any current active call.
hungUp = telephonyService.endCall();
}
} catch (RemoteException ex) {
Log.w(TAG, "ITelephony threw RemoteException", ex);
}
}
Log.i(TAG, "PowerKey down, isScreenOn = " + isScreenOn);
interceptPowerKeyDown(!isScreenOn || hungUp
|| mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
} else {
Log.i(TAG, "PowerKey up");
mPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
KillProcess();//到kill进程的函数
}
mPendingPowerKeyUpCanceled = false;
}
break;
}
........
}

代码中在返回result的标志位有ACTION_GO_TO_SLEEP的时候,开启kill进程,返回ACTION_WAKE_UP的时候,发送开机广播(防止一些应用根据开机广播启动)


至于这个goToSleep和wakeUp的处理,and4.4和5.1有差别。4.4是InputManager的native层根据PhoneWindowManager返回的flag,然后在native层去调PowerManagerService的goToSleep和wakeup函数。而5.1之后就直接在PhoneWindowManager中去调PowerManagerService的这两个函数。没有在native层绕了一把。


下面我们再看下killProcess这个函数:

    private void sendBootCompleted() {//发送开机广播
Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
mContext.sendBroadcast(intent);
}

private void KillProcess() {
List<ActivityManager.RunningAppProcessInfo> appProcessList = null;
appProcessList = mActivityManager.getRunningAppProcesses();//获取运行的app列表

for (ActivityManager.RunningAppProcessInfo appProcessInfo : appProcessList) {
int pid = appProcessInfo.pid;
int uid = appProcessInfo.uid;
String processName = appProcessInfo.processName;
PackageManager pm = mContext.getPackageManager();
try {
ApplicationInfo appinfo = pm.getApplicationInfo(processName, 0);//获取applicationinfo
boolean isSystemApp = (appinfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1;//判断是否系统应用
if (!isSystemApp) {
Log.d(TAG, "process '" + processName + "' will be killed");
mActivityManager.forceStopPackage(processName);
}
} catch(NameNotFoundException e) {
Log.e(TAG, "can not find processName:" + processName);
}
}
}