From cf9597791edc284b179f3aeaa64e9d53b5abbf36 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 29 Feb 2016 16:07:37 +0900 Subject: [PATCH] Don't pass calling contexts into static services. When initializing a service, StaticOuterContextServiceFetcher passes the calling context to it. This causes a leak if the service stores the context in a static variable. Instead, pass in the application context, which will never be freed for the life of the application, and correspondingly rename StaticOuterContextServiceFetcher to StaticApplicationContextServiceFetcher. Bug: 27147995 Change-Id: Ic67ebc32df7368184c2935f0327491fdc7d69836 --- core/java/android/app/SystemServiceRegistry.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 307c3eb18362f..b1c5fd8c69637 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -226,7 +226,7 @@ final class SystemServiceRegistry { SYSTEM_SERVICE_NAMES.put(android.text.ClipboardManager.class, Context.CLIPBOARD_SERVICE); registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class, - new StaticOuterContextServiceFetcher() { + new StaticApplicationContextServiceFetcher() { @Override public ConnectivityManager createService(Context context) { IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); @@ -840,22 +840,21 @@ final class SystemServiceRegistry { } /** - * Like StaticServiceFetcher, creates only one instance of the service per process, but when - * creating the service for the first time, passes it the outer context of the creating - * component. + * Like StaticServiceFetcher, creates only one instance of the service per application, but when + * creating the service for the first time, passes it the application context of the creating + * application. * - * TODO: Is this safe in the case where multiple applications share the same process? * TODO: Delete this once its only user (ConnectivityManager) is known to work well in the * case where multiple application components each have their own ConnectivityManager object. */ - static abstract class StaticOuterContextServiceFetcher implements ServiceFetcher { + static abstract class StaticApplicationContextServiceFetcher implements ServiceFetcher { private T mCachedInstance; @Override public final T getService(ContextImpl ctx) { - synchronized (StaticOuterContextServiceFetcher.this) { + synchronized (StaticApplicationContextServiceFetcher.this) { if (mCachedInstance == null) { - mCachedInstance = createService(ctx.getOuterContext()); + mCachedInstance = createService(ctx.getApplicationContext()); } return mCachedInstance; }