From b70465895113f68ab3f886a2772ef931905462c0 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Wed, 20 Apr 2016 14:33:51 -0700 Subject: [PATCH] Frameworks/base: Make debug helper lazy in ConnectivityManager Place helper map for callback field names into a holder. This avoids the reflective calls in static initialization of ConnectivityManager in the common (non-debug) case, which means the class can be compile-time initialized. Also saves the storage necessary (both the storage array as well as the reflection metadata). Follow-up to b027e6e92b2003c063de1127cd60acf7c303006e. Bug: 27265238 Change-Id: Ib4bfaf27acd234a035a5d198458340099a156a4c --- .../java/android/net/ConnectivityManager.java | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 9070ad9d03..faf5c64e5a 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -81,13 +81,6 @@ import java.util.concurrent.atomic.AtomicInteger; public class ConnectivityManager { private static final String TAG = "ConnectivityManager"; - private static final SparseArray sMagicDecoderRing = MessageUtils.findMessageNames( - new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"}); - - private static final String whatToString(int what) { - return sMagicDecoderRing.get(what, Integer.toString(what)); - } - /** * A change in network connectivity has occurred. A default connection has either * been established or lost. The NetworkInfo for the affected network is @@ -3360,4 +3353,32 @@ public class ConnectivityManager { throw e.rethrowFromSystemServer(); } } + + /** + * A holder class for debug info (mapping CALLBACK values to field names). This is stored + * in a holder for two reasons: + * 1) The reflection necessary to establish the map can't be run at compile-time. Thus, this + * code will make the enclosing class not compile-time initializeable, deferring its + * initialization to zygote startup. This leads to dirty (but shared) memory. + * As this is debug info, use a holder that isn't initialized by default. This way the map + * will be created on demand, while ConnectivityManager can be compile-time initialized. + * 2) Static initialization is still preferred for its strong thread safety guarantees without + * requiring a lock. + */ + private static class NoPreloadHolder { + public static final SparseArray sMagicDecoderRing = MessageUtils.findMessageNames( + new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"}); + } + + static { + // When debug is enabled, aggressively initialize the holder by touching the field (which + // will guarantee static initialization). + if (CallbackHandler.DBG) { + Object dummy = NoPreloadHolder.sMagicDecoderRing; + } + } + + private static final String whatToString(int what) { + return NoPreloadHolder.sMagicDecoderRing.get(what, Integer.toString(what)); + } }