Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf959779 authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

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
parent 17fc60e1
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -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<ConnectivityManager>() {
                new StaticApplicationContextServiceFetcher<ConnectivityManager>() {
            @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<T> implements ServiceFetcher<T> {
    static abstract class StaticApplicationContextServiceFetcher<T> implements ServiceFetcher<T> {
        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;
            }