diff options
-rw-r--r-- | Android.mk | 6 | ||||
-rw-r--r-- | core/java/android/provider/MediaStore.java | 30 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 80 | ||||
-rw-r--r-- | core/tests/coretests/src/android/pim/vcard/ExportTestResolver.java | 5 | ||||
-rw-r--r-- | core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java | 7 | ||||
-rw-r--r-- | core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java | 28 | ||||
-rw-r--r-- | core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java | 87 | ||||
-rw-r--r-- | core/tests/coretests/src/android/pim/vcard/VCardVerifier.java | 25 | ||||
-rw-r--r-- | media/libmedia/fixedfft.cpp | 2 | ||||
-rw-r--r-- | packages/SettingsProvider/res/values/defaults.xml | 3 | ||||
-rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java | 182 | ||||
-rw-r--r-- | tests/CoreTests/android/core/JavaPerformanceTests.java | 1 | ||||
-rw-r--r-- | tests/CoreTests/android/core/StringTest.java | 951 | ||||
-rw-r--r-- | tools/aapt/Android.mk | 2 | ||||
-rw-r--r-- | tools/localize/Android.mk | 2 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipProfile.java | 41 |
16 files changed, 312 insertions, 1140 deletions
@@ -348,7 +348,7 @@ framework_docs_LOCAL_JAVA_LIBRARIES := \ framework \ framework_docs_LOCAL_MODULE_CLASS := JAVA_LIBRARIES -framework_docs_LOCAL_DROIDDOC_HTML_DIR := docs/html +framework_docs_LOCAL_DROIDDOC_HTML_DIR := $(LOCAL_PATH)/docs/html $(OUT_DOCS)/gen # The since flag (-since N.xml API_LEVEL) is used to add API Level information # to the reference documentation. Must be in order of oldest to newest. framework_docs_LOCAL_DROIDDOC_OPTIONS := \ @@ -539,8 +539,8 @@ LOCAL_DROIDDOC_CUSTOM_ASSET_DIR:=assets-sdk include $(BUILD_DROIDDOC) -# explicitly specify that online-sdk depends on framework-res. -$(full_target): framework-res-package-target +# explicitly specify that online-sdk depends on framework-res and any generated docs +$(full_target): framework-res-package-target $(ALL_GENERATED_DOCS) # ==== docs that have all of the stuff that's @hidden ======================= include $(CLEAR_VARS) diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 40ed980..d20e89d 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -249,6 +249,8 @@ public final class MediaStore { private static final int MICRO_KIND = 3; private static final String[] PROJECTION = new String[] {_ID, MediaColumns.DATA}; static final int DEFAULT_GROUP_ID = 0; + private static final Object sThumbBufLock = new Object(); + private static byte[] sThumbBuf; private static Bitmap getMiniThumbFromFile(Cursor c, Uri baseUri, ContentResolver cr, BitmapFactory.Options options) { Bitmap bitmap = null; @@ -321,11 +323,15 @@ public final class MediaStore { long magic = thumbFile.getMagic(origId); if (magic != 0) { if (kind == MICRO_KIND) { - byte[] data = new byte[MiniThumbFile.BYTES_PER_MINTHUMB]; - if (thumbFile.getMiniThumbFromFile(origId, data) != null) { - bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); - if (bitmap == null) { - Log.w(TAG, "couldn't decode byte array."); + synchronized (sThumbBufLock) { + if (sThumbBuf == null) { + sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB]; + } + if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) { + bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length); + if (bitmap == null) { + Log.w(TAG, "couldn't decode byte array."); + } } } return bitmap; @@ -357,11 +363,15 @@ public final class MediaStore { // Assuming thumbnail has been generated, at least original image exists. if (kind == MICRO_KIND) { - byte[] data = new byte[MiniThumbFile.BYTES_PER_MINTHUMB]; - if (thumbFile.getMiniThumbFromFile(origId, data) != null) { - bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); - if (bitmap == null) { - Log.w(TAG, "couldn't decode byte array."); + synchronized (sThumbBufLock) { + if (sThumbBuf == null) { + sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB]; + } + if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) { + bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length); + if (bitmap == null) { + Log.w(TAG, "couldn't decode byte array."); + } } } } else if (kind == MINI_KIND) { diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 407d2e7..62a4495 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -506,7 +506,7 @@ static void blockSigpipe() static void readLocale(char* language, char* region) { char propLang[PROPERTY_VALUE_MAX], propRegn[PROPERTY_VALUE_MAX]; - + property_get("persist.sys.language", propLang, ""); property_get("persist.sys.country", propRegn, ""); if (*propLang == 0 && *propRegn == 0) { @@ -710,6 +710,33 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) LOGW("dalvik.vm.gc.overwritefree should be 'true' or 'false'"); } + /* enable heap verification before each gc */ + property_get("dalvik.vm.gc.preverify", propBuf, "false"); + if (strcmp(propBuf, "true") == 0) { + opt.optionString = "-Xgc:preverify"; + mOptions.add(opt); + } else if (strcmp(propBuf, "false") != 0) { + LOGW("dalvik.vm.gc.preverify should be 'true' or 'false'"); + } + + /* enable heap verification after each gc */ + property_get("dalvik.vm.gc.postverify", propBuf, "false"); + if (strcmp(propBuf, "true") == 0) { + opt.optionString = "-Xgc:postverify"; + mOptions.add(opt); + } else if (strcmp(propBuf, "false") != 0) { + LOGW("dalvik.vm.gc.postverify should be 'true' or 'false'"); + } + + /* enable card table verification for partial gc */ + property_get("dalvik.vm.gc.verifycardtable", propBuf, "false"); + if (strcmp(propBuf, "true") == 0) { + opt.optionString = "-Xgc:verifycardtable"; + mOptions.add(opt); + } else if (strcmp(propBuf, "false") != 0) { + LOGW("dalvik.vm.gc.verifycardtable should be 'true' or 'false'"); + } + /* enable debugging; set suspend=y to pause during VM init */ #ifdef HAVE_ANDROID_OS /* use android ADB transport */ @@ -757,16 +784,6 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) } #if defined(WITH_JIT) - /* Minimal profile threshold to trigger JIT compilation */ - char jitThresholdBuf[sizeof("-Xjitthreshold:") + PROPERTY_VALUE_MAX]; - property_get("dalvik.vm.jit.threshold", propBuf, ""); - if (strlen(propBuf) > 0) { - strcpy(jitThresholdBuf, "-Xjitthreshold:"); - strcat(jitThresholdBuf, propBuf); - opt.optionString = jitThresholdBuf; - mOptions.add(opt); - } - /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */ char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX]; property_get("dalvik.vm.jit.op", propBuf, ""); @@ -777,16 +794,6 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) mOptions.add(opt); } - /* - * Reverse the polarity of dalvik.vm.jit.op and force interpreter-only - * for non-selected opcodes. - */ - property_get("dalvik.vm.jit.includeop", propBuf, ""); - if (strlen(propBuf) > 0) { - opt.optionString = "-Xincludeselectedop"; - mOptions.add(opt); - } - /* Force interpreter-only mode for selected methods */ char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX]; property_get("dalvik.vm.jit.method", propBuf, ""); @@ -796,37 +803,6 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) opt.optionString = jitMethodBuf; mOptions.add(opt); } - - /* - * Reverse the polarity of dalvik.vm.jit.method and force interpreter-only - * for non-selected methods. - */ - property_get("dalvik.vm.jit.includemethod", propBuf, ""); - if (strlen(propBuf) > 0) { - opt.optionString = "-Xincludeselectedmethod"; - mOptions.add(opt); - } - - /* - * Enable profile collection on JIT'ed code. - */ - property_get("dalvik.vm.jit.profile", propBuf, ""); - if (strlen(propBuf) > 0) { - opt.optionString = "-Xjitprofile"; - mOptions.add(opt); - } - - /* - * Disable optimizations by setting the corresponding bit to 1. - */ - char jitOptBuf[sizeof("-Xjitdisableopt:") + PROPERTY_VALUE_MAX]; - property_get("dalvik.vm.jit.disableopt", propBuf, ""); - if (strlen(propBuf) > 0) { - strcpy(jitOptBuf, "-Xjitdisableopt:"); - strcat(jitOptBuf, propBuf); - opt.optionString = jitOptBuf; - mOptions.add(opt); - } #endif if (executionMode == kEMIntPortable) { diff --git a/core/tests/coretests/src/android/pim/vcard/ExportTestResolver.java b/core/tests/coretests/src/android/pim/vcard/ExportTestResolver.java index 5968e83..951d0d8 100644 --- a/core/tests/coretests/src/android/pim/vcard/ExportTestResolver.java +++ b/core/tests/coretests/src/android/pim/vcard/ExportTestResolver.java @@ -24,6 +24,7 @@ import android.net.Uri; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.RawContacts; +import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.test.mock.MockCursor; @@ -44,6 +45,10 @@ import java.util.List; public ContactEntry addInputContactEntry() { return mProvider.buildInputEntry(); } + + public ExportTestProvider getProvider() { + return mProvider; + } } /* package */ class MockEntityIterator implements EntityIterator { diff --git a/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java b/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java index c3f6f79..1563da9 100644 --- a/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java +++ b/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java @@ -19,8 +19,6 @@ import android.content.ContentProviderOperation; import android.content.ContentProviderResult; import android.content.ContentValues; import android.net.Uri; -import android.provider.ContactsContract.Data; -import android.provider.ContactsContract.RawContacts; import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.Event; import android.provider.ContactsContract.CommonDataKinds.GroupMembership; @@ -34,6 +32,9 @@ import android.provider.ContactsContract.CommonDataKinds.Relation; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; import android.provider.ContactsContract.CommonDataKinds.Website; +import android.provider.ContactsContract.Data; +import android.provider.ContactsContract.RawContacts; +import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.text.TextUtils; @@ -45,10 +46,10 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; -import java.util.Map.Entry; /* package */ class ImportTestResolver extends MockContentResolver { final ImportTestProvider mProvider; diff --git a/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java index 2de0464..2962a92 100644 --- a/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java +++ b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java @@ -438,14 +438,26 @@ public class VCardExporterTests extends VCardTestsBase { .put(Phone.TYPE, Phone.TYPE_CUSTOM) .put(Phone.LABEL, "invalid"); PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElemWithEmptyName(); - elem.addExpectedNode("TEL", "1", new TypeSet("MODEM")) - .addExpectedNode("TEL", "2", new TypeSet("MSG")) - .addExpectedNode("TEL", "3", new TypeSet("BBS")) - .addExpectedNode("TEL", "4", new TypeSet("VIDEO")) - .addExpectedNode("TEL", "5", new TypeSet("VOICE")) - .addExpectedNode("TEL", "6", new TypeSet("CELL")) - .addExpectedNode("TEL", "7", new TypeSet("CELL")) - .addExpectedNode("TEL", "8", new TypeSet("X-invalid")); + if (VCardConfig.isV30(vcardType)) { + // vCard 3.0 accepts "invalid". Also stop using toUpper() + elem.addExpectedNode("TEL", "1", new TypeSet("Modem")) + .addExpectedNode("TEL", "2", new TypeSet("MSG")) + .addExpectedNode("TEL", "3", new TypeSet("BBS")) + .addExpectedNode("TEL", "4", new TypeSet("VIDEO")) + .addExpectedNode("TEL", "5", new TypeSet("VOICE")) + .addExpectedNode("TEL", "6", new TypeSet("CELL")) + .addExpectedNode("TEL", "7", new TypeSet("CELL")) + .addExpectedNode("TEL", "8", new TypeSet("invalid")); + } else { + elem.addExpectedNode("TEL", "1", new TypeSet("MODEM")) + .addExpectedNode("TEL", "2", new TypeSet("MSG")) + .addExpectedNode("TEL", "3", new TypeSet("BBS")) + .addExpectedNode("TEL", "4", new TypeSet("VIDEO")) + .addExpectedNode("TEL", "5", new TypeSet("VOICE")) + .addExpectedNode("TEL", "6", new TypeSet("CELL")) + .addExpectedNode("TEL", "7", new TypeSet("CELL")) + .addExpectedNode("TEL", "8", new TypeSet("X-invalid")); + } } public void testPhoneTypeHandlingV21() { diff --git a/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java b/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java index 416e872..9c6003f 100644 --- a/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java +++ b/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java @@ -16,95 +16,8 @@ package android.pim.vcard; -import android.content.ContentProvider; -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; import android.content.ContentValues; -import android.content.EntityIterator; -import android.content.res.AssetFileDescriptor; -import android.database.Cursor; -import android.database.CursorWindow; -import android.database.IBulkCursor; -import android.database.IContentObserver; -import android.net.Uri; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.pim.vcard.VCardConfig; import android.test.AndroidTestCase; -import android.util.Log; - -import java.util.ArrayList; - -/** - * Almost a dead copy of android.test.mock.MockContentProvider, but different in that this - * class extends ContentProvider, not implementing IContentProvider, - * so that MockContentResolver is able to accept this class :( - */ -class MockContentProvider extends ContentProvider { - @Override - public boolean onCreate() { - return true; - } - - @Override - public int bulkInsert(Uri url, ContentValues[] initialValues) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @SuppressWarnings("unused") - public IBulkCursor bulkQuery(Uri url, String[] projection, String selection, - String[] selectionArgs, String sortOrder, IContentObserver observer, - CursorWindow window) throws RemoteException { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @Override - @SuppressWarnings("unused") - public int delete(Uri url, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @Override - public String getType(Uri url) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @Override - public Uri insert(Uri url, ContentValues initialValues) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @Override - public ParcelFileDescriptor openFile(Uri url, String mode) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @Override - public AssetFileDescriptor openAssetFile(Uri uri, String mode) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @Override - public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @Override - public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - @Override - public int update(Uri url, ContentValues values, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException("unimplemented mock method"); - } - - public IBinder asBinder() { - throw new UnsupportedOperationException("unimplemented mock method"); - } -} /** * BaseClass for vCard unit tests with utility classes. diff --git a/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java b/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java index bfc3158..3cb5b9b 100644 --- a/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java +++ b/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java @@ -31,6 +31,7 @@ import android.pim.vcard.VCardParser_V30; import android.pim.vcard.exception.VCardException; import android.test.AndroidTestCase; import android.test.mock.MockContext; +import android.util.Log; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -51,6 +52,8 @@ import java.util.Arrays; } /* package */ class VCardVerifier { + private static final String LOG_TAG = "VCardVerifier"; + private class VCardVerifierInternal implements VCardComposer.OneEntryHandler { public boolean onInit(Context context) { return true; @@ -267,10 +270,13 @@ import java.util.Arrays; final ContentResolver resolver, final Uri uri, final String selection, final String[] selectionArgs, final String sortOrder) { - final ContentProvider provider = - resolver.acquireContentProviderClient(uri).getLocalContentProvider(); - return ((ExportTestProvider)provider).queryEntities( - uri, selection, selectionArgs, sortOrder); + if (ExportTestResolver.class.equals(resolver.getClass())) { + return ((ExportTestResolver)resolver).getProvider().queryEntities( + uri, selection, selectionArgs, sortOrder); + } + + Log.e(LOG_TAG, "Unexpected provider given."); + return null; } private Method getMockGetEntityIteratorMethod() @@ -285,18 +291,19 @@ import java.util.Arrays; composer.addHandler(mLineVerifier); composer.addHandler(mVCardVerifierInternal); if (!composer.init(VCardComposer.CONTACTS_TEST_CONTENT_URI, null, null, null)) { - mTestCase.fail("init() failed. Reason: " + composer.getErrorReason()); + AndroidTestCase.fail("init() failed. Reason: " + composer.getErrorReason()); } - mTestCase.assertFalse(composer.isAfterLast()); + AndroidTestCase.assertFalse(composer.isAfterLast()); try { while (!composer.isAfterLast()) { try { final Method mockGetEntityIteratorMethod = getMockGetEntityIteratorMethod(); - mTestCase.assertTrue( - composer.createOneEntry(getMockGetEntityIteratorMethod())); + AndroidTestCase.assertNotNull(mockGetEntityIteratorMethod); + AndroidTestCase.assertTrue( + composer.createOneEntry(mockGetEntityIteratorMethod)); } catch (Exception e) { e.printStackTrace(); - mTestCase.fail(); + AndroidTestCase.fail(); } } } finally { diff --git a/media/libmedia/fixedfft.cpp b/media/libmedia/fixedfft.cpp index 28eb05a..9cf05ba 100644 --- a/media/libmedia/fixedfft.cpp +++ b/media/libmedia/fixedfft.cpp @@ -26,7 +26,9 @@ #include <stdio.h> #include <stdint.h> +#ifdef __ARM_ARCH__ #include <machine/cpu-features.h> +#endif #define LOG_FFT_SIZE 10 #define MAX_FFT_SIZE (1 << LOG_FFT_SIZE) diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 185d72a..8349fe6 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -47,7 +47,8 @@ <bool name="def_networks_available_notification_on">true</bool> <bool name="def_backup_enabled">false</bool> - <string name="def_backup_transport" translatable="false"></string> + <string name="def_backup_transport" translatable="false">android/com.android.internal.backup.LocalTransport</string> + <!-- Default value for whether or not to pulse the notification LED when there is a pending notification --> <bool name="def_notification_pulse">true</bool> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 2e95932..81d82de 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -22,6 +22,8 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.LinkedHashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import android.app.backup.BackupManager; import android.content.ContentProvider; @@ -37,6 +39,7 @@ import android.database.sqlite.SQLiteQueryBuilder; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; +import android.os.FileObserver; import android.os.ParcelFileDescriptor; import android.os.SystemProperties; import android.provider.DrmStore; @@ -56,9 +59,15 @@ public class SettingsProvider extends ContentProvider { // Cache for settings, access-ordered for acting as LRU. // Guarded by themselves. - private static final int MAX_CACHE_ENTRIES = 50; - private static final SettingsCache sSystemCache = new SettingsCache(); - private static final SettingsCache sSecureCache = new SettingsCache(); + private static final int MAX_CACHE_ENTRIES = 200; + private static final SettingsCache sSystemCache = new SettingsCache("system"); + private static final SettingsCache sSecureCache = new SettingsCache("secure"); + + // The count of how many known (handled by SettingsProvider) + // database mutations are currently being handled. Used by + // sFileObserver to not reload the database when it's ourselves + // modifying it. + private static final AtomicInteger sKnownMutationsInFlight = new AtomicInteger(0); // Over this size we don't reject loading or saving settings but // we do consider them broken/malicious and don't keep them in @@ -67,6 +76,10 @@ public class SettingsProvider extends ContentProvider { private static final Bundle NULL_SETTING = Bundle.forPair("value", null); + // Used as a sentinel value in an instance equality test when we + // want to cache the existence of a key, but not store its value. + private static final Bundle TOO_LARGE_TO_CACHE_MARKER = Bundle.forPair("_dummy", null); + protected DatabaseHelper mOpenHelper; private BackupManager mBackupManager; @@ -201,6 +214,43 @@ public class SettingsProvider extends ContentProvider { } } + // FileObserver for external modifications to the database file. + // Note that this is for platform developers only with + // userdebug/eng builds who should be able to tinker with the + // sqlite database out from under the SettingsProvider, which is + // normally the exclusive owner of the database. But we keep this + // enabled all the time to minimize development-vs-user + // differences in testing. + private static SettingsFileObserver sObserverInstance; + private class SettingsFileObserver extends FileObserver { + private final AtomicBoolean mIsDirty = new AtomicBoolean(false); + private final String mPath; + + public SettingsFileObserver(String path) { + super(path, FileObserver.CLOSE_WRITE | + FileObserver.CREATE | FileObserver.DELETE | + FileObserver.MOVED_TO | FileObserver.MODIFY); + mPath = path; + } + + public void onEvent(int event, String path) { + int modsInFlight = sKnownMutationsInFlight.get(); + if (modsInFlight > 0) { + // our own modification. + return; + } + Log.d(TAG, "external modification to " + mPath + "; event=" + event); + if (!mIsDirty.compareAndSet(false, true)) { + // already handled. (we get a few update events + // during an sqlite write) + return; + } + Log.d(TAG, "updating our caches for " + mPath); + fullyPopulateCaches(); + mIsDirty.set(false); + } + } + @Override public boolean onCreate() { mOpenHelper = new DatabaseHelper(getContext()); @@ -210,9 +260,65 @@ public class SettingsProvider extends ContentProvider { return false; } + // Watch for external modifications to the database file, + // keeping our cache in sync. + // It's kinda lame to call mOpenHelper.getReadableDatabase() + // during onCreate(), but since ensureAndroidIdIsSet has + // already done it above and initialized/upgraded the + // database, might as well just use it... + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + sObserverInstance = new SettingsFileObserver(db.getPath()); + sObserverInstance.startWatching(); + startAsyncCachePopulation(); return true; } + private void startAsyncCachePopulation() { + new Thread("populate-settings-caches") { + public void run() { + fullyPopulateCaches(); + } + }.start(); + } + + private void fullyPopulateCaches() { + fullyPopulateCache("secure", sSecureCache); + fullyPopulateCache("system", sSystemCache); + } + + // Slurp all values (if sane in number & size) into cache. + private void fullyPopulateCache(String table, SettingsCache cache) { + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + Cursor c = db.query( + table, + new String[] { Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE }, + null, null, null, null, null, + "" + (MAX_CACHE_ENTRIES + 1) /* limit */); + try { + synchronized (cache) { + cache.clear(); + cache.setFullyMatchesDisk(true); // optimistic + int rows = 0; + while (c.moveToNext()) { + rows++; + String name = c.getString(0); + String value = c.getString(1); + cache.populate(name, value); + } + if (rows > MAX_CACHE_ENTRIES) { + // Somewhat redundant, as removeEldestEntry() will + // have already done this, but to be explicit: + cache.setFullyMatchesDisk(false); + Log.d(TAG, "row count exceeds max cache entries for table " + table); + } + Log.d(TAG, "cache for settings table '" + table + "' fullycached=" + + cache.fullyMatchesDisk()); + } + } finally { + c.close(); + } + } + private boolean ensureAndroidIdIsSet() { final Cursor c = query(Settings.Secure.CONTENT_URI, new String[] { Settings.NameValueTable.VALUE }, @@ -262,7 +368,19 @@ public class SettingsProvider extends ContentProvider { private Bundle lookupValue(String table, SettingsCache cache, String key) { synchronized (cache) { if (cache.containsKey(key)) { - return cache.get(key); + Bundle value = cache.get(key); + if (value != TOO_LARGE_TO_CACHE_MARKER) { + return value; + } + // else we fall through and read the value from disk + } else if (cache.fullyMatchesDisk()) { + // Fast path (very common). Don't even try touch disk + // if we know we've slurped it all in. Trying to + // touch the disk would mean waiting for yaffs2 to + // give us access, which could takes hundreds of + // milliseconds. And we're very likely being called + // from somebody's UI thread... + return NULL_SETTING; } } @@ -338,6 +456,7 @@ public class SettingsProvider extends ContentProvider { checkWritePermissions(args); SettingsCache cache = SettingsCache.forTable(args.table); + sKnownMutationsInFlight.incrementAndGet(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); try { @@ -350,6 +469,7 @@ public class SettingsProvider extends ContentProvider { db.setTransactionSuccessful(); } finally { db.endTransaction(); + sKnownMutationsInFlight.decrementAndGet(); } sendNotify(uri); @@ -449,8 +569,10 @@ public class SettingsProvider extends ContentProvider { return Uri.withAppendedPath(url, name); } + sKnownMutationsInFlight.incrementAndGet(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); final long rowId = db.insert(args.table, null, initialValues); + sKnownMutationsInFlight.decrementAndGet(); if (rowId <= 0) return null; SettingsCache.populate(cache, initialValues); // before we notify @@ -471,12 +593,15 @@ public class SettingsProvider extends ContentProvider { } checkWritePermissions(args); + sKnownMutationsInFlight.incrementAndGet(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count = db.delete(args.table, args.where, args.args); + sKnownMutationsInFlight.decrementAndGet(); if (count > 0) { SettingsCache.wipe(args.table); // before we notify sendNotify(url); } + startAsyncCachePopulation(); if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) deleted"); return count; } @@ -489,12 +614,15 @@ public class SettingsProvider extends ContentProvider { } checkWritePermissions(args); + sKnownMutationsInFlight.incrementAndGet(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + sKnownMutationsInFlight.decrementAndGet(); int count = db.update(args.table, initialValues, args.where, args.args); if (count > 0) { SettingsCache.wipe(args.table); // before we notify sendNotify(url); } + startAsyncCachePopulation(); if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) <- " + initialValues); return count; } @@ -506,12 +634,12 @@ public class SettingsProvider extends ContentProvider { * When a client attempts to openFile the default ringtone or * notification setting Uri, we will proxy the call to the current * default ringtone's Uri (if it is in the DRM or media provider). - */ + */ int ringtoneType = RingtoneManager.getDefaultType(uri); // Above call returns -1 if the Uri doesn't match a default type if (ringtoneType != -1) { Context context = getContext(); - + // Get the current value for the default sound Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType); @@ -531,7 +659,7 @@ public class SettingsProvider extends ContentProvider { throw new FileNotFoundException(e.getMessage()); } } - + return context.getContentResolver().openFileDescriptor(soundUri, mode); } } @@ -607,13 +735,38 @@ public class SettingsProvider extends ContentProvider { */ private static final class SettingsCache extends LinkedHashMap<String, Bundle> { - public SettingsCache() { + private final String mCacheName; + private boolean mCacheFullyMatchesDisk = false; // has the whole database slurped. + + public SettingsCache(String name) { super(MAX_CACHE_ENTRIES, 0.75f /* load factor */, true /* access ordered */); + mCacheName = name; + } + + /** + * Is the whole database table slurped into this cache? + */ + public boolean fullyMatchesDisk() { + synchronized (this) { + return mCacheFullyMatchesDisk; + } + } + + public void setFullyMatchesDisk(boolean value) { + synchronized (this) { + mCacheFullyMatchesDisk = value; + } } @Override protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > MAX_CACHE_ENTRIES; + if (size() <= MAX_CACHE_ENTRIES) { + return false; + } + synchronized (this) { + mCacheFullyMatchesDisk = false; + } + return true; } /** @@ -658,11 +811,15 @@ public class SettingsProvider extends ContentProvider { return; } String value = contentValues.getAsString(Settings.NameValueTable.VALUE); - synchronized (cache) { + cache.populate(name, value); + } + + public void populate(String name, String value) { + synchronized (this) { if (value == null || value.length() <= MAX_CACHE_ENTRY_SIZE) { - cache.put(name, Bundle.forPair(Settings.NameValueTable.VALUE, value)); + put(name, Bundle.forPair(Settings.NameValueTable.VALUE, value)); } else { - cache.remove(name); + put(name, TOO_LARGE_TO_CACHE_MARKER); } } } @@ -678,6 +835,7 @@ public class SettingsProvider extends ContentProvider { } synchronized (cache) { cache.clear(); + cache.mCacheFullyMatchesDisk = true; } } diff --git a/tests/CoreTests/android/core/JavaPerformanceTests.java b/tests/CoreTests/android/core/JavaPerformanceTests.java index fbe70cc..95075ea 100644 --- a/tests/CoreTests/android/core/JavaPerformanceTests.java +++ b/tests/CoreTests/android/core/JavaPerformanceTests.java @@ -23,7 +23,6 @@ public class JavaPerformanceTests { public static String[] children() { return new String[] { - StringTest.class.getName(), HashMapPerformanceTest.class.getName(), ArrayListPerformanceTest.class.getName(), TreeMapPerformanceTest.class.getName(), diff --git a/tests/CoreTests/android/core/StringTest.java b/tests/CoreTests/android/core/StringTest.java deleted file mode 100644 index 128531c..0000000 --- a/tests/CoreTests/android/core/StringTest.java +++ /dev/null @@ -1,951 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.core; - -import java.util.Locale; - -import android.test.PerformanceTestBase; -import android.test.PerformanceTestCase; - -public class StringTest extends PerformanceTestBase { - public static final int ITERATIONS = 1000; - public static final String STATIC_STRING_01 = "Hello Android"; - public static final String STATIC_STRING_02 = - "Remember, today is the tomorrow you worried about yesterday"; - public static final char[] STATIC_CHAR_ARRAY = - {'N', 'A', 'N', 'D', 'R', 'O', 'I', 'D'}; - public static StringBuffer STATIC_SBUF = new StringBuffer(STATIC_STRING_02); - - @Override - public int startPerformance(PerformanceTestCase.Intermediates intermediates) { - intermediates.setInternalIterations(ITERATIONS); - return 0; - } - - /** Create an empty String object* */ - - public void testStringCreate() { - String rString; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = new String(); - rString = new String(); - rString = new String(); - rString = new String(); - rString = new String(); - rString = new String(); - rString = new String(); - rString = new String(); - rString = new String(); - rString = new String(); - } - } - - /** Create an initialised String object* */ - - public void testStringCreate1() { - String rString, str = STATIC_STRING_01; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = new String(str); - rString = new String(str); - rString = new String(str); - rString = new String(str); - rString = new String(str); - rString = new String(str); - rString = new String(str); - rString = new String(str); - rString = new String(str); - rString = new String(str); // 10 - } - } - - /** equals() with for loop* */ - public void testStringEquals() { - String mString = new String(STATIC_STRING_01); - String str = STATIC_STRING_01; - boolean result; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = mString.equals(str); - result = mString.equals(str); - result = mString.equals(str); - result = mString.equals(str); - result = mString.equals(str); - result = mString.equals(str); - result = mString.equals(str); - result = mString.equals(str); - result = mString.equals(str); - result = mString.equals(str); - } - } - - /** - * ContentEquals- Comparing the content of a String with that of a String - * Buffer* - */ - - public void testStringContentEquals() { - StringBuffer sBuf = new StringBuffer(STATIC_STRING_01); - String str = STATIC_STRING_01; - boolean result; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - result = str.contentEquals(sBuf); - } - } - - /** Compare string objects lexicographically using compareTo() with for loop* */ - - public void testStringCompareTo() { - String str1 = new String(STATIC_STRING_01); - String str2 = STATIC_STRING_01; - int result; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = str1.compareTo(str2); - result = str1.compareTo(str2); - result = str1.compareTo(str2); - result = str1.compareTo(str2); - result = str1.compareTo(str2); - result = str1.compareTo(str2); - result = str1.compareTo(str2); - result = str1.compareTo(str2); - result = str1.compareTo(str2); - result = str1.compareTo(str2); - } - - } - - /** Compare string objects using compareToIgnorecase() with for loop* */ - - public void testStringCompareToIgnoreCase() { - String mString = new String(STATIC_STRING_01); - String str2 = STATIC_STRING_01; - int result; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - result = mString.compareToIgnoreCase(str2); - } - } - - /** startsWith * */ - - public void testStringstartsWith() { - boolean result; - String str1 = STATIC_STRING_02, str2 = "Rem"; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = str1.startsWith(str2); - result = str1.startsWith(str2); - result = str1.startsWith(str2); - result = str1.startsWith(str2); - result = str1.startsWith(str2); - result = str1.startsWith(str2); - result = str1.startsWith(str2); - result = str1.startsWith(str2); - result = str1.startsWith(str2); - result = str1.startsWith(str2); - } - } - - /** startsWith(String seq, int begin) * */ - - public void testStringstartsWith1() { - String str1 = STATIC_STRING_02, str2 = "tom"; - int pos = 10; - boolean result; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - result = str1.startsWith(str2, pos); - } - } - - /** endsWith * */ - - public void testStringendsWith() { - String str = STATIC_STRING_02, str1 = "day"; - boolean result; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = str.endsWith(str1); - result = str.endsWith(str1); - result = str.endsWith(str1); - result = str.endsWith(str1); - result = str.endsWith(str1); - result = str.endsWith(str1); - result = str.endsWith(str1); - result = str.endsWith(str1); - result = str.endsWith(str1); - result = str.endsWith(str1); - } - } - - /** - * indexOf to determine whether a string contains a substring - */ - public void testStringindexOf() { - boolean result; - String str = STATIC_STRING_02, str1 = "tomo"; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - result = str.indexOf(str1) > 0; - } - } - - /** indexOf()* */ - - public void testStringindexOf1() { - int index; - String str = STATIC_STRING_02; - char c = 't'; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = str.indexOf(c); - index = str.indexOf(c); - index = str.indexOf(c); - index = str.indexOf(c); - index = str.indexOf(c); - index = str.indexOf(c); - index = str.indexOf(c); - index = str.indexOf(c); - index = str.indexOf(c); - index = str.indexOf(c); - } - - } - - /** indexOf(char c, int start)* */ - public void testStringindexOf2() { - int index, pos = 12; - String str = STATIC_STRING_02, str1 = "tom"; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - index = str.indexOf(str1, pos); - } - } - - /** lastIndexOf()* */ - - public void testStringlastIndexOf() { - int index; - char c = 't'; - String str = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - index = str.lastIndexOf(c); - } - } - - /** lastIndexOf()* */ - - public void testStringlastIndexOf1() { - int index, pos = 36; - String str = STATIC_STRING_02, str1 = "tom"; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - index = str.lastIndexOf(str1, pos); - } - } - - /** - * contains() to determine whether a string contains a substring - */ - - public void testStringcontains() { - boolean result; - String str = STATIC_STRING_02, str1 = "tomo"; - for (int i = ITERATIONS - 1; i >= 0; i--) { - result = str.contains(str1); - result = str.contains(str1); - result = str.contains(str1); - result = str.contains(str1); - result = str.contains(str1); - result = str.contains(str1); - result = str.contains(str1); - result = str.contains(str1); - result = str.contains(str1); - result = str.contains(str1); - } - } - - /** substring(int start) */ - - public void testStringsubstring() { - String rString; - String str = STATIC_STRING_02; - int index = 10; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = str.substring(index); - rString = str.substring(index); - rString = str.substring(index); - rString = str.substring(index); - rString = str.substring(index); - rString = str.substring(index); - rString = str.substring(index); - rString = str.substring(index); - rString = str.substring(index); - rString = str.substring(index); - } - } - - /** substring(int start, int end) in a for loop* */ - - public void testStringsubstring1() { - String rString; - String str = STATIC_STRING_02; - int start = 10, end = 48; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = str.substring(start, end); - rString = str.substring(start, end); - rString = str.substring(start, end); - rString = str.substring(start, end); - rString = str.substring(start, end); - rString = str.substring(start, end); - rString = str.substring(start, end); - rString = str.substring(start, end); - rString = str.substring(start, end); - rString = str.substring(start, end); - } - } - - /** - * valueOf(char[] cArray) String representation of a character array - */ - public void testStringvalueOf() { - String rString; - char[] cArray = STATIC_CHAR_ARRAY; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - rString = String.valueOf(cArray); - } - } - - /** valueOf(char[] cArray, int offset, int count)* */ - - public void testStringvalueOf1() { - String rString; - char[] cArray = STATIC_CHAR_ARRAY; - int start = 1, end = 7; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - rString = String.valueOf(cArray, start, end); - } - } - - /** Convert a string to a char Array* */ - - public void testStringtoCharArray() { - char[] cArray; - String str = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - cArray = str.toCharArray(); - cArray = str.toCharArray(); - cArray = str.toCharArray(); - cArray = str.toCharArray(); - cArray = str.toCharArray(); - cArray = str.toCharArray(); - cArray = str.toCharArray(); - cArray = str.toCharArray(); - cArray = str.toCharArray(); - cArray = str.toCharArray(); - } - } - - /** length()* */ - - public void testStringlength() { - int len; - String str = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - len = str.length(); - len = str.length(); - len = str.length(); - len = str.length(); - len = str.length(); - len = str.length(); - len = str.length(); - len = str.length(); - len = str.length(); - len = str.length(); - } - } - - /** hashcode()* */ - - public void testStringhashCode() { - int index; - String str = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = str.hashCode(); - index = str.hashCode(); - index = str.hashCode(); - index = str.hashCode(); - index = str.hashCode(); - index = str.hashCode(); - index = str.hashCode(); - index = str.hashCode(); - index = str.hashCode(); - index = str.hashCode(); - } - } - - /** replace()* */ - - public void testStringreplace() { - String rString; - String str = STATIC_STRING_02; - char c1 = ' ', c2 = ' '; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - rString = str.replace(c1, c2); - } - } - - public void testStringreplaceAll() { - String rString; - String str = STATIC_STRING_02, str1 = " ", str2 = "/"; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - rString = str.replaceAll(str1, str2); - } - } - - /** Convert a StringBuffer to a String* */ - - public void testStringtoString() { - StringBuffer sBuf = new StringBuffer(STATIC_STRING_02); - - String rString; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = sBuf.toString(); - rString = sBuf.toString(); - rString = sBuf.toString(); - rString = sBuf.toString(); - rString = sBuf.toString(); - rString = sBuf.toString(); - rString = sBuf.toString(); - rString = sBuf.toString(); - rString = sBuf.toString(); - rString = sBuf.toString(); - } - } - - /** Split a string into an array of strings* */ - - public void testStringsplit() { - String[] strings; - String str1 = STATIC_STRING_02, str = " "; - for (int i = ITERATIONS - 1; i >= 0; i--) { - strings = str1.split(str); - strings = str1.split(str); - strings = str1.split(str); - strings = str1.split(str); - strings = str1.split(str); - strings = str1.split(str); - strings = str1.split(str); - strings = str1.split(str); - strings = str1.split(str); - strings = str1.split(str); - - } - } - - /** Split a string into an array of strings* */ - - public void testStringsplit1() { - String str = STATIC_STRING_02, str1 = " "; - String[] strings; - int pos = 8; - for (int i = ITERATIONS - 1; i >= 0; i--) { - strings = str.split(str1, pos); - strings = str.split(str1, pos); - strings = str.split(str1, pos); - strings = str.split(str1, pos); - strings = str.split(str1, pos); - strings = str.split(str1, pos); - strings = str.split(str1, pos); - strings = str.split(str1, pos); - strings = str.split(str1, pos); - strings = str.split(str1, pos); - } - } - - public void testStringgetBytes() { - byte[] bytes; - String str = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - bytes = str.getBytes(); - bytes = str.getBytes(); - bytes = str.getBytes(); - bytes = str.getBytes(); - bytes = str.getBytes(); - bytes = str.getBytes(); - bytes = str.getBytes(); - bytes = str.getBytes(); - bytes = str.getBytes(); - bytes = str.getBytes(); - } - } - - /** copyValueOf(char[] data) * */ - - public void testStringcopyValueOf() { - String rString; - char[] cArray = STATIC_CHAR_ARRAY; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - rString = String.copyValueOf(cArray); - } - } - - /** copyValueOf(char[] data, int index, int count)* */ - - public void testStringcopyValueOf1() { - String rString; - int start = 1, end = 7; - char[] cArray = STATIC_CHAR_ARRAY; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - rString = String.copyValueOf(cArray, start, end); - } - } - - /** trim()* */ - - public void testStringtrim() { - String mString = - new String( - " HELLO ANDROID "); - String rString; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = mString.trim(); - rString = mString.trim(); - rString = mString.trim(); - rString = mString.trim(); - rString = mString.trim(); - rString = mString.trim(); - rString = mString.trim(); - rString = mString.trim(); - rString = mString.trim(); - rString = mString.trim(); - } - } - - /** getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)* */ - - public void testStringgetChars() { - char[] cArray = STATIC_CHAR_ARRAY; - String str = STATIC_STRING_01; - int value1 = 7, value2 = 12, value3 = 1; - for (int i = ITERATIONS - 1; i >= 0; i--) { - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - str.getChars(value1, value2, cArray, value3); - } - } - - /** toUpperCase()* */ - - public void testStringtoUpperCase() { - String rString, str = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = str.toUpperCase(); - rString = str.toUpperCase(); - rString = str.toUpperCase(); - rString = str.toUpperCase(); - rString = str.toUpperCase(); - rString = str.toUpperCase(); - rString = str.toUpperCase(); - rString = str.toUpperCase(); - rString = str.toUpperCase(); - rString = str.toUpperCase(); - } - } - - /** toUpperCase() with locale* */ - - public void testStringtoUpperCase1() { - Locale locale = new Locale("tr"); - String str = STATIC_STRING_02; - String rString; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - rString = str.toUpperCase(locale); - } - } - - /** toLowerCase* */ - - public void StringtoLowerCase() { - String rString, str = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = str.toLowerCase(); - rString = str.toLowerCase(); - rString = str.toLowerCase(); - rString = str.toLowerCase(); - rString = str.toLowerCase(); - rString = str.toLowerCase(); - rString = str.toLowerCase(); - rString = str.toLowerCase(); - rString = str.toLowerCase(); - rString = str.toLowerCase(); - } - } - - /** toLowerCase with locale* */ - - public void testStringtoLowerCase1() { - Locale locale = new Locale("tr"); - String rString, str = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - rString = str.toLowerCase(locale); - } - } - - /** charAt()* */ - - public void testStringcharAt() { - String str = STATIC_STRING_02; - int index, pos = 21; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = str.charAt(pos); - index = str.charAt(pos); - index = str.charAt(pos); - index = str.charAt(pos); - index = str.charAt(pos); - index = str.charAt(pos); - index = str.charAt(pos); - index = str.charAt(pos); - index = str.charAt(pos); - index = str.charAt(pos); - } - } - - public void testStringConcat() { - String mString, str1 = STATIC_STRING_01, str2 = STATIC_STRING_02; - for (int i = ITERATIONS - 1; i >= 0; i--) { - mString = str1.concat(str2); - mString = str1.concat(str2); - mString = str1.concat(str2); - mString = str1.concat(str2); - mString = str1.concat(str2); - mString = str1.concat(str2); - mString = str1.concat(str2); - mString = str1.concat(str2); - mString = str1.concat(str2); - mString = str1.concat(str2); - } - } - - public void testStringBufferAppend() { - StringBuffer sBuf = new StringBuffer(" "); - for (int i = ITERATIONS - 1; i >= 0; i--) { - sBuf.append(i); - sBuf.append(i); - sBuf.append(i); - sBuf.append(i); - sBuf.append(i); - sBuf.append(i); - sBuf.append(i); - sBuf.append(i); - sBuf.append(i); - sBuf.append(i); - } - } - - public void testStringBufferInsert() { - StringBuffer sBuf = new StringBuffer(" "); - int index = sBuf.length(); - for (int i = ITERATIONS - 1; i >= 0; i--) { - sBuf.insert(index, i); - sBuf.insert(index, i); - sBuf.insert(index, i); - sBuf.insert(index, i); - sBuf.insert(index, i); - sBuf.insert(index, i); - sBuf.insert(index, i); - sBuf.insert(index, i); - sBuf.insert(index, i); - sBuf.insert(index, i); - } - } - - public void testStringBufferReverse() { - StringBuffer sBuf = STATIC_SBUF; - for (int i = ITERATIONS - 1; i >= 0; i--) { - sBuf.reverse(); - sBuf.reverse(); - sBuf.reverse(); - sBuf.reverse(); - sBuf.reverse(); - sBuf.reverse(); - sBuf.reverse(); - sBuf.reverse(); - sBuf.reverse(); - sBuf.reverse(); - } - } - - public void testStringBufferSubstring() { - StringBuffer sBuf = STATIC_SBUF; - String rString; - int index = 0; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = sBuf.substring(index); - rString = sBuf.substring(index); - rString = sBuf.substring(index); - rString = sBuf.substring(index); - rString = sBuf.substring(index); - rString = sBuf.substring(index); - rString = sBuf.substring(index); - rString = sBuf.substring(index); - rString = sBuf.substring(index); - rString = sBuf.substring(index); - } - } - - public void testStringBufferSubstring1() { - StringBuffer sBuf = STATIC_SBUF; - String rString; - int start = 5, end = 25; - for (int i = ITERATIONS - 1; i >= 0; i--) { - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - rString = sBuf.substring(start, end); - } - } - - public void testStringBufferReplace() { - StringBuffer sBuf = STATIC_SBUF; - int start = 3, end = 6; - String str = "ind"; - for (int i = ITERATIONS - 1; i >= 0; i--) { - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - sBuf.replace(start, end, str); - } - } - - public void testStringBufferIndexOf() { - StringBuffer sBuf = STATIC_SBUF; - String str = "t"; - int index; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - index = sBuf.indexOf(str); - } - } - - public void testStringBufferIndexOf1() { - StringBuffer sBuf = STATIC_SBUF; - String str = "tom"; - int index, pos = 12; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - index = sBuf.indexOf(str, pos); - } - - } - - public void testStringBufferLastIndexOf() { - StringBuffer sBuf = STATIC_SBUF; - String str = "t"; - int index; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - index = sBuf.lastIndexOf(str); - } - } - - public void testStringBufferLastIndexOf1() { - StringBuffer sBuf = STATIC_SBUF; - int index, pos = 36; - String str = "tom"; - for (int i = ITERATIONS - 1; i >= 0; i--) { - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - index = sBuf.lastIndexOf(str, pos); - } - } -} diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk index b339a2c..094b7db 100644 --- a/tools/aapt/Android.mk +++ b/tools/aapt/Android.mk @@ -41,7 +41,7 @@ LOCAL_STATIC_LIBRARIES := \ libpng ifeq ($(HOST_OS),linux) -LOCAL_LDLIBS += -lrt +LOCAL_LDLIBS += -lrt -lpthread endif # Statically link libz for MinGW (Win SDK under Linux), diff --git a/tools/localize/Android.mk b/tools/localize/Android.mk index ab79f8d..f284e86 100644 --- a/tools/localize/Android.mk +++ b/tools/localize/Android.mk @@ -34,7 +34,7 @@ LOCAL_STATIC_LIBRARIES := \ libcutils ifeq ($(HOST_OS),linux) -LOCAL_LDLIBS += -lrt +LOCAL_LDLIBS += -lrt -lpthread endif diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java index e71c293..ec8d0ed 100644 --- a/voip/java/android/net/sip/SipProfile.java +++ b/voip/java/android/net/sip/SipProfile.java @@ -35,7 +35,7 @@ import javax.sip.address.URI; * Class containing a SIP account, domain and server information. * @hide */ -public class SipProfile implements Parcelable, Serializable { +public class SipProfile implements Parcelable, Serializable, Cloneable { private static final long serialVersionUID = 1L; private static final int DEFAULT_PORT = 5060; private Address mAddress; @@ -46,6 +46,7 @@ public class SipProfile implements Parcelable, Serializable { private String mProfileName; private boolean mSendKeepAlive = false; private boolean mAutoRegistration = true; + private boolean mAllowOutgoingCall = false; /** @hide */ public static final Parcelable.Creator<SipProfile> CREATOR = @@ -79,6 +80,23 @@ public class SipProfile implements Parcelable, Serializable { } /** + * Creates a builder based on the given profile. + */ + public Builder(SipProfile profile) { + if (profile == null) throw new NullPointerException(); + try { + mProfile = (SipProfile) profile.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException("should not occur", e); + } + mProfile.mAddress = null; + mUri = profile.getUri(); + mUri.setUserPassword(profile.getPassword()); + mDisplayName = profile.getDisplayName(); + mProxyAddress = profile.getProxyAddress(); + } + + /** * Constructor. * * @param uriString the URI string as "sip:<user_name>@<domain>" @@ -226,6 +244,18 @@ public class SipProfile implements Parcelable, Serializable { } /** + * Sets the allow-outgoing-call flag. + * + * @param flag true if allowing to make outgoing call on the profile; + * false otherwise + * @return this builder object + */ + public Builder setOutgoingCallAllowed(boolean flag) { + mProfile.mAllowOutgoingCall = flag; + return this; + } + + /** * Builds and returns the SIP profile object. * * @return the profile object created @@ -262,6 +292,7 @@ public class SipProfile implements Parcelable, Serializable { mProfileName = in.readString(); mSendKeepAlive = (in.readInt() == 0) ? false : true; mAutoRegistration = (in.readInt() == 0) ? false : true; + mAllowOutgoingCall = (in.readInt() == 0) ? false : true; } /** @hide */ @@ -274,6 +305,7 @@ public class SipProfile implements Parcelable, Serializable { out.writeString(mProfileName); out.writeInt(mSendKeepAlive ? 1 : 0); out.writeInt(mAutoRegistration ? 1 : 0); + out.writeInt(mAllowOutgoingCall ? 1 : 0); } /** @hide */ @@ -398,4 +430,11 @@ public class SipProfile implements Parcelable, Serializable { public boolean getAutoRegistration() { return mAutoRegistration; } + + /** + * Returns true if allowing to make outgoing calls on this profile. + */ + public boolean isOutgoingCallAllowed() { + return mAllowOutgoingCall; + } } |