From 31faf3f1bd131f63cf127d84ede1d86acdbaaa8d Mon Sep 17 00:00:00 2001 From: Tim Murray Date: Fri, 1 Mar 2019 20:25:07 -0800 Subject: [PATCH] Compact system processes. Compact system processes soon after boot and during idle maintenance. This will help keep the pagecache in a more consistent state. Test: boots, works bug 119988524 Change-Id: I7207d6ba3a2047278b767718dbc532e06f5516fd --- .../server/am/ActivityManagerService.java | 5 ++ .../com/android/server/am/AppCompactor.java | 18 ++++ services/core/jni/Android.bp | 1 + .../com_android_server_am_AppCompactor.cpp | 88 +++++++++++++++++++ services/core/jni/onload.cpp | 2 + 5 files changed, 114 insertions(+) create mode 100644 services/core/jni/com_android_server_am_AppCompactor.cpp diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 97cc756e3924f..a1f2ac630c04e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5121,6 +5121,7 @@ public class ActivityManagerService extends IActivityManager.Stub String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { synchronized (ActivityManagerService.this) { + mOomAdjuster.mAppCompact.compactAllSystem(); requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); } } @@ -8614,6 +8615,10 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { final long now = SystemClock.uptimeMillis(); final long timeSinceLastIdle = now - mLastIdleTime; + + // Compact all non-zygote processes to freshen up the page cache. + mOomAdjuster.mAppCompact.compactAllSystem(); + final long lowRamSinceLastIdle = getLowRamTimeSinceIdle(now); mLastIdleTime = now; mLowRamTimeSinceLastIdle = 0; diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java index c73c808450109..f58fb95b1ec9a 100644 --- a/services/core/java/com/android/server/am/AppCompactor.java +++ b/services/core/java/com/android/server/am/AppCompactor.java @@ -92,6 +92,7 @@ public final class AppCompactor { static final int COMPACT_PROCESS_PERSISTENT = 3; static final int COMPACT_PROCESS_BFGS = 4; static final int COMPACT_PROCESS_MSG = 1; + static final int COMPACT_SYSTEM_MSG = 2; /** * This thread must be moved to the system background cpuset. @@ -264,6 +265,16 @@ public final class AppCompactor { || (now - app.lastCompactTime) > mCompactThrottleBFGS); } + @GuardedBy("mAm") + void compactAllSystem() { + if (mUseCompaction) { + mCompactionHandler.sendMessage(mCompactionHandler.obtainMessage( + COMPACT_SYSTEM_MSG)); + } + } + + private native void compactSystem(); + /** * Reads the flag value from DeviceConfig to determine whether app compaction * should be enabled, and starts/stops the compaction thread as needed. @@ -497,6 +508,13 @@ public final class AppCompactor { // nothing to do, presumably the process died Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } + break; + } + case COMPACT_SYSTEM_MSG: { + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactSystem"); + compactSystem(); + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + break; } } } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 00b815ae1bfa7..a7423ea40bf0d 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -50,6 +50,7 @@ cc_library_static { "com_android_server_VibratorService.cpp", "com_android_server_PersistentDataBlockService.cpp", "com_android_server_GraphicsStatsService.cpp", + "com_android_server_am_AppCompactor.cpp", "onload.cpp", ], diff --git a/services/core/jni/com_android_server_am_AppCompactor.cpp b/services/core/jni/com_android_server_am_AppCompactor.cpp new file mode 100644 index 0000000000000..de6aa8b3266be --- /dev/null +++ b/services/core/jni/com_android_server_am_AppCompactor.cpp @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#define LOG_TAG "AppCompactor" +//#define LOG_NDEBUG 0 + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +using android::base::StringPrintf; +using android::base::WriteStringToFile; + +namespace android { + +// This performs per-process reclaim on all processes belonging to non-app UIDs. +// For the most part, these are non-zygote processes like Treble HALs, but it +// also includes zygote-derived processes that run in system UIDs, like bluetooth +// or potentially some mainline modules. The only process that should definitely +// not be compacted is system_server, since compacting system_server around the +// time of BOOT_COMPLETE could result in perceptible issues. +static void com_android_server_am_AppCompactor_compactSystem(JNIEnv *, jobject) { + std::unique_ptr proc(opendir("/proc"), closedir); + struct dirent* current; + while ((current = readdir(proc.get()))) { + if (current->d_type != DT_DIR) { + continue; + } + + // don't compact system_server, rely on persistent compaction during screen off + // in order to avoid mmap_sem-related stalls + if (atoi(current->d_name) == getpid()) { + continue; + } + + std::string status_name = StringPrintf("/proc/%s/status", current->d_name); + struct stat status_info; + + if (stat(status_name.c_str(), &status_info) != 0) { + // must be some other directory that isn't a pid + continue; + } + + // android.os.Process.FIRST_APPLICATION_UID + if (status_info.st_uid >= 10000) { + continue; + } + + std::string reclaim_path = StringPrintf("/proc/%s/reclaim", current->d_name); + WriteStringToFile(std::string("all"), reclaim_path); + } +} + +static const JNINativeMethod sMethods[] = { + /* name, signature, funcPtr */ + {"compactSystem", "()V", (void*)com_android_server_am_AppCompactor_compactSystem}, +}; + +int register_android_server_am_AppCompactor(JNIEnv* env) +{ + return jniRegisterNativeMethods(env, "com/android/server/am/AppCompactor", + sMethods, NELEM(sMethods)); +} + +} diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 5ffed03c86aee..2cfaebf4632e3 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -54,6 +54,7 @@ int register_android_server_GraphicsStatsService(JNIEnv* env); int register_android_hardware_display_DisplayViewport(JNIEnv* env); int register_android_server_net_NetworkStatsService(JNIEnv* env); int register_android_server_security_VerityUtils(JNIEnv* env); +int register_android_server_am_AppCompactor(JNIEnv* env); }; using namespace android; @@ -101,5 +102,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_hardware_display_DisplayViewport(env); register_android_server_net_NetworkStatsService(env); register_android_server_security_VerityUtils(env); + register_android_server_am_AppCompactor(env); return JNI_VERSION_1_4; }