diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java index 7b3d017128670b7942f472067b9cdb8a5b471968..d15c79f41d3f08c13c237f47f711f76353126299 100644 --- a/core/java/android/app/ApplicationExitInfo.java +++ b/core/java/android/app/ApplicationExitInfo.java @@ -468,6 +468,15 @@ public final class ApplicationExitInfo implements Parcelable { */ public static final int SUBREASON_EXCESSIVE_BINDER_OBJECTS = 29; + /** + * The process was killed by the [kernel] Out-of-memory (OOM) killer; this + * would be set only when the reason is {@link #REASON_LOW_MEMORY}. + * + * For internal use only. + * @hide + */ + public static final int SUBREASON_OOM_KILL = 30; + // If there is any OEM code which involves additional app kill reasons, it should // be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000. @@ -644,6 +653,7 @@ public final class ApplicationExitInfo implements Parcelable { SUBREASON_PACKAGE_UPDATE, SUBREASON_UNDELIVERED_BROADCAST, SUBREASON_EXCESSIVE_BINDER_OBJECTS, + SUBREASON_OOM_KILL, }) @Retention(RetentionPolicy.SOURCE) public @interface SubReason {} @@ -1371,6 +1381,8 @@ public final class ApplicationExitInfo implements Parcelable { return "UNDELIVERED BROADCAST"; case SUBREASON_EXCESSIVE_BINDER_OBJECTS: return "EXCESSIVE BINDER OBJECTS"; + case SUBREASON_OOM_KILL: + return "OOM KILL"; default: return "UNKNOWN"; } diff --git a/core/java/android/os/OomKillRecord.java b/core/java/android/os/OomKillRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..151a65fdfaf54d3bcc63bac846d8c0964b0afff5 --- /dev/null +++ b/core/java/android/os/OomKillRecord.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 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 android.os; + + +/** + * Expected data to get back from the OOM event's file. + * Note that this should be equivalent to the struct <b>OomKill</b> inside + * <pre> + * system/memory/libmeminfo/libmemevents/include/memevents.h + * </pre> + * + * @hide + */ +public final class OomKillRecord { + private long mTimeStampInMillis; + private int mPid; + private int mUid; + private String mProcessName; + private short mOomScoreAdj; + + public OomKillRecord(long timeStampInMillis, int pid, int uid, + String processName, short oomScoreAdj) { + this.mTimeStampInMillis = timeStampInMillis; + this.mPid = pid; + this.mUid = uid; + this.mProcessName = processName; + this.mOomScoreAdj = oomScoreAdj; + } + + public long getTimestampMilli() { + return mTimeStampInMillis; + } + + public int getPid() { + return mPid; + } + + public int getUid() { + return mUid; + } + + public String getProcessName() { + return mProcessName; + } + + public short getOomScoreAdj() { + return mOomScoreAdj; + } +} diff --git a/services/core/java/com/android/server/am/OomConnection.java b/services/core/java/com/android/server/am/OomConnection.java new file mode 100644 index 0000000000000000000000000000000000000000..17a4ce5b921cde2201ba371ef04a51b6cf88580c --- /dev/null +++ b/services/core/java/com/android/server/am/OomConnection.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 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 android.os.OomKillRecord; +import android.util.Slog; + +/** Connection to the out-of-memory (OOM) events' file */ +public final class OomConnection { + private static final String TAG = "OomConnection"; + + /** Connection listener interface */ + public interface OomConnectionListener { + + /** + * Callback function to handle the newest OOM kills. + * + * @param oomKills List of oom kills received from `waitOom()` + */ + void handleOomEvent(OomKillRecord[] oomKills); + } + + private final OomConnectionListener mOomListener; + + private final OomConnectionThread mOomConnectionThread; + + private static native OomKillRecord[] waitOom(); + + public OomConnection(OomConnectionListener listener) { + mOomListener = listener; + mOomConnectionThread = new OomConnectionThread(); + mOomConnectionThread.start(); + } + + private final class OomConnectionThread extends Thread { + public void run() { + while (true) { + OomKillRecord[] oom_kills = null; + try { + oom_kills = waitOom(); + mOomListener.handleOomEvent(oom_kills); + } catch (RuntimeException e) { + Slog.e(TAG, "failed waiting for OOM events: " + e); + break; + } + } + } + } +} diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index a97675f1d77609d760b27780b695a36c5b0f9ea1..4572766371ec0e78444afaaa1fe74c616d174404 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -97,6 +97,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.OomKillRecord; import android.os.PowerManager; import android.os.Process; import android.os.RemoteCallbackList; @@ -412,6 +413,8 @@ public final class ProcessList { private static LmkdConnection sLmkdConnection = null; + private static OomConnection sOomConnection = null; + private boolean mOomLevelsSet = false; private boolean mAppDataIsolationEnabled = false; @@ -855,6 +858,21 @@ public final class ProcessList { THREAD_PRIORITY_BACKGROUND, true /* allowIo */); sKillThread.start(); sKillHandler = new KillHandler(sKillThread.getLooper()); + sOomConnection = new OomConnection(new OomConnection.OomConnectionListener() { + @Override + public void handleOomEvent(OomKillRecord[] oomKills) { + for (OomKillRecord oomKill: oomKills) { + synchronized (mProcLock) { + noteAppKill( + oomKill.getPid(), + oomKill.getUid(), + ApplicationExitInfo.REASON_LOW_MEMORY, + ApplicationExitInfo.SUBREASON_OOM_KILL, + "oom"); + } + } + } + }); sLmkdConnection = new LmkdConnection(sKillThread.getLooper().getQueue(), new LmkdConnection.LmkdConnectionListener() { @Override diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index ec5378f01ce3b3852077714cc277440ee94d8279..bc70658a06c4730644ebd030bd87d75dc7044a45 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -78,6 +78,7 @@ cc_library_static { "onload.cpp", ":lib_cachedAppOptimizer_native", ":lib_gameManagerService_native", + ":lib_oomConnection_native", ], include_dirs: [ @@ -122,6 +123,7 @@ cc_defaults { "libhardware_legacy", "libhidlbase", "libmeminfo", + "libmemevents", "libmemtrackproxy", "libmtp", "libnativehelper", @@ -239,3 +241,8 @@ filegroup { "com_android_server_app_GameManagerService.cpp", ], } + +filegroup { + name: "lib_oomConnection_native", + srcs: ["com_android_server_am_OomConnection.cpp",], +} diff --git a/services/core/jni/com_android_server_am_OomConnection.cpp b/services/core/jni/com_android_server_am_OomConnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e892d23460c90c1c5b4fd8d8fd8b1f7939115d24 --- /dev/null +++ b/services/core/jni/com_android_server_am_OomConnection.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2023 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 "OomConnection" + +#include <core_jni_helpers.h> +#include <jni.h> +#include <memevents/memevents.h> + +namespace android { + +// Used to cache the results of the JNI name lookup +static struct { + jclass clazz; + jmethodID ctor; +} sOomKillRecordInfo; + +static memevents::MemEventListener memevent_listener; + +/** + * Initialize listening and waiting for new out-of-memory (OOM) events to occur. + * Once a OOM event is detected, we then fetch the list of OOM kills, and return + * a corresponding java array with the information gathered. + * + * In the case that we encounter an error, we make sure to close the epfd, and + * the OOM file descriptor, by calling `deregisterAllEvents()`. + * + * @return list of `android.os.OomKillRecord` + * @throws java.lang.RuntimeException + */ +static jobjectArray android_server_am_OomConnection_waitOom(JNIEnv* env, jobject) { + const memevents::MemEvent oom_event = memevents::MemEvent::OOM_KILL; + if (!memevent_listener.registerEvent(oom_event)) { + memevent_listener.deregisterAllEvents(); + jniThrowRuntimeException(env, "listener failed to register to OOM events"); + return nullptr; + } + + memevents::MemEvent event_received; + do { + event_received = memevent_listener.listen(); + if (event_received == memevents::MemEvent::ERROR) { + memevent_listener.deregisterAllEvents(); + jniThrowRuntimeException(env, "listener received error event"); + return nullptr; + } + } while (event_received != oom_event); + + std::vector<memevents::OomKill> oom_events; + if (!memevent_listener.getOomEvents(oom_events)) { + memevent_listener.deregisterAllEvents(); + jniThrowRuntimeException(env, "Failed to get OOM events"); + return nullptr; + } + + jobjectArray java_oom_array = + env->NewObjectArray(oom_events.size(), sOomKillRecordInfo.clazz, nullptr); + if (java_oom_array == NULL) { + memevent_listener.deregisterAllEvents(); + jniThrowRuntimeException(env, "Failed to create OomKillRecord array"); + return nullptr; + } + + for (int i = 0; i < oom_events.size(); i++) { + const memevents::OomKill oom_event = oom_events[i]; + jstring process_name = env->NewStringUTF(oom_event.process_name); + if (process_name == NULL) { + memevent_listener.deregisterAllEvents(); + jniThrowRuntimeException(env, "Failed creating java string for process name"); + } + jobject java_oom_kill = env->NewObject(sOomKillRecordInfo.clazz, sOomKillRecordInfo.ctor, + oom_event.timestamp_ms, oom_event.pid, oom_event.uid, + process_name, oom_event.oom_score_adj); + if (java_oom_kill == NULL) { + memevent_listener.deregisterAllEvents(); + jniThrowRuntimeException(env, "Failed to create OomKillRecord object"); + return java_oom_array; + } + env->SetObjectArrayElement(java_oom_array, i, java_oom_kill); + } + return java_oom_array; +} + +static const JNINativeMethod sOomConnectionMethods[] = { + /* name, signature, funcPtr */ + {"waitOom", "()[Landroid/os/OomKillRecord;", + (void*)android_server_am_OomConnection_waitOom}, +}; + +int register_android_server_am_OomConnection(JNIEnv* env) { + sOomKillRecordInfo.clazz = FindClassOrDie(env, "android/os/OomKillRecord"); + sOomKillRecordInfo.clazz = MakeGlobalRefOrDie(env, sOomKillRecordInfo.clazz); + + sOomKillRecordInfo.ctor = + GetMethodIDOrDie(env, sOomKillRecordInfo.clazz, "<init>", "(JIILjava/lang/String;S)V"); + + return RegisterMethodsOrDie(env, "com/android/server/am/OomConnection", sOomConnectionMethods, + NELEM(sOomConnectionMethods)); +} +} // namespace android \ No newline at end of file diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index f6f67374660919d628a3da093c948c7143b73fd0..df4489528be57e3537b631790f879815f26f5288 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -52,6 +52,7 @@ int register_android_server_Watchdog(JNIEnv* env); int register_android_server_HardwarePropertiesManagerService(JNIEnv* env); int register_android_server_SyntheticPasswordManager(JNIEnv* env); int register_android_hardware_display_DisplayViewport(JNIEnv* env); +int register_android_server_am_OomConnection(JNIEnv* env); int register_android_server_am_CachedAppOptimizer(JNIEnv* env); int register_android_server_am_LowMemDetector(JNIEnv* env); int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(JNIEnv* env); @@ -112,6 +113,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_storage_AppFuse(env); register_android_server_SyntheticPasswordManager(env); register_android_hardware_display_DisplayViewport(env); + register_android_server_am_OomConnection(env); register_android_server_am_CachedAppOptimizer(env); register_android_server_am_LowMemDetector(env); register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(env); diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp index f1dc1fa1a108df58ae7158c3b28a0fd524ffcdac..1eb9888489cbd14dfb7beb99c08a5a8ca4712950 100644 --- a/services/tests/mockingservicestests/jni/Android.bp +++ b/services/tests/mockingservicestests/jni/Android.bp @@ -22,6 +22,7 @@ cc_library_shared { srcs: [ ":lib_cachedAppOptimizer_native", ":lib_gameManagerService_native", + ":lib_oomConnection_native", "onload.cpp", ], @@ -42,6 +43,7 @@ cc_library_shared { "libgui", "libhidlbase", "liblog", + "libmemevents", "libmeminfo", "libnativehelper", "libprocessgroup", diff --git a/services/tests/mockingservicestests/jni/onload.cpp b/services/tests/mockingservicestests/jni/onload.cpp index 23ccb22321b22443e5430c6b527e8a7f93529ebc..fb910513adda6a9bc69e8dd98e0422bb39e11945 100644 --- a/services/tests/mockingservicestests/jni/onload.cpp +++ b/services/tests/mockingservicestests/jni/onload.cpp @@ -26,6 +26,7 @@ namespace android { int register_android_server_am_CachedAppOptimizer(JNIEnv* env); int register_android_server_app_GameManagerService(JNIEnv* env); +int register_android_server_am_OomConnection(JNIEnv* env); }; using namespace android; @@ -42,6 +43,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) ALOG_ASSERT(env, "Could not retrieve the env!"); register_android_server_am_CachedAppOptimizer(env); register_android_server_app_GameManagerService(env); + register_android_server_am_OomConnection(env); return JNI_VERSION_1_4; } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java index 64cc3979f181f1e43888a664f9dcba3539ef1779..9ba4f5b4fe305116a5615c66450c6cc60aae2732 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java @@ -218,4 +218,9 @@ public class ActivityManagerInternalTest { assertEquals(errMsg, Thread.State.TERMINATED, getState()); } } + + // TODO: [b/302724778] Remove manual JNI load + static { + System.loadLibrary("mockingservicestestjni"); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java index 2bc66ace454b2a6df42a22d4283d6fa0b99834b1..40b5458b06b988a8040b20befdb454406c2e5a88 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java @@ -1210,4 +1210,9 @@ public class ActivityManagerServiceTest { return returnValueForstartUserOnSecondaryDisplay; } } + + // TODO: [b/302724778] Remove manual JNI load + static { + System.loadLibrary("mockingservicestestjni"); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java index 1c0989c4fb65de018d85469f3acee50f72544ffb..9391d5bfeed42950e8ca5e0874eb4d4403c0d87c 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java @@ -338,4 +338,8 @@ public class AppChildProcessTest { } } + // TODO: [b/302724778] Remove manual JNI load + static { + System.loadLibrary("mockingservicestestjni"); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java index d56229c9681f1177967daf63c2ed83184b2dfff3..e15942bb8f9af1e6bc33d75d7d8d583b771c9b5d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java @@ -1126,4 +1126,9 @@ public class ApplicationExitInfoTest { }; } } + + // TODO: [b/302724778] Remove manual JNI load + static { + System.loadLibrary("mockingservicestestjni"); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java index 0abf46b8ee55fc8304872e5d2c505139b602eed5..596a3f3d04007c6f5e23e1e2a9826df3cf512db6 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java @@ -284,4 +284,9 @@ public class AsyncProcessStartTest { return app; } + + // TODO: [b/302724778] Remove manual JNI load + static { + System.loadLibrary("mockingservicestestjni"); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java index 434d200353691e0f7d02dcc0373b03de39ab9ec1..dfb8fda56edfb5f712e8c774cc885d6d16d08187 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java @@ -803,4 +803,9 @@ public class CacheOomRankerTest { return mHandler; } } + + // TODO: [b/302724778] Remove manual JNI load + static { + System.loadLibrary("mockingservicestestjni"); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java index fd1b06830a898d02bff1374aede0ae4604c3c71a..7ec27be0bfc308200c037eb09049a38b42b1515d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java @@ -201,4 +201,9 @@ public final class ServiceTimeoutTest { return mActiveServices; } } + + // TODO: [b/302724778] Remove manual JNI load + static { + System.loadLibrary("mockingservicestestjni"); + } } diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 20d8a5d1efeb0036467513e758d774041c3e65f1..71f7f577d038fda55789f231628eddbb1379c9a7 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -2,6 +2,13 @@ // Build FrameworksServicesTests package //######################################################################## +java_defaults { + name: "FrameworksServicesTests-jni-defaults", + jni_libs: [ + "libservicestestjni", + ], +} + package { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import @@ -13,6 +20,9 @@ package { android_test { name: "FrameworksServicesTests", + defaults: [ + "FrameworksServicesTests-jni-defaults", + ], // Include all test java files. srcs: [ diff --git a/services/tests/servicestests/jni/Android.bp b/services/tests/servicestests/jni/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..174beb81d3ebe896ed2f372dfcb8aadaef12ff82 --- /dev/null +++ b/services/tests/servicestests/jni/Android.bp @@ -0,0 +1,58 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +cc_library_shared { + name: "libservicestestjni", + + defaults: ["android.hardware.graphics.common-ndk_shared"], + + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + "-Wthread-safety", + ], + + srcs: [ + ":lib_cachedAppOptimizer_native", + ":lib_gameManagerService_native", + ":lib_oomConnection_native", + "onload.cpp", + ], + + include_dirs: [ + "frameworks/base/libs", + "frameworks/native/services", + "frameworks/native/libs/math/include", + "frameworks/native/libs/ui/include", + "system/memory/libmeminfo/include", + ], + + shared_libs: [ + "libandroid", + "libandroid_runtime", + "libbase", + "libbinder", + "libgralloctypes", + "libgui", + "libhidlbase", + "liblog", + "libmeminfo", + "libmemevents", + "libnativehelper", + "libprocessgroup", + "libutils", + "libcutils", + "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", + "android.hardware.graphics.common@1.2", + "android.hardware.graphics.mapper@4.0", + "android.hidl.token@1.0-utils", + ], +} \ No newline at end of file diff --git a/services/tests/servicestests/jni/onload.cpp b/services/tests/servicestests/jni/onload.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f160b3d9736735fa016f52307d286e20c62d8389 --- /dev/null +++ b/services/tests/servicestests/jni/onload.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 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. + */ + +/* + * this is a mini native libaray for cached app optimizer tests to run properly. It + * loads all the native methods necessary. + */ +#include <nativehelper/JNIHelp.h> +#include "jni.h" +#include "utils/Log.h" +#include "utils/misc.h" + +namespace android { +int register_android_server_am_CachedAppOptimizer(JNIEnv* env); +int register_android_server_app_GameManagerService(JNIEnv* env); +int register_android_server_am_OomConnection(JNIEnv* env); +}; + +using namespace android; + +extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) +{ + JNIEnv* env = NULL; + jint result = -1; + + if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { + ALOGE("GetEnv failed!"); + return result; + } + ALOG_ASSERT(env, "Could not retrieve the env!"); + register_android_server_am_CachedAppOptimizer(env); + register_android_server_app_GameManagerService(env); + register_android_server_am_OomConnection(env); + return JNI_VERSION_1_4; +} diff --git a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java index acdfee9af5570b26502a6cad097e11187d45a236..c0051c6c9e17f4ce3d6e449df4eb4228200b98d9 100644 --- a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java @@ -172,4 +172,9 @@ public class AnrHelperTest { anyString(), any(), any(), any(), anyBoolean(), any(), eq(mAuxExecutorService), anyBoolean(), anyBoolean(), any()); } + + // TODO: [b/302724778] Remove manual JNI load + static { + System.loadLibrary("servicestestjni"); + } }