Merge "change ObserverNode.binderDied() to lock the root node before manipulating the observers tree by calling removeObserverLocked()"

This commit is contained in:
Fred Quintana
2010-03-02 13:23:17 -08:00
committed by Android (Google) Code Review
2 changed files with 44 additions and 44 deletions

View File

@@ -32,7 +32,6 @@ import android.Manifest;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
@@ -104,7 +103,7 @@ public final class ContentService extends IContentService.Stub {
throw new IllegalArgumentException("You must pass a valid uri and observer");
}
synchronized (mRootNode) {
mRootNode.addObserver(uri, observer, notifyForDescendents);
mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode);
if (Config.LOGV) Log.v(TAG, "Registered observer " + observer + " at " + uri +
" with notifyForDescendents " + notifyForDescendents);
}
@@ -115,7 +114,7 @@ public final class ContentService extends IContentService.Stub {
throw new IllegalArgumentException("You must pass a valid observer");
}
synchronized (mRootNode) {
mRootNode.removeObserver(observer);
mRootNode.removeObserverLocked(observer);
if (Config.LOGV) Log.v(TAG, "Unregistered observer " + observer);
}
}
@@ -132,7 +131,7 @@ public final class ContentService extends IContentService.Stub {
try {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
synchronized (mRootNode) {
mRootNode.collectObservers(uri, 0, observer, observerWantsSelfNotifications,
mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
calls);
}
final int numCalls = calls.size();
@@ -470,10 +469,12 @@ public final class ContentService extends IContentService.Stub {
*/
public static final class ObserverNode {
private class ObserverEntry implements IBinder.DeathRecipient {
public IContentObserver observer;
public boolean notifyForDescendents;
public final IContentObserver observer;
public final boolean notifyForDescendents;
private final Object observersLock;
public ObserverEntry(IContentObserver o, boolean n) {
public ObserverEntry(IContentObserver o, boolean n, Object observersLock) {
this.observersLock = observersLock;
observer = o;
notifyForDescendents = n;
try {
@@ -484,7 +485,9 @@ public final class ContentService extends IContentService.Stub {
}
public void binderDied() {
removeObserver(observer);
synchronized (observersLock) {
removeObserverLocked(observer);
}
}
}
@@ -519,16 +522,16 @@ public final class ContentService extends IContentService.Stub {
return uri.getPathSegments().size() + 1;
}
public void addObserver(Uri uri, IContentObserver observer, boolean notifyForDescendents) {
addObserver(uri, 0, observer, notifyForDescendents);
public void addObserverLocked(Uri uri, IContentObserver observer,
boolean notifyForDescendents, Object observersLock) {
addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock);
}
private void addObserver(Uri uri, int index, IContentObserver observer,
boolean notifyForDescendents) {
private void addObserverLocked(Uri uri, int index, IContentObserver observer,
boolean notifyForDescendents, Object observersLock) {
// If this is the leaf node add the observer
if (index == countUriSegments(uri)) {
mObservers.add(new ObserverEntry(observer, notifyForDescendents));
mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock));
return;
}
@@ -538,7 +541,7 @@ public final class ContentService extends IContentService.Stub {
for (int i = 0; i < N; i++) {
ObserverNode node = mChildren.get(i);
if (node.mName.equals(segment)) {
node.addObserver(uri, index + 1, observer, notifyForDescendents);
node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, observersLock);
return;
}
}
@@ -546,13 +549,13 @@ public final class ContentService extends IContentService.Stub {
// No child found, create one
ObserverNode node = new ObserverNode(segment);
mChildren.add(node);
node.addObserver(uri, index + 1, observer, notifyForDescendents);
node.addObserverLocked(uri, index + 1, observer, notifyForDescendents, observersLock);
}
public boolean removeObserver(IContentObserver observer) {
public boolean removeObserverLocked(IContentObserver observer) {
int size = mChildren.size();
for (int i = 0; i < size; i++) {
boolean empty = mChildren.get(i).removeObserver(observer);
boolean empty = mChildren.get(i).removeObserverLocked(observer);
if (empty) {
mChildren.remove(i);
i--;
@@ -578,10 +581,8 @@ public final class ContentService extends IContentService.Stub {
return false;
}
private void collectMyObservers(Uri uri,
boolean leaf, IContentObserver observer, boolean selfNotify,
ArrayList<ObserverCall> calls)
{
private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
boolean selfNotify, ArrayList<ObserverCall> calls) {
int N = mObservers.size();
IBinder observerBinder = observer == null ? null : observer.asBinder();
for (int i = 0; i < N; i++) {
@@ -600,17 +601,17 @@ public final class ContentService extends IContentService.Stub {
}
}
public void collectObservers(Uri uri, int index, IContentObserver observer,
public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
boolean selfNotify, ArrayList<ObserverCall> calls) {
String segment = null;
int segmentCount = countUriSegments(uri);
if (index >= segmentCount) {
// This is the leaf node, notify all observers
collectMyObservers(uri, true, observer, selfNotify, calls);
collectMyObserversLocked(true, observer, selfNotify, calls);
} else if (index < segmentCount){
segment = getUriSegment(uri, index);
// Notify any observers at this level who are interested in descendents
collectMyObservers(uri, false, observer, selfNotify, calls);
collectMyObserversLocked(false, observer, selfNotify, calls);
}
int N = mChildren.size();
@@ -618,7 +619,7 @@ public final class ContentService extends IContentService.Stub {
ObserverNode node = mChildren.get(i);
if (segment == null || node.mName.equals(segment)) {
// We found the child,
node.collectObservers(uri, index + 1, observer, selfNotify, calls);
node.collectObserversLocked(uri, index + 1, observer, selfNotify, calls);
if (segment != null) {
break;
}