diff options
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/app/Activity.java | 2 | ||||
-rw-r--r-- | core/java/android/app/Service.java | 10 | ||||
-rw-r--r-- | core/java/android/content/ContentProvider.java | 178 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 1 | ||||
-rw-r--r-- | core/java/android/database/sqlite/SQLiteOpenHelper.java | 39 | ||||
-rw-r--r-- | core/java/android/net/DownloadManager.java | 2 | ||||
-rw-r--r-- | core/java/android/net/NetworkInfo.java | 126 | ||||
-rw-r--r-- | core/java/android/os/StrictMode.java | 2 |
8 files changed, 242 insertions, 118 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 61fd5f3..142c325 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2059,7 +2059,7 @@ public class Activity extends ContextThemeWrapper * removed. Otherwise, all entries up to but not including that entry * will be removed */ - static final int POP_BACK_STACK_INCLUSIVE = 1<<0; + public static final int POP_BACK_STACK_INCLUSIVE = 1<<0; /** * Pop the top state off the back stack. Returns true if there was one diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 697a987..b7a750b 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -400,7 +400,15 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac * * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java * start_compatibility} - * + * + * <p class="caution">Note that the system calls this on your + * service's main thread. A service's main thread is the same + * thread where UI operations place for Activities running in the + * same process. You should always avoid stalling the main + * thread's event loop. When doing long-running operations, + * network calls, or heavy disk I/O, you should kick off a new + * thread, or use {@link android.os.AsyncTask}.</p> + * * @param intent The Intent supplied to {@link android.content.Context#startService}, * as given. This may be null if the service is being restarted after * its process has gone away, and it had previously returned anything diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 5fb2aae..40108c3 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -57,6 +57,7 @@ import java.util.ArrayList; * * <p>The primary methods that need to be implemented are: * <ul> + * <li>{@link #onCreate} which is called to initialize the provider</li> * <li>{@link #query} which returns data to the caller</li> * <li>{@link #insert} which inserts new data into the content provider</li> * <li>{@link #update} which updates existing data in the content provider</li> @@ -64,8 +65,15 @@ import java.util.ArrayList; * <li>{@link #getType} which returns the MIME type of data in the content provider</li> * </ul></p> * - * <p>This class takes care of cross process calls so subclasses don't have to worry about which - * process a request is coming from.</p> + * <p class="caution">Data access methods (such as {@link #insert} and + * {@link #update}) may be called from many threads at once, and must be thread-safe. + * Other methods (such as {@link #onCreate}) are only called from the application + * main thread, and must avoid performing lengthy operations. See the method + * descriptions for their expected thread behavior.</p> + * + * <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate + * ContentProvider instance, so subclasses don't have to worry about the details of + * cross-process calls.</p> */ public abstract class ContentProvider implements ComponentCallbacks { /* @@ -81,6 +89,21 @@ public abstract class ContentProvider implements ComponentCallbacks { private Transport mTransport = new Transport(); + /** + * Construct a ContentProvider instance. Content providers must be + * <a href="{@docRoot}guide/topics/manifest/provider-element.html">declared + * in the manifest</a>, accessed with {@link ContentResolver}, and created + * automatically by the system, so applications usually do not create + * ContentProvider instances directly. + * + * <p>At construction time, the object is uninitialized, and most fields and + * methods are unavailable. Subclasses should initialize themselves in + * {@link #onCreate}, not the constructor. + * + * <p>Content providers are created on the application main thread at + * application launch time. The constructor must not perform lengthy + * operations, or application startup will be delayed. + */ public ContentProvider() { } @@ -328,8 +351,8 @@ public abstract class ContentProvider implements ComponentCallbacks { /** - * Retrieve the Context this provider is running in. Only available once - * onCreate(Map icicle) has been called -- this will be null in the + * Retrieves the Context this provider is running in. Only available once + * {@link #onCreate} has been called -- this will return null in the * constructor. */ public final Context getContext() { @@ -403,23 +426,59 @@ public abstract class ContentProvider implements ComponentCallbacks { } /** - * Called when the provider is being started. + * Implement this to initialize your content provider on startup. + * This method is called for all registered content providers on the + * application main thread at application launch time. It must not perform + * lengthy operations, or application startup will be delayed. + * + * <p>You should defer nontrivial initialization (such as opening, + * upgrading, and scanning databases) until the content provider is used + * (via {@link #query}, {@link #insert}, etc). Deferred initialization + * keeps application startup fast, avoids unnecessary work if the provider + * turns out not to be needed, and stops database errors (such as a full + * disk) from halting application launch. + * + * <p>For SQL databases, {@link android.database.sqlite.SQLiteOpenHelper} + * is a helpful utility class that makes it easy to manage databases, + * and will automatically defer opening until first use. If you do use + * SQLiteOpenHelper, make sure to avoid calling + * {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase} or + * {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} + * from this method. (Instead, override + * {@link android.database.sqlite.SQLiteOpenHelper#onOpen} to initialize the + * database when it is first opened.) * * @return true if the provider was successfully loaded, false otherwise */ public abstract boolean onCreate(); + /** + * {@inheritDoc} + * This method is always called on the application main thread, and must + * not perform lengthy operations. + * + * <p>The default content provider implementation does nothing. + * Override this method to take appropriate action. + * (Content providers do not usually care about things like screen + * orientation, but may want to know about locale changes.) + */ public void onConfigurationChanged(Configuration newConfig) { } - + + /** + * {@inheritDoc} + * This method is always called on the application main thread, and must + * not perform lengthy operations. + * + * <p>The default content provider implementation does nothing. + * Subclasses may override this method to take appropriate action. + */ public void onLowMemory() { } /** - * Receives a query request from a client in a local process, and - * returns a Cursor. This is called internally by the {@link ContentResolver}. - * This method can be called from multiple - * threads, as described in + * Implement this to handle query requests from clients. + * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: * Processes and Threads</a>. * <p> @@ -476,11 +535,11 @@ public abstract class ContentProvider implements ComponentCallbacks { String selection, String[] selectionArgs, String sortOrder); /** - * Return the MIME type of the data at the given URI. This should start with + * Implement this to handle requests for the MIME type of the data at the + * given URI. The returned MIME type should start with * <code>vnd.android.cursor.item</code> for a single record, * or <code>vnd.android.cursor.dir/</code> for multiple items. - * This method can be called from multiple - * threads, as described in + * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: * Processes and Threads</a>. * @@ -490,11 +549,10 @@ public abstract class ContentProvider implements ComponentCallbacks { public abstract String getType(Uri uri); /** - * Implement this to insert a new row. + * Implement this to handle requests to insert a new row. * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} * after inserting. - * This method can be called from multiple - * threads, as described in + * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: * Processes and Threads</a>. * @param uri The content:// URI of the insertion request. @@ -504,12 +562,12 @@ public abstract class ContentProvider implements ComponentCallbacks { public abstract Uri insert(Uri uri, ContentValues values); /** - * Implement this to insert a set of new rows, or the default implementation will - * iterate over the values and call {@link #insert} on each of them. + * Override this to handle requests to insert a set of new rows, or the + * default implementation will iterate over the values and call + * {@link #insert} on each of them. * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} * after inserting. - * This method can be called from multiple - * threads, as described in + * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: * Processes and Threads</a>. * @@ -526,13 +584,12 @@ public abstract class ContentProvider implements ComponentCallbacks { } /** - * A request to delete one or more rows. The selection clause is applied when performing - * the deletion, allowing the operation to affect multiple rows in a - * directory. + * Implement this to handle requests to delete one or more rows. + * The implementation should apply the selection clause when performing + * deletion, allowing the operation to affect multiple rows in a directory. * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()} * after deleting. - * This method can be called from multiple - * threads, as described in + * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: * Processes and Threads</a>. * @@ -549,13 +606,12 @@ public abstract class ContentProvider implements ComponentCallbacks { public abstract int delete(Uri uri, String selection, String[] selectionArgs); /** - * Update a content URI. All rows matching the optionally provided selection - * will have their columns listed as the keys in the values map with the - * values of those keys. + * Implement this to update one or more rows. + * The implementation should update all rows matching the selection + * to set the columns according to the provided values map. * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} * after updating. - * This method can be called from multiple - * threads, as described in + * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: * Processes and Threads</a>. * @@ -570,18 +626,15 @@ public abstract class ContentProvider implements ComponentCallbacks { String[] selectionArgs); /** - * Open a file blob associated with a content URI. - * This method can be called from multiple - * threads, as described in + * Override this to open a file blob associated with a content URI. + * The default implementation always throws {@link FileNotFoundException}. + * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: * Processes and Threads</a>. - * - * <p>Returns a - * ParcelFileDescriptor, from which you can obtain a - * {@link java.io.FileDescriptor} for use with - * {@link java.io.FileInputStream}, {@link java.io.FileOutputStream}, etc. - * This can be used to store large data (such as an image) associated with - * a particular piece of content. + * + * <p>Returns a ParcelFileDescriptor, which is returned directly to the + * caller. This way large data (such as images and documents) can be + * returned without copying the content. * * <p>The returned ParcelFileDescriptor is owned by the caller, so it is * their responsibility to close it when done. That is, the implementation @@ -599,31 +652,35 @@ public abstract class ContentProvider implements ComponentCallbacks { * no file associated with the given URI or the mode is invalid. * @throws SecurityException Throws SecurityException if the caller does * not have permission to access the file. - * + * * @see #openAssetFile(Uri, String) * @see #openFileHelper(Uri, String) - */ + */ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { throw new FileNotFoundException("No files supported by provider at " + uri); } - + /** * This is like {@link #openFile}, but can be implemented by providers * that need to be able to return sub-sections of files, often assets - * inside of their .apk. Note that when implementing this your clients - * must be able to deal with such files, either directly with - * {@link ContentResolver#openAssetFileDescriptor - * ContentResolver.openAssetFileDescriptor}, or by using the higher-level + * inside of their .apk. + * This method can be called from multiple threads, as described in + * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: + * Processes and Threads</a>. + * + * <p>If you implement this, your clients must be able to deal with such + * files, either directly with + * {@link ContentResolver#openAssetFileDescriptor}, or by using the higher-level * {@link ContentResolver#openInputStream ContentResolver.openInputStream} * or {@link ContentResolver#openOutputStream ContentResolver.openOutputStream} * methods. - * - * <p><em>Note: if you are implementing this to return a full file, you + * + * <p class="note">If you are implementing this to return a full file, you * should create the AssetFileDescriptor with * {@link AssetFileDescriptor#UNKNOWN_LENGTH} to be compatible with - * applications that can not handle sub-sections of files.</em></p> + * applications that can not handle sub-sections of files.</p> * * @param uri The URI whose file is to be opened. * @param mode Access mode for the file. May be "r" for read-only access, @@ -735,17 +792,20 @@ public abstract class ContentProvider implements ComponentCallbacks { } /** - * Applies each of the {@link ContentProviderOperation} objects and returns an array - * of their results. Passes through OperationApplicationException, which may be thrown - * by the call to {@link ContentProviderOperation#apply}. - * If all the applications succeed then a {@link ContentProviderResult} array with the - * same number of elements as the operations will be returned. It is implementation-specific - * how many, if any, operations will have been successfully applied if a call to - * apply results in a {@link OperationApplicationException}. + * Override this to perform a batch of operations, or the default + * implementation will {@link ContentProviderOperation#apply} each of the + * {@link ContentProviderOperation} objects. If the apply calls all succeed + * then a {@link ContentProviderResult} array with the same number of + * elements as the operations will be returned. If any of the apply calls + * fail, it is up to the implementation how many of the others take effect. + * This method can be called from multiple threads, as described in + * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: + * Processes and Threads</a>. + * * @param operations the operations to apply * @return the results of the applications - * @throws OperationApplicationException thrown if an application fails. - * See {@link ContentProviderOperation#apply} for more information. + * @throws OperationApplicationException thrown if any operation fails. + * @see ContentProviderOperation#apply */ public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) throws OperationApplicationException { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 3d64984..b5ec633 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1566,7 +1566,6 @@ public abstract class Context { * {@link android.net.DownloadManager} for requesting HTTP downloads. * * @see #getSystemService - * @hide (TODO) for now */ public static final String DOWNLOAD_SERVICE = "download"; diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java index 0f2e872..d8cce21 100644 --- a/core/java/android/database/sqlite/SQLiteOpenHelper.java +++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java @@ -24,10 +24,16 @@ import android.util.Log; /** * A helper class to manage database creation and version management. - * You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and + * + * <p>You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and * optionally {@link #onOpen}, and this class takes care of opening the database * if it exists, creating it if it does not, and upgrading it as necessary. * Transactions are used to make sure the database is always in a sensible state. + * + * <p>This class makes it easy for {@link android.content.ContentProvider} + * implementations to defer opening and upgrading the database until first use, + * to avoid blocking application startup with long-running database upgrades. + * * <p>For an example, see the NotePadProvider class in the NotePad sample application, * in the <em>samples/</em> directory of the SDK.</p> * @@ -51,8 +57,9 @@ public abstract class SQLiteOpenHelper { /** * Create a helper object to create, open, and/or manage a database. - * The database is not actually created or opened until one of - * {@link #getWritableDatabase} or {@link #getReadableDatabase} is called. + * This method always returns very quickly. The database is not actually + * created or opened until one of {@link #getWritableDatabase} or + * {@link #getReadableDatabase} is called. * * @param context to use to open or create the database * @param name of the database file, or null for an in-memory database @@ -96,13 +103,20 @@ public abstract class SQLiteOpenHelper { /** * Create and/or open a database that will be used for reading and writing. - * Once opened successfully, the database is cached, so you can call this - * method every time you need to write to the database. Make sure to call - * {@link #close} when you no longer need it. + * The first time this is called, the database will be opened and + * {@link #onCreate}, {@link #onUpgrade} and/or {@link #onOpen} will be + * called. * - * <p>Errors such as bad permissions or a full disk may cause this operation + * <p>Once opened successfully, the database is cached, so you can + * call this method every time you need to write to the database. + * (Make sure to call {@link #close} when you no longer need the database.) + * Errors such as bad permissions or a full disk may cause this method * to fail, but future attempts may succeed if the problem is fixed.</p> * + * <p class="caution">Database upgrade may take a long time, you + * should not call this method from the application main thread, including + * from {@link android.content.ContentProvider#onCreate ContentProvider.onCreate()}. + * * @throws SQLiteException if the database cannot be opened for writing * @return a read/write database object valid until {@link #close} is called */ @@ -183,6 +197,11 @@ public abstract class SQLiteOpenHelper { * database object will be closed and the read/write object will be returned * in the future. * + * <p class="caution">Like {@link #getWritableDatabase}, this method may + * take a long time to return, so you should not call it from the + * application main thread, including from + * {@link android.content.ContentProvider#onCreate ContentProvider.onCreate()}. + * * @throws SQLiteException if the database cannot be opened * @return a database object valid until {@link #getWritableDatabase} * or {@link #close} is called. @@ -262,9 +281,9 @@ public abstract class SQLiteOpenHelper { public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion); /** - * Called when the database has been opened. - * Override method should check {@link SQLiteDatabase#isReadOnly} before - * updating the database. + * Called when the database has been opened. The implementation + * should check {@link SQLiteDatabase#isReadOnly} before updating the + * database. * * @param db The database. */ diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java index 455bd36..1d88c18 100644 --- a/core/java/android/net/DownloadManager.java +++ b/core/java/android/net/DownloadManager.java @@ -42,8 +42,6 @@ import java.util.Set; * Instances of this class should be obtained through * {@link android.content.Context#getSystemService(String)} by passing * {@link android.content.Context#DOWNLOAD_SERVICE}. - * - * @hide */ public class DownloadManager { /** diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java index 21f711c..5f5e11c 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/core/java/android/net/NetworkInfo.java @@ -97,7 +97,7 @@ public class NetworkInfo implements Parcelable { stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED); stateMap.put(DetailedState.FAILED, State.DISCONNECTED); } - + private int mNetworkType; private int mSubtype; private String mTypeName; @@ -144,7 +144,9 @@ public class NetworkInfo implements Parcelable { * @return the network type */ public int getType() { - return mNetworkType; + synchronized (this) { + return mNetworkType; + } } /** @@ -153,12 +155,16 @@ public class NetworkInfo implements Parcelable { * @return the network subtype */ public int getSubtype() { - return mSubtype; + synchronized (this) { + return mSubtype; + } } void setSubtype(int subtype, String subtypeName) { - mSubtype = subtype; - mSubtypeName = subtypeName; + synchronized (this) { + mSubtype = subtype; + mSubtypeName = subtypeName; + } } /** @@ -167,7 +173,9 @@ public class NetworkInfo implements Parcelable { * @return the name of the network type */ public String getTypeName() { - return mTypeName; + synchronized (this) { + return mTypeName; + } } /** @@ -175,7 +183,9 @@ public class NetworkInfo implements Parcelable { * @return the name of the network subtype */ public String getSubtypeName() { - return mSubtypeName; + synchronized (this) { + return mSubtypeName; + } } /** @@ -188,7 +198,9 @@ public class NetworkInfo implements Parcelable { * of being established, {@code false} otherwise. */ public boolean isConnectedOrConnecting() { - return mState == State.CONNECTED || mState == State.CONNECTING; + synchronized (this) { + return mState == State.CONNECTED || mState == State.CONNECTING; + } } /** @@ -197,7 +209,9 @@ public class NetworkInfo implements Parcelable { * @return {@code true} if network connectivity exists, {@code false} otherwise. */ public boolean isConnected() { - return mState == State.CONNECTED; + synchronized (this) { + return mState == State.CONNECTED; + } } /** @@ -213,7 +227,9 @@ public class NetworkInfo implements Parcelable { * @return {@code true} if the network is available, {@code false} otherwise */ public boolean isAvailable() { - return mIsAvailable; + synchronized (this) { + return mIsAvailable; + } } /** @@ -223,7 +239,9 @@ public class NetworkInfo implements Parcelable { * @hide */ public void setIsAvailable(boolean isAvailable) { - mIsAvailable = isAvailable; + synchronized (this) { + mIsAvailable = isAvailable; + } } /** @@ -234,7 +252,9 @@ public class NetworkInfo implements Parcelable { * otherwise. */ public boolean isFailover() { - return mIsFailover; + synchronized (this) { + return mIsFailover; + } } /** @@ -244,7 +264,9 @@ public class NetworkInfo implements Parcelable { * @hide */ public void setFailover(boolean isFailover) { - mIsFailover = isFailover; + synchronized (this) { + mIsFailover = isFailover; + } } /** @@ -254,11 +276,15 @@ public class NetworkInfo implements Parcelable { * @return {@code true} if roaming is in effect, {@code false} otherwise. */ public boolean isRoaming() { - return mIsRoaming; + synchronized (this) { + return mIsRoaming; + } } void setRoaming(boolean isRoaming) { - mIsRoaming = isRoaming; + synchronized (this) { + mIsRoaming = isRoaming; + } } /** @@ -266,7 +292,9 @@ public class NetworkInfo implements Parcelable { * @return the coarse-grained state */ public State getState() { - return mState; + synchronized (this) { + return mState; + } } /** @@ -274,7 +302,9 @@ public class NetworkInfo implements Parcelable { * @return the fine-grained state */ public DetailedState getDetailedState() { - return mDetailedState; + synchronized (this) { + return mDetailedState; + } } /** @@ -287,10 +317,12 @@ public class NetworkInfo implements Parcelable { * @hide */ public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) { - this.mDetailedState = detailedState; - this.mState = stateMap.get(detailedState); - this.mReason = reason; - this.mExtraInfo = extraInfo; + synchronized (this) { + this.mDetailedState = detailedState; + this.mState = stateMap.get(detailedState); + this.mReason = reason; + this.mExtraInfo = extraInfo; + } } /** @@ -299,7 +331,9 @@ public class NetworkInfo implements Parcelable { * @return the reason for failure, or null if not available */ public String getReason() { - return mReason; + synchronized (this) { + return mReason; + } } /** @@ -309,20 +343,24 @@ public class NetworkInfo implements Parcelable { * @return the extra information, or null if not available */ public String getExtraInfo() { - return mExtraInfo; + synchronized (this) { + return mExtraInfo; + } } @Override public String toString() { - StringBuilder builder = new StringBuilder("NetworkInfo: "); - builder.append("type: ").append(getTypeName()).append("[").append(getSubtypeName()). - append("], state: ").append(mState).append("/").append(mDetailedState). - append(", reason: ").append(mReason == null ? "(unspecified)" : mReason). - append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo). - append(", roaming: ").append(mIsRoaming). - append(", failover: ").append(mIsFailover). - append(", isAvailable: ").append(mIsAvailable); - return builder.toString(); + synchronized (this) { + StringBuilder builder = new StringBuilder("NetworkInfo: "); + builder.append("type: ").append(getTypeName()).append("[").append(getSubtypeName()). + append("], state: ").append(mState).append("/").append(mDetailedState). + append(", reason: ").append(mReason == null ? "(unspecified)" : mReason). + append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo). + append(", roaming: ").append(mIsRoaming). + append(", failover: ").append(mIsFailover). + append(", isAvailable: ").append(mIsAvailable); + return builder.toString(); + } } /** @@ -338,17 +376,19 @@ public class NetworkInfo implements Parcelable { * @hide */ public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mNetworkType); - dest.writeInt(mSubtype); - dest.writeString(mTypeName); - dest.writeString(mSubtypeName); - dest.writeString(mState.name()); - dest.writeString(mDetailedState.name()); - dest.writeInt(mIsFailover ? 1 : 0); - dest.writeInt(mIsAvailable ? 1 : 0); - dest.writeInt(mIsRoaming ? 1 : 0); - dest.writeString(mReason); - dest.writeString(mExtraInfo); + synchronized (this) { + dest.writeInt(mNetworkType); + dest.writeInt(mSubtype); + dest.writeString(mTypeName); + dest.writeString(mSubtypeName); + dest.writeString(mState.name()); + dest.writeString(mDetailedState.name()); + dest.writeInt(mIsFailover ? 1 : 0); + dest.writeInt(mIsAvailable ? 1 : 0); + dest.writeInt(mIsRoaming ? 1 : 0); + dest.writeString(mReason); + dest.writeString(mExtraInfo); + } } /** diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index dc92590..d4b0500 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -97,7 +97,7 @@ public final class StrictMode { * via Parcel.writeNoException() (amusingly) where the caller can * choose how to react. */ - private static ThreadLocal<ArrayList<ApplicationErrorReport.CrashInfo>> gatheredViolations = + private static final ThreadLocal<ArrayList<ApplicationErrorReport.CrashInfo>> gatheredViolations = new ThreadLocal<ArrayList<ApplicationErrorReport.CrashInfo>>() { @Override protected ArrayList<ApplicationErrorReport.CrashInfo> initialValue() { // Starts null to avoid unnecessary allocations when |