Android system实战 — Android R 进程保活白名单
- 0. 前言
- 1. 具体实现
- 1.1 准备工作
- 1.2 源码实现
- 1.2.1 源码
- 1.2.2 diff文件
0. 前言
最近在Android R上实现一些需求,进行记录一下,关于进程保活的基础知识可以参考Android system — 进程生命周期与ADJ,实际上本质上,就是在提高进程的adj等级,从而达到保活的效果,当然如果你不care原理,也可以直接看下面具体实现。
1. 具体实现
主要涉及源码路径:
platform/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
1.1 准备工作
在源码实现之前,我们需要先准备进程白名单,并将其编译至system/etc/app_oom_adj.txt
白名单格式如下:
通用格式:
-序号(整数),包名
其中,序号值越小,则意味着对应的包名进程越受到保护,越难被系统回收内存;
该功能设置后,查看是否生效,可以通过查看进程的adj值来确认:
ps -A | grep “进程名”
cat /proc/进程名对应PID/oom_score_adj
例如:
1.2 源码实现
platform/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
1.2.1 源码
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
import static android.os.Process.SCHED_OTHER;
import static android.os.Process.THREAD_GROUP_BACKGROUND;
import static android.os.Process.THREAD_GROUP_DEFAULT;
import static android.os.Process.THREAD_GROUP_RESTRICTED;
import static android.os.Process.THREAD_GROUP_TOP_APP;
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.setProcessGroup;
import static android.os.Process.setThreadPriority;
import static android.os.Process.setThreadScheduler;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ_REASON;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS;
import static com.android.server.am.ActivityManagerService.DISPATCH_OOM_ADJ_OBSERVER_MSG;
import static com.android.server.am.ActivityManagerService.IDLE_UIDS_MSG;
import static com.android.server.am.ActivityManagerService.TAG_BACKUP;
import static com.android.server.am.ActivityManagerService.TAG_LRU;
import static com.android.server.am.ActivityManagerService.TAG_OOM_ADJ;
import static com.android.server.am.ActivityManagerService.TAG_PROCESS_OBSERVERS;
import static com.android.server.am.ActivityManagerService.TAG_PSS;
import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
import static com.android.server.am.ActivityManagerService.TOP_APP_PRIORITY_BOOST;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import android.app.ActivityManager;
import android.app.ApplicationExitInfo;
import android.app.usage.UsageEvents;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ServiceInfo;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.compat.IPlatformCompat;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.WindowProcessController;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Vector;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* All of the code required to compute proc states and oom_adj values.
*/
public final class OomAdjuster {
private static final String TAG = "OomAdjuster";
static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange";
static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver";
......
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
return true;
});
mTmpUidRecords = new ActiveUids(service, false);
mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1);
mNumSlots = ((ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) >> 1)
/ ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
mPlatformCompat = IPlatformCompat.Stub.asInterface(b);
//for specific process priority guard
parseCustomsizedAppOomAdj("/system/etc/app_oom_adj.txt");
}
void initSettings() {
mCachedAppOptimizer.init();
if (mService.mConstants.KEEP_WARMING_SERVICES.size() > 0) {
final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
mService.mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mService) {
......
/** Inform the oomadj observer of changes to oomadj. Used by tests. */
@GuardedBy("mService")
void reportOomAdjMessageLocked(String tag, String msg) {
Slog.d(tag, msg);
if (mService.mCurOomAdjObserver != null) {
mService.mUiHandler.obtainMessage(DISPATCH_OOM_ADJ_OBSERVER_MSG, msg).sendToTarget();
}
}
private class AppOomAdj {
public int m_nOomAdj;
public String m_sAppName;
public AppOomAdj(int adj, String appname) {
this.m_nOomAdj = adj;
this.m_sAppName = appname;
}
}
private Vector<AppOomAdj> mVec = null;
private void parseCustomsizedAppOomAdj(String file) {
try {
FileReader fr = new FileReader(file);
BufferedReader br=new BufferedReader(fr);
String line = "";
String[] arrs=null;
AppOomAdj obj = null;
if (mVec == null) {
mVec = new Vector<AppOomAdj>();
}
while ((line=br.readLine()) != null) {
arrs=line.split(",");
obj = new AppOomAdj(Integer.parseInt(arrs[0]), arrs[1]);
mVec.add(obj);
}
br.close();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
@GuardedBy("mService")
private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
long nowElapsed) {
boolean success = true;
if (app.getCurRawAdj() != app.setRawAdj) {
app.setRawAdj = app.getCurRawAdj();
}
int changes = 0;
//Slog.d(TAG, "applyOomAdjLocked pkg: " + app.processName+",pid:"+ app.pid+",uid:"+ app.uid +",curAdj:"+app.curAdj+",setAdj:"+app.setAdj);
if (mVec != null) {
int i = 0;
int oom_score_adj = 0;
for (;i < mVec.size(); i++) {
if (app.processName.equals(mVec.get(i).m_sAppName)) {
//new curAdj point to {oom_score_adj}
oom_score_adj = mVec.get(i).m_nOomAdj;
app.curAdj = oom_score_adj;
//Slog.d(TAG, "applyOomAdjLocked pkg:"+app.processName+" mVec app.curAdj:"+app.curAdj);
}
}
}
// don't compact during bootup
if (mCachedAppOptimizer.useCompaction() && mService.mBooted) {
// Cached and prev/home compaction
if (app.curAdj != app.setAdj) {
// Perform a minor compaction when a perceptible app becomes the prev/home app
// Perform a major compaction when any app enters cached
// reminder: here, setAdj is previous state, curAdj is upcoming state
if (app.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ &&
(app.curAdj == ProcessList.PREVIOUS_APP_ADJ ||
......
}
1.2.2 diff文件
From 4a534042738f6793827ab51089bbdd0977b489ad Mon Sep 17 00:00:00 2001
From: yuefu.zhou <yuefu.zhou@amlogic.com>
Date: Fri, 03 Feb 2023 18:32:13 +0800
Subject: [PATCH] AMS: Support for configuring process priority. [2/2]
PD#IPTV-19626
Problem:
need support configure the process priority.
Solution:
Support for configuring process priority.
Verify:
S928X
Change-Id: If5f82e86f2a33a8cfbdf664d6079a9ad904fc4ac
Signed-off-by: yuefu.zhou <yuefu.zhou@amlogic.com>
---
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index faa7dce..2d0ce94 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -110,6 +110,12 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Vector;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
/**
* All of the code required to compute proc states and oom_adj values.
@@ -265,6 +271,9 @@
/ ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
mPlatformCompat = IPlatformCompat.Stub.asInterface(b);
+
+ //for specific process priority guard
+ parseCustomsizedAppOomAdj("/system/etc/app_oom_adj.txt");
}
void initSettings() {
@@ -2144,6 +2153,43 @@
}
}
+ private class AppOomAdj {
+ public int m_nOomAdj;
+ public String m_sAppName;
+ public AppOomAdj(int adj, String appname) {
+ this.m_nOomAdj = adj;
+ this.m_sAppName = appname;
+ }
+ }
+
+ private Vector<AppOomAdj> mVec = null;
+ private void parseCustomsizedAppOomAdj(String file) {
+ try {
+ FileReader fr = new FileReader(file);
+ BufferedReader br=new BufferedReader(fr);
+ String line = "";
+ String[] arrs=null;
+ AppOomAdj obj = null;
+
+ if (mVec == null) {
+ mVec = new Vector<AppOomAdj>();
+ }
+
+ while ((line=br.readLine()) != null) {
+ arrs=line.split(",");
+ obj = new AppOomAdj(Integer.parseInt(arrs[0]), arrs[1]);
+ mVec.add(obj);
+ }
+
+ br.close();
+ fr.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
/** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
@GuardedBy("mService")
private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
@@ -2155,6 +2201,19 @@
}
int changes = 0;
+ //Slog.d(TAG, "applyOomAdjLocked pkg: " + app.processName+",pid:"+ app.pid+",uid:"+ app.uid +",curAdj:"+app.curAdj+",setAdj:"+app.setAdj);
+ if (mVec != null) {
+ int i = 0;
+ int oom_score_adj = 0;
+ for (;i < mVec.size(); i++) {
+ if (app.processName.equals(mVec.get(i).m_sAppName)) {
+ //new curAdj point to {oom_score_adj}
+ oom_score_adj = mVec.get(i).m_nOomAdj;
+ app.curAdj = oom_score_adj;
+ //Slog.d(TAG, "applyOomAdjLocked pkg:"+app.processName+" mVec app.curAdj:"+app.curAdj);
+ }
+ }
+ }
// don't compact during bootup
if (mCachedAppOptimizer.useCompaction() && mService.mBooted) {