summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.xml6
-rw-r--r--calendar/Android.mk17
-rw-r--r--core/java/android/content/ContentService.java53
-rw-r--r--core/java/android/database/sqlite/SQLiteCompiledSql.java19
-rw-r--r--core/java/android/database/sqlite/SQLiteProgram.java9
-rw-r--r--core/java/android/provider/Browser.java60
-rw-r--r--core/java/android/widget/AbsListView.java11
-rw-r--r--core/java/android/widget/GridView.java4
-rw-r--r--core/java/android/widget/ListView.java4
-rw-r--r--core/tests/coretests/src/android/content/ObserverNodeTest.java35
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp3
11 files changed, 143 insertions, 78 deletions
diff --git a/api/current.xml b/api/current.xml
index d74127ad2d06..28a71687e3ad 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -55017,7 +55017,7 @@
volatile="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="protected"
>
</field>
@@ -55027,7 +55027,7 @@
volatile="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="protected"
>
</field>
@@ -55037,7 +55037,7 @@
volatile="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="protected"
>
</field>
diff --git a/calendar/Android.mk b/calendar/Android.mk
deleted file mode 100644
index 7f9ee0ac452f..000000000000
--- a/calendar/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2009 Google, Inc.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := calendar
-LOCAL_SRC_FILES := \
- ../core/java/android/provider/Calendar.java \
- ../core/java/android/pim/EventRecurrence.java \
- ../core/java/android/pim/ICalendar.java \
- ../core/java/android/pim/RecurrenceSet.java \
- ../core/java/android/pim/ContactsAsyncHelper.java \
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Include this library in the build server's output directory
-$(call dist-for-goals, droid, $(LOCAL_BUILT_MODULE):calendar.jar)
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index b5a78fa95c71..0477d6dfc3e9 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -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;
}
diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java
index a7a1d9ae6d25..486ad20dcb7f 100644
--- a/core/java/android/database/sqlite/SQLiteCompiledSql.java
+++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java
@@ -28,6 +28,8 @@ import android.util.Log;
*/
/* package */ class SQLiteCompiledSql {
+ private static final String TAG = "SQLiteCompiledSql";
+
/** The database this program is compiled against. */
/* package */ SQLiteDatabase mDatabase;
@@ -44,11 +46,17 @@ import android.util.Log;
*/
/* package */ int nStatement = 0;
+ /** the following are for debugging purposes */
+ private String mSqlStmt = null;
+ private Throwable mStackTrace = null;
+
/** when in cache and is in use, this member is set */
private boolean mInUse = false;
/* package */ SQLiteCompiledSql(SQLiteDatabase db, String sql) {
mDatabase = db;
+ mSqlStmt = sql;
+ mStackTrace = new Exception().fillInStackTrace();
this.nHandle = db.mNativeHandle;
compile(sql, true);
}
@@ -115,8 +123,15 @@ import android.util.Log;
* Make sure that the native resource is cleaned up.
*/
@Override
- protected void finalize() {
- releaseSqlStatement();
+ protected void finalize() throws Throwable {
+ try {
+ if (nStatement == 0) return;
+ // finalizer should NEVER get called
+ Log.w(TAG, "finalizer should never be called. sql: " + mSqlStmt, mStackTrace);
+ releaseSqlStatement();
+ } finally {
+ super.finalize();
+ }
}
/**
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 63acab767d71..389e15e6935a 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -21,7 +21,10 @@ package android.database.sqlite;
*/
public abstract class SQLiteProgram extends SQLiteClosable {
- /** The database this program is compiled against. */
+ /** The database this program is compiled against.
+ * @deprecated do not use this
+ */
+ @Deprecated
protected SQLiteDatabase mDatabase;
/** The SQL used to create this query */
@@ -30,7 +33,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
/**
* Native linkage, do not modify. This comes from the database and should not be modified
* in here or in the native code.
+ * @deprecated do not use this
*/
+ @Deprecated
protected int nHandle = 0;
/**
@@ -41,7 +46,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
/**
* SQLiteCompiledSql statement id is populated with the corresponding object from the above
* member. This member is used by the native_bind_* methods
+ * @deprecated do not use this
*/
+ @Deprecated
protected int nStatement = 0;
/* package */ SQLiteProgram(SQLiteDatabase db, String sql) {
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 10b93711ebba..f32fb5a2ec57 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -211,6 +211,57 @@ public class Browser {
new String[] { BookmarkColumns.URL }, null, null, null);
}
+ private static final void addOrUrlEquals(StringBuilder sb) {
+ sb.append(" OR " + BookmarkColumns.URL + " = ");
+ }
+
+ /**
+ * Return a Cursor with all history/bookmarks that are similar to url,
+ * where similar means 'http(s)://' and 'www.' are optional, but the rest
+ * of the url is the same.
+ * @param cr The ContentResolver used to access the database.
+ * @param url The url to compare to.
+ * @hide
+ */
+ public static final Cursor getVisitedLike(ContentResolver cr, String url) {
+ boolean secure = false;
+ String compareString = url;
+ if (compareString.startsWith("http://")) {
+ compareString = compareString.substring(7);
+ } else if (compareString.startsWith("https://")) {
+ compareString = compareString.substring(8);
+ secure = true;
+ }
+ if (compareString.startsWith("www.")) {
+ compareString = compareString.substring(4);
+ }
+ StringBuilder whereClause = null;
+ if (secure) {
+ whereClause = new StringBuilder(BookmarkColumns.URL + " = ");
+ DatabaseUtils.appendEscapedSQLString(whereClause,
+ "https://" + compareString);
+ addOrUrlEquals(whereClause);
+ DatabaseUtils.appendEscapedSQLString(whereClause,
+ "https://www." + compareString);
+ } else {
+ whereClause = new StringBuilder(BookmarkColumns.URL + " = ");
+ DatabaseUtils.appendEscapedSQLString(whereClause,
+ compareString);
+ addOrUrlEquals(whereClause);
+ String wwwString = "www." + compareString;
+ DatabaseUtils.appendEscapedSQLString(whereClause,
+ wwwString);
+ addOrUrlEquals(whereClause);
+ DatabaseUtils.appendEscapedSQLString(whereClause,
+ "http://" + compareString);
+ addOrUrlEquals(whereClause);
+ DatabaseUtils.appendEscapedSQLString(whereClause,
+ "http://" + wwwString);
+ }
+ return cr.query(BOOKMARKS_URI, HISTORY_PROJECTION,
+ whereClause.toString(), null, null);
+ }
+
/**
* Update the visited history to acknowledge that a site has been
* visited.
@@ -225,14 +276,7 @@ public class Browser {
String url, boolean real) {
long now = new Date().getTime();
try {
- StringBuilder sb = new StringBuilder(BookmarkColumns.URL + " = ");
- DatabaseUtils.appendEscapedSQLString(sb, url);
- Cursor c = cr.query(
- BOOKMARKS_URI,
- HISTORY_PROJECTION,
- sb.toString(),
- null,
- null);
+ Cursor c = getVisitedLike(cr, url);
/* We should only get one answer that is exactly the same. */
if (c.moveToFirst()) {
ContentValues map = new ContentValues();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 2ea6abcad0da..a555ae4772f5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4032,6 +4032,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
@ViewDebug.ExportedProperty
boolean recycledHeaderFooter;
+ /**
+ * When an AbsListView is measured with an AT_MOST measure spec, it needs
+ * to obtain children views to measure itself. When doing so, the children
+ * are not attached to the window, but put in the recycler which assumes
+ * they've been attached before. Setting this flag will force the reused
+ * view to be attached to the window rather than just attached to the
+ * parent.
+ */
+ @ViewDebug.ExportedProperty
+ boolean forceAdd;
+
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 9e930a5f7e39..be633be65084 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -938,6 +938,7 @@ public class GridView extends AbsListView {
child.setLayoutParams(p);
}
p.viewType = mAdapter.getItemViewType(0);
+ p.forceAdd = true;
int childHeightSpec = getChildMeasureSpec(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
@@ -1257,9 +1258,10 @@ public class GridView extends AbsListView {
}
p.viewType = mAdapter.getItemViewType(position);
- if (recycled) {
+ if (recycled && !p.forceAdd) {
attachViewToParent(child, where, p);
} else {
+ p.forceAdd = false;
addViewInLayout(child, where, p, true);
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 88f2e123096c..e3eb6db99168 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1109,6 +1109,7 @@ public class ListView extends AbsListView {
child.setLayoutParams(p);
}
p.viewType = mAdapter.getItemViewType(position);
+ p.forceAdd = true;
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec,
mListPadding.left + mListPadding.right, p.width);
@@ -1743,10 +1744,11 @@ public class ListView extends AbsListView {
}
p.viewType = mAdapter.getItemViewType(position);
- if (recycled || (p.recycledHeaderFooter &&
+ if ((recycled && !p.forceAdd) || (p.recycledHeaderFooter &&
p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) {
attachViewToParent(child, flowDown ? -1 : 0, p);
} else {
+ p.forceAdd = false;
if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
p.recycledHeaderFooter = true;
}
diff --git a/core/tests/coretests/src/android/content/ObserverNodeTest.java b/core/tests/coretests/src/android/content/ObserverNodeTest.java
index 68cc75b7b2ad..736c75926db4 100644
--- a/core/tests/coretests/src/android/content/ObserverNodeTest.java
+++ b/core/tests/coretests/src/android/content/ObserverNodeTest.java
@@ -24,50 +24,49 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.test.AndroidTestCase;
-import android.util.Log;
-public class ObserverNodeTest extends AndroidTestCase {
+public class ObserverNodeTest extends AndroidTestCase {
static class TestObserver extends ContentObserver {
public TestObserver() {
super(new Handler());
}
}
-
+
public void testUri() {
ObserverNode root = new ObserverNode("");
Uri[] uris = new Uri[] {
Uri.parse("content://c/a/"),
Uri.parse("content://c/"),
- Uri.parse("content://x/"),
+ Uri.parse("content://x/"),
Uri.parse("content://c/b/"),
Uri.parse("content://c/a/a1/1/"),
Uri.parse("content://c/a/a1/2/"),
Uri.parse("content://c/b/1/"),
Uri.parse("content://c/b/2/"),
};
-
+
int[] nums = new int[] {4, 7, 1, 4, 2, 2, 3, 3};
-
+
// special case
- root.addObserver(uris[0], new TestObserver().getContentObserver(), false);
+ root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root);
for(int i = 1; i < uris.length; i++) {
- root.addObserver(uris[i], new TestObserver().getContentObserver(), true);
+ root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root);
}
-
+
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
-
+
for (int i = nums.length - 1; i >=0; --i) {
- root.collectObservers(uris[i], 0, null, false, calls);
+ root.collectObserversLocked(uris[i], 0, null, false, calls);
assertEquals(nums[i], calls.size());
calls.clear();
}
}
-
+
public void testUriNotNotify() {
ObserverNode root = new ObserverNode("");
Uri[] uris = new Uri[] {
Uri.parse("content://c/"),
- Uri.parse("content://x/"),
+ Uri.parse("content://x/"),
Uri.parse("content://c/a/"),
Uri.parse("content://c/b/"),
Uri.parse("content://c/a/1/"),
@@ -76,15 +75,15 @@ public class ObserverNodeTest extends AndroidTestCase {
Uri.parse("content://c/b/2/"),
};
int[] nums = new int[] {7, 1, 3, 3, 1, 1, 1, 1};
-
+
for(int i = 0; i < uris.length; i++) {
- root.addObserver(uris[i], new TestObserver().getContentObserver(), false);
+ root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root);
}
-
+
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
-
+
for (int i = uris.length - 1; i >=0; --i) {
- root.collectObservers(uris[i], 0, null, false, calls);
+ root.collectObserversLocked(uris[i], 0, null, false, calls);
assertEquals(nums[i], calls.size());
calls.clear();
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index c26d68274e60..594e01049157 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1768,7 +1768,7 @@ ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
status_t MediaPlayerService::AudioCache::wait()
{
Mutex::Autolock lock(mLock);
- if (!mCommandComplete) {
+ while (!mCommandComplete) {
mSignal.wait(mLock);
}
mCommandComplete = false;
@@ -1805,6 +1805,7 @@ void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int
}
// wake up thread
+ Mutex::Autolock lock(p->mLock);
p->mCommandComplete = true;
p->mSignal.signal();
}