Android增加系统白名单,防止重要应用低内存时被误杀

前言

   在前面的篇章Lowmemkill问题分析我们详细介绍了系统在低内存的时候杀应用的原因。也许有些读者会说现在手机动辄6G+128G的存储了,还会存在低内存杀应用的可能?那么这个就是饱汉不知饿汉饥的苦了,在一些特殊行业譬如工控或者pos行业,依然存在着512M+8G的配置,你说这种配置会不会存在系统内存紧张然后干掉一些系统认为不重要但是其实非常重要的应用或者服务。遇到这种情况,应用开发者的应对方法无外乎如下两种:
(1).普通玩家:这里指的普通玩家就是一般的开发者,可以通过将服务设置为前台服务,或者通过双服务心跳机制来防止杀死,这类方法比较多,大概率就是和系统斗智斗勇增加存活几率,当然这其中也存在一些流氓手段,就不一一举例了。

(2).高阶玩家:这里的高阶玩家一般就指那些大厂的开发应用了,譬如腾讯的微信,QQ啊,这种一般设备终端厂商会将这些特殊的应用放进系统白名单,防止系统被杀。这个很容易理解吗,这种玩家一般给点赞助费啥的给终端厂商,终端厂商也乐于此吗。不然如果出现这种国民级别的应用不能在自己终端上面愉快的玩耍,你说大众是认为应用不行还是终端有问题呢。



一.Android增加白名单防止重要应用低内存时被误杀

由于后续有读者询问,在Android 9以及以上版本的修改方法,这里我重新今天就加一下高版本的方法!

1.1 Android 7以及之前版本

   前面说了那么多,对于系统Rom开发者来说也需要这么一个白名单,防止重要应用被杀,那么这里我介绍一种方法通过动态控制adj的值来做到。具体修改如下:

+++ b/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18056,6 +18056,24 @@ public final class ActivityManagerService extends ActivityManagerNative
         }
     }
 
+    //特权应用,防止被lowmemkill掉 
+    final List<String> mUmsPrivilegedApplication = new ArrayList<String>(){{
+        add("com.xxx.xxx.updater");//
+        add("com.xxx.xxx.xxx.daemon");//
+        add("com.xxx.xxx.mastercontrol");//
+        add("com.xxx.xxx.uapi");//
+    }};  
+    
+    //List是有序的
+    final List<Integer>mUmsPrivilegedApplicationAdj = new ArrayList<Integer>(){
+        {
+          add(ProcessList.PREVIOUS_APP_ADJ); 
+          add(ProcessList.PREVIOUS_APP_ADJ); 
+          add(ProcessList.PREVIOUS_APP_ADJ); 
+          add(ProcessList.PREVIOUS_APP_ADJ); 
+        }
+    };
+
     private final boolean applyOomAdjLocked(ProcessRecord app,
             ProcessRecord TOP_APP, boolean doingAll, long now) {
         boolean success = true;
@@ -18067,11 +18085,37 @@ public final class ActivityManagerService extends ActivityManagerNative
         int changes = 0;
 
         if (app.curAdj != app.setAdj) {
-            ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
-            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
-                TAG, "Set " + app.pid + " " + app.processName +
-                " adj " + app.curAdj + ": " + app.adjType);
-            app.setAdj = app.curAdj;
+           boolean isUmsAppWhiteProcess = false;
+           int mThirdPartyAdj = ProcessList.CACHED_APP_MIN_ADJ;
+           //xxx 2018.12.17 add
+           if(mUmsPrivilegedApplication.size() == mUmsPrivilegedApplicationAdj.size()){
+               for(int i = 0; i < mUmsPrivilegedApplication.size(); i++){
+                   if((mUmsPrivilegedApplication.get(i).equals(app.processName)) && (app.curAdj > mUmsPrivilegedApplicationAdj.get(i)))
+                    {
+                          isUmsAppWhiteProcess = true;
+                          mThirdPartyAdj = mUmsPrivilegedApplicationAdj.get(i);
+                          break;
+                    }
+               }
+           }
+           if(isUmsAppWhiteProcess){
+               ProcessList.setOomAdj(app.pid, app.info.uid, mThirdPartyAdj);
+               if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
+                   TAG, "Set " + app.pid + " " + app.processName +
+                   " adj " + mThirdPartyAdj + ": " + app.adjType);
+               app.setAdj = mThirdPartyAdj;
+           }else{
+               ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
+               if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
+                   TAG, "Set " + app.pid + " " + app.processName +
+                   " adj " + app.curAdj + ": " + app.adjType);
+               app.setAdj = app.curAdj;
+           }
         }

通过上面的修改,可以做到动态调整adj的值,防止误杀重要的应用或者系统级别的服务。


1.2 Android 9以及之后版本

这里没有啥可多说的了,其原理就是调整应用的adj值,防止被lmkd杀掉!这里我们直接上我修改好的提交,如下:

diff --git a/frameworks/base/core/res/res/values/config.xml b/frameworks/base/core/res/res/values/config.xml
index aa56aa2bf9..403dcf04b4 100644
--- a/frameworks/base/core/res/res/values/config.xml
+++ b/frameworks/base/core/res/res/values/config.xml
@@ -4383,4 +4383,11 @@
     <bool name="config_pdp_reject_enable_retry">false</bool>
     <!-- pdp data reject retry delay in ms -->
     <integer name="config_pdp_reject_retry_delay_ms">-1</integer>
+    <string-array translatable="false" name="low_memory_killer_tracker_whitelist" >
+    <item>"com.xxx.xxxdroid.tester"</item>
+    <item>"com.xxx.xxxdroid.tester.service"</item>
+    <item>"com.xxx.xxxdroid.uiautomatorservice"</item>
+    <item>"com.xxx.ft"</item>
+    <item>"com.xxx.xxx"</item>
+    </string-array>
 </resources>
diff --git a/frameworks/base/core/res/res/values/symbols.xml b/frameworks/base/core/res/res/values/symbols.xml
index 32c29cc7b2..d296b12b95 100644
--- a/frameworks/base/core/res/res/values/symbols.xml
+++ b/frameworks/base/core/res/res/values/symbols.xml
@@ -4074,4 +4074,5 @@
   <java-symbol type="string" name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" />
 
   <java-symbol type="array" name="config_notificationMsgPkgsAllowedAsConvos" />
+  <java-symbol type="array" name="low_memory_killer_tracker_whitelist" />
 </resources>
diff --git a/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java b/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
index a7ee0cf300..689b22b9ed 100644
--- a/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
@@ -109,7 +109,8 @@ import java.io.PrintWriter;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
-
+import java.util.List;
+import android.content.res.Resources;
 /**
  * All of the code required to compute proc states and oom_adj values.
  */
@@ -234,7 +235,7 @@ public final class OomAdjuster {
     private ArrayDeque<ProcessRecord> mTmpQueue;
 
     private final IPlatformCompat mPlatformCompat;
-
+	private List<String> mLmKillerBypassPackages = new ArrayList<String>();
     OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
         this(service, processList, activeUids, createAdjusterThread());
     }
@@ -299,8 +300,22 @@ public final class OomAdjuster {
                 / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
         IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
         mPlatformCompat = IPlatformCompat.Stub.asInterface(b);
+		String[] lmKillerTrackerWhitelist = Resources.getSystem().getStringArray(
+                com.android.internal.R.array.low_memory_killer_tracker_whitelist);
+        mLmKillerBypassPackages = Arrays.asList(lmKillerTrackerWhitelist);
+
     }
 
+    private boolean isInWhitelist(ProcessRecord pr) {
+        String pkgName = pr.info.packageName;
+    
+        for (String token : mLmKillerBypassPackages) { 
+            if (pkgName.startsWith(token)) {
+                return true; 
+            }
+        }
+        return false;
+    }
     void initSettings() {
         mCachedAppOptimizer.init();
     }
@@ -2269,14 +2284,29 @@ public final class OomAdjuster {
                     }
                 }
             }
-            ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
-            if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
-                String msg = "Set " + app.pid + " " + app.processName + " adj "
-                        + app.curAdj + ": " + app.adjType;
-                reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
-            }
-            app.setAdj = app.curAdj;
-            app.verifiedAdj = ProcessList.INVALID_ADJ;
+			boolean isAppWhiteProcess = false;
+			if( isInWhitelist(app) && (app.curAdj > ProcessList.PERSISTENT_SERVICE_ADJ))
+				isAppWhiteProcess = true;
+			if(isAppWhiteProcess){
+                Slog.d(TAG,"isAppWhiteProcess so not kill!");
+                ProcessList.setOomAdj(app.pid, app.uid, ProcessList.PERSISTENT_SERVICE_ADJ);
+                if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
+                    String msg = "Set " + app.pid + " " + app.processName + " adj "
+                            + app.curAdj + ": " + app.adjType;
+                    reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
+                }    
+                app.setAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
+                app.verifiedAdj = ProcessList.INVALID_ADJ;
+			}else{
+                ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
+                if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
+                    String msg = "Set " + app.pid + " " + app.processName + " adj "
+                            + app.curAdj + ": " + app.adjType;
+                    reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
+                }
+                app.setAdj = app.curAdj;
+                app.verifiedAdj = ProcessList.INVALID_ADJ;
+			}
         }
 
         final int curSchedGroup = app.getCurrentSchedulingGroup();


总结

   如上是一种比较通用的白名单的做法,方法可能有许多但是最终的目的就是动态调整adj的值防止系统在低内存的时候误将一些重要的应用kill了。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐