From d28118879c0a564b035eb7a7ac5f96d7c74737ad Mon Sep 17 00:00:00 2001 From: Jared Duke Date: Mon, 28 Oct 2024 21:50:32 +0000 Subject: Introduce a LazyJniRegistrar helper class for system server Currently, system server registers all JNI native method entrypoints eagerly in SystemServer init. This has generally been fine, but doesn't allow for any flexibility in the existence of Java classes defining these entrypoints; it's assumed that all such entrypoints always exist. The LazyJniRegistrar class allows lazy registration of JNI methods for classes or services, shifting registration responsibilty to the Java classes that use these entrypoints. This in turn allows optional classes or services to be stripped from the build. Start by migrating only a small subset of classes that may be considered optional in the near future. Eventually, we might consider migrating more classes to further streamline init and avoid cascading initialization overhead. Bug: 375264322 Test: m + presubmit Flag: EXEMPT refactor Change-Id: Ia2a0f52575cd47b0f418bb0439ab3a02d413b6ae --- .../java/com/android/server/ConsumerIrService.java | 6 +++ .../com/android/server/utils/LazyJniRegistrar.java | 47 +++++++++++++++++++ services/core/java/com/android/server/utils/OWNERS | 1 + .../com/android/server/vr/VrManagerService.java | 5 +++ services/core/jni/Android.bp | 1 + services/core/jni/OWNERS | 1 + .../com_android_server_utils_LazyJniRegistrar.cpp | 52 ++++++++++++++++++++++ services/core/jni/onload.cpp | 9 ++-- 8 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 services/core/java/com/android/server/utils/LazyJniRegistrar.java create mode 100644 services/core/jni/com_android_server_utils_LazyJniRegistrar.cpp diff --git a/services/core/java/com/android/server/ConsumerIrService.java b/services/core/java/com/android/server/ConsumerIrService.java index ee6d808aa549..8362079b9009 100644 --- a/services/core/java/com/android/server/ConsumerIrService.java +++ b/services/core/java/com/android/server/ConsumerIrService.java @@ -30,6 +30,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; +import com.android.server.utils.LazyJniRegistrar; + public class ConsumerIrService extends IConsumerIrService.Stub { private static final String TAG = "ConsumerIrService"; @@ -39,6 +41,10 @@ public class ConsumerIrService extends IConsumerIrService.Stub { private static native int halTransmit(int carrierFrequency, int[] pattern); private static native int[] halGetCarrierFrequencies(); + static { + LazyJniRegistrar.registerConsumerIrService(); + } + private final Context mContext; private final PowerManager.WakeLock mWakeLock; private final boolean mHasNativeHal; diff --git a/services/core/java/com/android/server/utils/LazyJniRegistrar.java b/services/core/java/com/android/server/utils/LazyJniRegistrar.java new file mode 100644 index 000000000000..ac4a92e12909 --- /dev/null +++ b/services/core/java/com/android/server/utils/LazyJniRegistrar.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 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.utils; + +import com.android.tools.r8.keepanno.annotations.KeepItemKind; +import com.android.tools.r8.keepanno.annotations.MethodAccessFlags; +import com.android.tools.r8.keepanno.annotations.UsedByNative; + +/** + * Utility class for lazily registering native methods for a given class. + * + *

Note: Most native methods are registered eagerly via the + * native {@code JNI_OnLoad} hook when system server loads its primary native + * lib. However, some classes within system server may be stripped if unused. + * This class offers a way to selectively register their native methods. Such + * register calls should typically be done from that class's {@code static {}} + * init block. + */ +@UsedByNative( + description = "Referenced from JNI in jni/com_android_server_utils_LazyJniRegistrar.cpp", + kind = KeepItemKind.CLASS_AND_MEMBERS, + methodAccess = {MethodAccessFlags.NATIVE}) +public final class LazyJniRegistrar { + + // Note: {@link SystemServer#run} loads the native "android_servers" lib, so no need to do so + // explicitly here. Classes that use this registration must not be initialized before this. + + /** Registers native methods for ConsumerIrService. */ + public static native void registerConsumerIrService(); + + /** Registers native methods for VrManagerService. */ + public static native void registerVrManagerService(); +} diff --git a/services/core/java/com/android/server/utils/OWNERS b/services/core/java/com/android/server/utils/OWNERS index fbc0b56c2eb7..9f1cc8196736 100644 --- a/services/core/java/com/android/server/utils/OWNERS +++ b/services/core/java/com/android/server/utils/OWNERS @@ -10,6 +10,7 @@ per-file Watcher.java = file:/services/core/java/com/android/server/pm/OWNERS per-file Watcher.java = shombert@google.com per-file EventLogger.java = file:/platform/frameworks/av:/media/janitors/media_solutions_OWNERS per-file EventLogger.java = jmtrivi@google.com +per-file LazyJniRegistrar.java = file:/PERFORMANCE_OWNERS # Bug component : 158088 = per-file AnrTimer*.java per-file AnrTimer*.java = file:/PERFORMANCE_OWNERS diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index 1ff01a6c70bf..9cfe3bab6e0b 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -67,6 +67,7 @@ import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.SystemService; +import com.android.server.utils.LazyJniRegistrar; import com.android.server.utils.ManagedApplicationService; import com.android.server.utils.ManagedApplicationService.BinderChecker; import com.android.server.utils.ManagedApplicationService.LogEvent; @@ -131,6 +132,10 @@ public class VrManagerService extends SystemService private static native void initializeNative(); private static native void setVrModeNative(boolean enabled); + static { + LazyJniRegistrar.registerVrManagerService(); + } + private final Object mLock = new Object(); private final IBinder mOverlayToken = new Binder(); diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 7a710dc51004..ab987ad0e957 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -76,6 +76,7 @@ cc_library_static { "com_android_server_am_LowMemDetector.cpp", "com_android_server_pm_PackageManagerShellCommandDataLoader.cpp", "com_android_server_sensor_SensorService.cpp", + "com_android_server_utils_LazyJniRegistrar.cpp", "com_android_server_wm_TaskFpsCallbackController.cpp", "onload.cpp", ":lib_cachedAppOptimizer_native", diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS index b622751fc3e8..8052b092a1e1 100644 --- a/services/core/jni/OWNERS +++ b/services/core/jni/OWNERS @@ -30,6 +30,7 @@ per-file com_android_server_vibrator_* = file:/services/core/java/com/android/se per-file com_android_server_am_CachedAppOptimizer.cpp = file:/PERFORMANCE_OWNERS per-file com_android_server_am_Freezer.cpp = file:/PERFORMANCE_OWNERS per-file com_android_server_companion_virtual_InputController.cpp = file:/services/companion/java/com/android/server/companion/virtual/OWNERS +per-file com_android_server_utils_LazyJniRegistrar.cpp = file:/PERFORMANCE_OWNERS # Memory per-file com_android_server_am_OomConnection.cpp = file:/MEMORY_OWNERS diff --git a/services/core/jni/com_android_server_utils_LazyJniRegistrar.cpp b/services/core/jni/com_android_server_utils_LazyJniRegistrar.cpp new file mode 100644 index 000000000000..ad7781e3b8b5 --- /dev/null +++ b/services/core/jni/com_android_server_utils_LazyJniRegistrar.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 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. + */ + +#include + +#include "jni.h" + +namespace android { + +// Forward declared per-class registration methods. +int register_android_server_ConsumerIrService(JNIEnv* env); +int register_android_server_vr_VrManagerService(JNIEnv* env); + +namespace { + +// TODO(b/)375264322: Remove these trampoline methods after finalizing the +// registrar implementation. Instead, just update the called methods to take a +// class arg, and hand those methods to jniRegisterNativeMethods directly. +void registerConsumerIrService(JNIEnv* env, jclass) { + register_android_server_ConsumerIrService(env); +} + +void registerVrManagerService(JNIEnv* env, jclass) { + register_android_server_vr_VrManagerService(env); +} + +static const JNINativeMethod sJniRegistrarMethods[] = { + {"registerConsumerIrService", "()V", (void*)registerConsumerIrService}, + {"registerVrManagerService", "()V", (void*)registerVrManagerService}, +}; + +} // namespace + +int register_android_server_utils_LazyJniRegistrar(JNIEnv* env) { + return jniRegisterNativeMethods(env, "com/android/server/utils/LazyJniRegistrar", + sJniRegistrarMethods, NELEM(sJniRegistrarMethods)); +} + +} // namespace android diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 6464081d615a..6329b8c86a4d 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -25,7 +25,6 @@ namespace android { int register_android_server_BatteryStatsService(JNIEnv* env); -int register_android_server_ConsumerIrService(JNIEnv *env); int register_android_server_InputManager(JNIEnv* env); int register_android_server_LightsService(JNIEnv* env); int register_android_server_PowerManagerService(JNIEnv* env); @@ -39,7 +38,6 @@ int register_android_server_UsbAlsaJackDetector(JNIEnv* env); int register_android_server_UsbAlsaMidiDevice(JNIEnv* env); int register_android_server_UsbDeviceManager(JNIEnv* env); int register_android_server_UsbHostManager(JNIEnv* env); -int register_android_server_vr_VrManagerService(JNIEnv* env); int register_android_server_vibrator_VibratorController(JavaVM* vm, JNIEnv* env); int register_android_server_vibrator_VibratorManagerService(JavaVM* vm, JNIEnv* env); int register_android_server_location_GnssLocationProvider(JNIEnv* env); @@ -56,6 +54,7 @@ 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_android_server_utils_AnrTimer(JNIEnv *env); +int register_android_server_utils_LazyJniRegistrar(JNIEnv* env); int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(JNIEnv* env); int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(JNIEnv* env); int register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env); @@ -72,6 +71,9 @@ int register_com_android_server_display_DisplayControl(JNIEnv* env); int register_com_android_server_SystemClockTime(JNIEnv* env); int register_android_server_display_smallAreaDetectionController(JNIEnv* env); int register_com_android_server_accessibility_BrailleDisplayConnection(JNIEnv* env); + +// Note: Consider adding new JNI entrypoints for optional services to +// LazyJniRegistrar instead, and relying on lazy registration. }; using namespace android; @@ -100,14 +102,12 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_UsbAlsaJackDetector(env); register_android_server_UsbAlsaMidiDevice(env); register_android_server_UsbHostManager(env); - register_android_server_vr_VrManagerService(env); register_android_server_vibrator_VibratorController(vm, env); register_android_server_vibrator_VibratorManagerService(vm, env); register_android_server_SystemServer(env); register_android_server_location_GnssLocationProvider(env); register_android_server_connectivity_Vpn(env); register_android_server_devicepolicy_CryptoTestHelper(env); - register_android_server_ConsumerIrService(env); register_android_server_BatteryStatsService(env); register_android_server_tv_TvUinputBridge(env); register_android_server_tv_TvInputHal(env); @@ -120,6 +120,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_am_CachedAppOptimizer(env); register_android_server_am_LowMemDetector(env); register_android_server_utils_AnrTimer(env); + register_android_server_utils_LazyJniRegistrar(env); register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(env); register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(env); register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env); -- cgit v1.2.3-59-g8ed1b