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 guardparseCustomsizedAppOomAdj("/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() {@Overridepublic 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 bootupif (mCachedAppOptimizer.useCompaction() && mService.mBooted) {// Cached and prev/home compactionif (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 stateif (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-19626Problem:
need support configure the process priority.Solution:
Support for configuring process priority.Verify:
S928XChange-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 bootupif (mCachedAppOptimizer.useCompaction() && mService.mBooted) {