Merge "Set SOURCE to app package name when starting QSB (if not set)"
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 5e2c61e..072a9d2 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -434,7 +434,11 @@
sp<DataSource> dataSource;
if (!strncasecmp("http://", filename, 7)) {
dataSource = new HTTPDataSource(filename);
- dataSource = new CachingDataSource(dataSource, 64 * 1024, 10);
+ if (((HTTPDataSource *)dataSource.get())->connect() != OK) {
+ fprintf(stderr, "failed to connect to HTTP server.\n");
+ return -1;
+ }
+ dataSource = new CachingDataSource(dataSource, 32 * 1024, 20);
} else {
dataSource = new FileSource(filename);
}
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 6d0a266..16b603c 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1699,7 +1699,7 @@
}
}
} else {
- Account[] accounts = getAccounts(null /* type */);
+ Account[] accounts = getAccountsByType(null /* type */);
fout.println("Accounts: " + accounts.length);
for (Account account : accounts) {
fout.println(" " + account);
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index f364def..0909952 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -266,7 +266,7 @@
}
private void dismissDialog() {
- if (mDecor == null || !mShowing || mDecor.getWindowToken() == null) {
+ if (mDecor == null || !mShowing) {
return;
}
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 85769a6..840a714 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -416,6 +416,9 @@
}
private void initializeSyncAdapter(Account account, String authority) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "initializeSyncAdapter: " + account + ", authority " + authority);
+ }
SyncAdapterType syncAdapterType = SyncAdapterType.newKey(authority, account.type);
RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
mSyncAdapters.getServiceInfo(syncAdapterType);
@@ -427,9 +430,11 @@
Intent intent = new Intent();
intent.setAction("android.content.SyncAdapter");
intent.setComponent(syncAdapterInfo.componentName);
- mContext.bindService(intent, new InitializerServiceConnection(account, authority, mContext,
+ if (!mContext.bindService(intent, new InitializerServiceConnection(account, authority, mContext,
mMainHandler),
- Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND);
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND)) {
+ Log.w(TAG, "initializeSyncAdapter: failed to bind to " + intent);
+ }
}
private static class InitializerServiceConnection implements ServiceConnection {
@@ -452,6 +457,9 @@
try {
if (!mInitialized) {
mInitialized = true;
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "calling initialize: " + mAccount + ", authority " + mAuthority);
+ }
ISyncAdapter.Stub.asInterface(service).initialize(mAccount, mAuthority);
}
} catch (RemoteException e) {
@@ -1307,7 +1315,6 @@
// it if sync is still failing
private boolean mErrorNotificationInstalled = false;
private volatile CountDownLatch mReadyToRunLatch = new CountDownLatch(1);
-
public void onBootCompleted() {
mBootCompleted = true;
if (mReadyToRunLatch != null) {
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 240da72..0ec24530 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -121,6 +121,9 @@
private static final boolean SYNC_ENABLED_DEFAULT = false;
+ // the version of the accounts xml file format
+ private static final int ACCOUNTS_VERSION = 1;
+
public static class PendingOperation {
final Account account;
final int syncSource;
@@ -1322,6 +1325,7 @@
* Read all account information back in to the initial engine state.
*/
private void readAccountInfoLocked() {
+ boolean writeNeeded = false;
FileInputStream fis = null;
try {
fis = mAccountInfoFile.openRead();
@@ -1336,6 +1340,16 @@
if ("accounts".equals(tagName)) {
String listen = parser.getAttributeValue(
null, "listen-for-tickles");
+ String versionString = parser.getAttributeValue(null, "version");
+ int version;
+ try {
+ version = (versionString == null) ? 0 : Integer.parseInt(versionString);
+ } catch (NumberFormatException e) {
+ version = 0;
+ }
+ if (version < ACCOUNTS_VERSION) {
+ writeNeeded = true;
+ }
mMasterSyncAutomatically = listen == null
|| Boolean.parseBoolean(listen);
eventType = parser.next();
@@ -1346,7 +1360,7 @@
tagName = parser.getName();
if (parser.getDepth() == 2) {
if ("authority".equals(tagName)) {
- authority = parseAuthority(parser);
+ authority = parseAuthority(parser, version);
periodicSync = null;
}
} else if (parser.getDepth() == 3) {
@@ -1364,9 +1378,11 @@
}
} catch (XmlPullParserException e) {
Log.w(TAG, "Error reading accounts", e);
+ return;
} catch (java.io.IOException e) {
if (fis == null) Log.i(TAG, "No initial accounts");
else Log.w(TAG, "Error reading accounts", e);
+ return;
} finally {
if (fis != null) {
try {
@@ -1375,9 +1391,13 @@
}
}
}
+
+ if (writeNeeded) {
+ writeAccountInfoLocked();
+ }
}
- private AuthorityInfo parseAuthority(XmlPullParser parser) {
+ private AuthorityInfo parseAuthority(XmlPullParser parser, int version) {
AuthorityInfo authority = null;
int id = -1;
try {
@@ -1406,8 +1426,14 @@
if (DEBUG_FILE) Log.v(TAG, "Creating entry");
authority = getOrCreateAuthorityLocked(
new Account(accountName, accountType), authorityName, id, false);
- // clear this since we will read these later on
- authority.periodicSyncs.clear();
+ // If the version is 0 then we are upgrading from a file format that did not
+ // know about periodic syncs. In that case don't clear the list since we
+ // want the default, which is a daily periodioc sync.
+ // Otherwise clear out this default list since we will populate it later with
+ // the periodic sync descriptions that are read from the configuration file.
+ if (version > 0) {
+ authority.periodicSyncs.clear();
+ }
}
if (authority != null) {
authority.enabled = enabled == null || Boolean.parseBoolean(enabled);
@@ -1443,6 +1469,7 @@
}
final Pair<Bundle, Long> periodicSync = Pair.create(extras, period);
authority.periodicSyncs.add(periodicSync);
+
return periodicSync;
}
@@ -1491,6 +1518,7 @@
out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
out.startTag(null, "accounts");
+ out.attribute(null, "version", Integer.toString(ACCOUNTS_VERSION));
if (!mMasterSyncAutomatically) {
out.attribute(null, "listen-for-tickles", "false");
}
@@ -1505,7 +1533,7 @@
out.attribute(null, "authority", authority.authority);
if (!authority.enabled) {
out.attribute(null, "enabled", "false");
- }
+ }
if (authority.syncable < 0) {
out.attribute(null, "syncable", "unknown");
} else if (authority.syncable == 0) {
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 1c0d55f..af42ce0 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -62,6 +62,10 @@
private int mLoadType;
private boolean mFirstLayoutDone = true;
private boolean mCommitted = true;
+ // Flag for blocking messages. This is used during destroy() so
+ // that if the UI thread posts any messages after the message
+ // queue has been cleared,they are ignored.
+ private boolean mBlockMessages = false;
// Is this frame the main frame?
private boolean mIsMainFrame;
@@ -383,6 +387,7 @@
public void destroy() {
mOrientationListener.disable();
nativeDestroyFrame();
+ mBlockMessages = true;
removeCallbacksAndMessages(null);
}
@@ -392,6 +397,9 @@
*/
@Override
public void handleMessage(Message msg) {
+ if (mBlockMessages) {
+ return;
+ }
switch (msg.what) {
case FRAME_COMPLETED: {
if (mSettings.getSavePassword() && hasPasswordField()) {
diff --git a/core/tests/coretests/src/android/content/SyncStorageEngineTest.java b/core/tests/coretests/src/android/content/SyncStorageEngineTest.java
index 1505a7c..7028d1a 100644
--- a/core/tests/coretests/src/android/content/SyncStorageEngineTest.java
+++ b/core/tests/coretests/src/android/content/SyncStorageEngineTest.java
@@ -16,6 +16,8 @@
package android.content;
+import com.android.internal.os.AtomicFile;
+
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import android.test.suitebuilder.annotation.SmallTest;
@@ -26,6 +28,7 @@
import java.util.List;
import java.io.File;
+import java.io.FileOutputStream;
public class SyncStorageEngineTest extends AndroidTestCase {
@@ -193,6 +196,109 @@
assertEquals(1, engine.getIsSyncable(account1, authority2));
assertEquals(0, engine.getIsSyncable(account2, authority2));
}
+
+ @SmallTest
+ public void testAuthorityParsing() throws Exception {
+ final Account account = new Account("account1", "type1");
+ final String authority1 = "auth1";
+ final String authority2 = "auth2";
+ final String authority3 = "auth3";
+ final Bundle extras = new Bundle();
+ PeriodicSync sync1 = new PeriodicSync(account, authority1, extras, (long) (60 * 60 * 24));
+ PeriodicSync sync2 = new PeriodicSync(account, authority2, extras, (long) (60 * 60 * 24));
+ PeriodicSync sync3 = new PeriodicSync(account, authority3, extras, (long) (60 * 60 * 24));
+ PeriodicSync sync1s = new PeriodicSync(account, authority1, extras, 1000);
+ PeriodicSync sync2s = new PeriodicSync(account, authority2, extras, 1000);
+ PeriodicSync sync3s = new PeriodicSync(account, authority3, extras, 1000);
+
+ MockContentResolver mockResolver = new MockContentResolver();
+
+ final TestContext testContext = new TestContext(mockResolver, getContext());
+ SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
+
+ byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<accounts>\n"
+ + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
+ + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n"
+ + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
+ + "</accounts>\n").getBytes();
+
+ File syncDir = new File(new File(testContext.getFilesDir(), "system"), "sync");
+ syncDir.mkdirs();
+ AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
+ FileOutputStream fos = accountInfoFile.startWrite();
+ fos.write(accountsFileData);
+ accountInfoFile.finishWrite(fos);
+
+ engine.clearAndReadState();
+
+ List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, authority1);
+ assertEquals(1, syncs.size());
+ assertEquals(sync1, syncs.get(0));
+
+ syncs = engine.getPeriodicSyncs(account, authority2);
+ assertEquals(1, syncs.size());
+ assertEquals(sync2, syncs.get(0));
+
+ syncs = engine.getPeriodicSyncs(account, authority3);
+ assertEquals(1, syncs.size());
+ assertEquals(sync3, syncs.get(0));
+
+ accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<accounts version=\"1\">\n"
+ + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
+ + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n"
+ + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
+ + "</accounts>\n").getBytes();
+
+ accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
+ fos = accountInfoFile.startWrite();
+ fos.write(accountsFileData);
+ accountInfoFile.finishWrite(fos);
+
+ engine.clearAndReadState();
+
+ syncs = engine.getPeriodicSyncs(account, authority1);
+ assertEquals(0, syncs.size());
+
+ syncs = engine.getPeriodicSyncs(account, authority2);
+ assertEquals(0, syncs.size());
+
+ syncs = engine.getPeriodicSyncs(account, authority3);
+ assertEquals(0, syncs.size());
+
+ accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<accounts version=\"1\">\n"
+ + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\">\n"
+ + "<periodicSync period=\"1000\" />\n"
+ + "</authority>"
+ + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\">\n"
+ + "<periodicSync period=\"1000\" />\n"
+ + "</authority>"
+ + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\">\n"
+ + "<periodicSync period=\"1000\" />\n"
+ + "</authority>"
+ + "</accounts>\n").getBytes();
+
+ accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
+ fos = accountInfoFile.startWrite();
+ fos.write(accountsFileData);
+ accountInfoFile.finishWrite(fos);
+
+ engine.clearAndReadState();
+
+ syncs = engine.getPeriodicSyncs(account, authority1);
+ assertEquals(1, syncs.size());
+ assertEquals(sync1s, syncs.get(0));
+
+ syncs = engine.getPeriodicSyncs(account, authority2);
+ assertEquals(1, syncs.size());
+ assertEquals(sync2s, syncs.get(0));
+
+ syncs = engine.getPeriodicSyncs(account, authority3);
+ assertEquals(1, syncs.size());
+ assertEquals(sync3s, syncs.get(0));
+ }
}
class TestContext extends ContextWrapper {
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 43762e7..843a8fd 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -58,7 +58,7 @@
int pathRemaining = PATH_MAX - pathLength;
strcpy(pathBuffer, path);
- if (pathLength > 0 && pathBuffer[pathLength - 1]) {
+ if (pathLength > 0 && pathBuffer[pathLength - 1] != '/') {
pathBuffer[pathLength] = '/';
pathBuffer[pathLength + 1] = 0;
--pathRemaining;
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 2a16d26..0fea72e 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -222,7 +222,7 @@
ssize_t n = mDataSource->readAt(mOffset, &header, 1);
if (n < 1) {
- return ERROR_IO;
+ return ERROR_END_OF_STREAM;
}
if (header & 0x83) {
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 16a2a10..b263238 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -275,6 +275,7 @@
size_t utf8len = 0;
for (size_t i = 0; i < size; ++i) {
if (data[i] == '\0') {
+ size = i;
break;
} else if (data[i] < 0x80) {
++utf8len;
diff --git a/obex/javax/obex/ServerRequestHandler.java b/obex/javax/obex/ServerRequestHandler.java
index d93e5b6..0882572 100644
--- a/obex/javax/obex/ServerRequestHandler.java
+++ b/obex/javax/obex/ServerRequestHandler.java
@@ -197,6 +197,13 @@
}
/**
+ * Called when a ABORT request is received.
+ */
+ public int onAbort(HeaderSet request, HeaderSet reply) {
+ return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
+ }
+
+ /**
* Called when a PUT request is received.
* <P>
* If this method is not implemented by the class that extends this class,
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
index 503d440..a4b9759 100644
--- a/obex/javax/obex/ServerSession.java
+++ b/obex/javax/obex/ServerSession.java
@@ -115,6 +115,9 @@
case ObexHelper.OBEX_OPCODE_SETPATH:
handleSetPathRequest();
break;
+ case ObexHelper.OBEX_OPCODE_ABORT:
+ handleAbortRequest();
+ break;
case -1:
done = true;
@@ -145,6 +148,35 @@
}
/**
+ * Handles a ABORT request from a client. This method will read the rest of
+ * the request from the client. Assuming the request is valid, it will
+ * create a <code>HeaderSet</code> object to pass to the
+ * <code>ServerRequestHandler</code> object. After the handler processes the
+ * request, this method will create a reply message to send to the server.
+ *
+ * @throws IOException if an error occurred at the transport layer
+ */
+ private void handleAbortRequest() throws IOException {
+ int code = ResponseCodes.OBEX_HTTP_OK;
+ HeaderSet request = new HeaderSet();
+ HeaderSet reply = new HeaderSet();
+
+ int length = mInput.read();
+ length = (length << 8) + mInput.read();
+ if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
+ code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
+ } else {
+ for (int i = 3; i < length; i++) {
+ mInput.read();
+ }
+ code = mListener.onAbort(request, reply);
+ Log.v(TAG, "onAbort request handler return value- " + code);
+ code = validateResponseCode(code);
+ }
+ sendResponse(code, null);
+ }
+
+ /**
* Handles a PUT request from a client. This method will provide a
* <code>ServerOperation</code> object to the request handler. The
* <code>ServerOperation</code> object will handle the rest of the request.