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

Commit 1e7f69b0 authored by spooja's avatar spooja Committed by Gerrit Code Review
Browse files

frameworks/base: Fix ContentService JNI leaks

- A list of ObserverCall(s) is created by ContentService as
  it notifies changes to the registered content observers.
  Clear observer after use.

- If same Observer and same URI are registered, the callback
  functions are called multiple times when data identified by
  a given content URI changes. It makes system slow and it
  cause ANR sometimes. And when run
  unregisterContentObserver(), just one deleted but others
  are remained in mObservers. So add prevent code to avoid
  to duplicated registration of Observers

CRs-Fixed: 868634

Change-Id: I5906f581f4beaed04af09e5b9e3999f67d94f1fc
(cherry picked from commit 48eda689)
Ticket: CYNGNOS-751
parent d6835771
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

/**
@@ -187,8 +188,6 @@ public final class ContentService extends IContentService.Stub {
        synchronized (mRootNode) {
            mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
                    Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
            if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
                    " with notifyForDescendants " + notifyForDescendants);
        }
    }

@@ -245,8 +244,9 @@ public final class ContentService extends IContentService.Stub {
        // This makes it so that future permission checks will be in the context of this
        // process rather than the caller's process. We will restore this before returning.
        long identityToken = clearCallingIdentity();
        ArrayList<ObserverCall> calls = null;
        try {
            ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
            calls = new ArrayList<ObserverCall>();
            synchronized (mRootNode) {
                mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
                        userHandle, calls);
@@ -285,6 +285,9 @@ public final class ContentService extends IContentService.Stub {
                }
            }
        } finally {
            if (calls != null) {
                calls.clear();
            }
            restoreCallingIdentity(identityToken);
        }
    }
@@ -1014,8 +1017,18 @@ public final class ContentService extends IContentService.Stub {
                int uid, int pid, int userHandle) {
            // If this is the leaf node add the observer
            if (index == countUriSegments(uri)) {
                Iterator<ObserverEntry> iter = mObservers.iterator();
                while(iter.hasNext()) {
                    ObserverEntry next = iter.next();
                    if(next.observer.asBinder() == observer.asBinder()) {
                        Log.w(TAG, "Observer " + observer + " is already registered.");
                         return;
                    }
                }
                mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
                        uid, pid, userHandle));
                if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
                        " with notifyForDescendants " + notifyForDescendants);
                return;
            }