diff options
18 files changed, 279 insertions, 159 deletions
diff --git a/api/current.xml b/api/current.xml index 53f7f1e..7e81eb7 100644 --- a/api/current.xml +++ b/api/current.xml @@ -22817,32 +22817,6 @@ <parameter name="args" type="java.lang.String[]"> </parameter> </method> -<method name="findFragmentById" - return="android.app.Fragment" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="deprecated" - visibility="public" -> -<parameter name="id" type="int"> -</parameter> -</method> -<method name="findFragmentByTag" - return="android.app.Fragment" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="deprecated" - visibility="public" -> -<parameter name="tag" type="java.lang.String"> -</parameter> -</method> <method name="findViewById" return="android.view.View" abstract="false" @@ -24065,17 +24039,6 @@ <parameter name="view" type="android.view.View"> </parameter> </method> -<method name="openFragmentTransaction" - return="android.app.FragmentTransaction" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="deprecated" - visibility="public" -> -</method> <method name="openOptionsMenu" return="void" abstract="false" @@ -43623,6 +43586,30 @@ <parameter name="data" type="D"> </parameter> </method> +<method name="onLoadInBackground" + return="D" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="protected" +> +</method> +<method name="setUpdateThrottle" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="delayMS" type="long"> +</parameter> +</method> <method name="waitForLoader" return="void" abstract="false" @@ -50212,21 +50199,6 @@ <parameter name="cursor" type="android.database.Cursor"> </parameter> </method> -<method name="registerContentObserver" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="cursor" type="android.database.Cursor"> -</parameter> -<parameter name="observer" type="android.database.ContentObserver"> -</parameter> -</method> <method name="setProjection" return="void" abstract="false" @@ -55453,7 +55425,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -55578,7 +55550,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -55600,7 +55572,7 @@ native="false" synchronized="false" static="false" - final="true" + final="false" deprecated="not deprecated" visibility="public" > @@ -68017,6 +67989,21 @@ <parameter name="selectionArgs" type="java.lang.String[]"> </parameter> </method> +<method name="concatenateWhere" + return="java.lang.String" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="a" type="java.lang.String"> +</parameter> +<parameter name="b" type="java.lang.String"> +</parameter> +</method> <method name="createDbFromSqlStatements" return="void" abstract="false" diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 938c47d..ec2f771 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -73,13 +73,11 @@ import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.widget.AdapterView; -import android.widget.FrameLayout; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; /** * An activity is a single, focused thing that the user can do. Almost all @@ -1579,16 +1577,6 @@ public class Activity extends ContextThemeWrapper return mFragments; } - /** - * Start a series of edit operations on the Fragments associated with - * this activity. - * @deprecated use {@link #getFragmentManager}. - */ - @Deprecated - public FragmentTransaction openFragmentTransaction() { - return mFragments.openTransaction(); - } - void invalidateFragmentIndex(int index) { //Log.v(TAG, "invalidateFragmentIndex: index=" + index); if (mAllLoaderManagers != null) { @@ -1770,30 +1758,6 @@ public class Activity extends ContextThemeWrapper } /** - * Finds a fragment that was identified by the given id either when inflated - * from XML or as the container ID when added in a transaction. This only - * returns fragments that are currently added to the activity's content. - * @return The fragment if found or null otherwise. - * @deprecated use {@link #getFragmentManager}. - */ - @Deprecated - public Fragment findFragmentById(int id) { - return mFragments.findFragmentById(id); - } - - /** - * Finds a fragment that was identified by the given tag either when inflated - * from XML or as supplied when added in a transaction. This only - * returns fragments that are currently added to the activity's content. - * @return The fragment if found or null otherwise. - * @deprecated use {@link #getFragmentManager}. - */ - @Deprecated - public Fragment findFragmentByTag(String tag) { - return mFragments.findFragmentByTag(tag); - } - - /** * Set the activity content from a layout resource. The resource will be * inflated, adding all top-level views to the activity. * diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 72f7286..16d3a7f 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -485,6 +485,11 @@ class ContextImpl extends Context { } @Override + public int getThemeResId() { + return mThemeResource; + } + + @Override public Resources.Theme getTheme() { if (mTheme == null) { if (mThemeResource == 0) { diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java index bcd46d9..72a455e 100644 --- a/core/java/android/app/DialogFragment.java +++ b/core/java/android/app/DialogFragment.java @@ -211,7 +211,7 @@ public class DialogFragment extends Fragment */ @Deprecated public void show(Activity activity, String tag) { - FragmentTransaction ft = activity.openFragmentTransaction(); + FragmentTransaction ft = activity.getFragmentManager().openTransaction(); ft.add(this, tag); ft.commit(); } diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index 5aec348..1b8debc 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java @@ -24,8 +24,8 @@ public abstract class FragmentTransaction { * @param fragment The fragment to be added. This fragment must not already * be added to the activity. * @param tag Optional tag name for the fragment, to later retrieve the - * fragment with {@link Activity#findFragmentByTag(String) - * Activity.findFragmentByTag(String)}. + * fragment with {@link FragmentManager#findFragmentByTag(String) + * FragmentManager.findFragmentByTag(String)}. * * @return Returns the same FragmentTransaction instance. */ @@ -47,8 +47,8 @@ public abstract class FragmentTransaction { * to be replaced. * @param fragment The new fragment to place in the container. * @param tag Optional tag name for the fragment, to later retrieve the - * fragment with {@link Activity#findFragmentByTag(String) - * Activity.findFragmentByTag(String)}. + * fragment with {@link FragmentManager#findFragmentByTag(String) + * FragmentManager.findFragmentByTag(String)}. * * @return Returns the same FragmentTransaction instance. */ diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java index 01a2912..ec4e578 100644 --- a/core/java/android/content/AsyncTaskLoader.java +++ b/core/java/android/content/AsyncTaskLoader.java @@ -17,8 +17,13 @@ package android.content; import android.os.AsyncTask; +import android.os.Handler; +import android.os.SystemClock; import android.util.Log; +import android.util.TimeUtils; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.concurrent.ExecutionException; /** @@ -30,14 +35,15 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> { private static final String TAG = "AsyncTaskLoader"; - final class LoadTask extends AsyncTask<Void, Void, D> { + final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable { - private D result; + D result; + boolean waiting; /* Runs on a worker thread */ @Override protected D doInBackground(Void... params) { - result = AsyncTaskLoader.this.loadInBackground(); + result = AsyncTaskLoader.this.onLoadInBackground(); return result; } @@ -49,38 +55,91 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> { @Override protected void onCancelled() { - AsyncTaskLoader.this.onCancelled(result); + AsyncTaskLoader.this.dispatchOnCancelled(this, result); + } + + @Override + public void run() { + waiting = false; + AsyncTaskLoader.this.executePendingTask(); } } volatile LoadTask mTask; + volatile LoadTask mCancellingTask; + + long mUpdateThrottle; + long mLastLoadCompleteTime = -10000; + Handler mHandler; public AsyncTaskLoader(Context context) { super(context); } + /** + * Set amount to throttle updates by. This is the minimum time from + * when the last {@link #onLoadInBackground()} call has completed until + * a new load is scheduled. + * + * @param delayMS Amount of delay, in milliseconds. + */ + public void setUpdateThrottle(long delayMS) { + mUpdateThrottle = delayMS; + if (delayMS != 0) { + mHandler = new Handler(); + } + } + @Override protected void onForceLoad() { super.onForceLoad(); cancelLoad(); mTask = new LoadTask(); - mTask.execute((Void[]) null); + executePendingTask(); } /** * Attempt to cancel the current load task. See {@link AsyncTask#cancel(boolean)} - * for more info. + * for more info. Must be called on the main thread of the process. + * + * <p>Cancelling is not an immediate operation, since the load is performed + * in a background thread. If there is currently a load in progress, this + * method requests that the load be cancelled, and notes this is the case; + * once the background thread has completed its work its remaining state + * will be cleared. If another load request comes in during this time, + * it will be held until the cancelled load is complete. * - * @return <tt>false</tt> if the task could not be canceled, + * @return Returns <tt>false</tt> if the task could not be cancelled, * typically because it has already completed normally, or - * because {@link #startLoading()} hasn't been called, and - * <tt>true</tt> otherwise + * because {@link #startLoading()} hasn't been called; returns + * <tt>true</tt> otherwise. */ public boolean cancelLoad() { if (mTask != null) { - boolean cancelled = mTask.cancel(false); - mTask = null; - return cancelled; + if (mCancellingTask != null) { + // There was a pending task already waiting for a previous + // one being canceled; just drop it. + if (mTask.waiting) { + mTask.waiting = false; + mHandler.removeCallbacks(mTask); + } + mTask = null; + return false; + } else if (mTask.waiting) { + // There is a task, but it is waiting for the time it should + // execute. We can just toss it. + mTask.waiting = false; + mHandler.removeCallbacks(mTask); + mTask = null; + return false; + } else { + boolean cancelled = mTask.cancel(false); + if (cancelled) { + mCancellingTask = mTask; + } + mTask = null; + return cancelled; + } } return false; } @@ -92,32 +151,67 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> { public void onCancelled(D data) { } + void executePendingTask() { + if (mCancellingTask == null && mTask != null) { + if (mTask.waiting) { + mTask.waiting = false; + mHandler.removeCallbacks(mTask); + } + if (mUpdateThrottle > 0) { + long now = SystemClock.uptimeMillis(); + if (now < (mLastLoadCompleteTime+mUpdateThrottle)) { + // Not yet time to do another load. + mTask.waiting = true; + mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle); + return; + } + } + mTask.execute((Void[]) null); + } + } + + void dispatchOnCancelled(LoadTask task, D data) { + onCancelled(data); + if (mCancellingTask == task) { + mLastLoadCompleteTime = SystemClock.uptimeMillis(); + mCancellingTask = null; + executePendingTask(); + } + } + void dispatchOnLoadComplete(LoadTask task, D data) { if (mTask != task) { - onCancelled(data); + dispatchOnCancelled(task, data); } else { + mLastLoadCompleteTime = SystemClock.uptimeMillis(); mTask = null; deliverResult(data); } } /** + */ + public abstract D loadInBackground(); + + /** * Called on a worker thread to perform the actual load. Implementations should not deliver the - * results directly, but should return them from this method, which will eventually end up - * calling deliverResult on the UI thread. If implementations need to process - * the results on the UI thread they may override deliverResult and do so + * result directly, but should return them from this method, which will eventually end up + * calling {@link #deliverResult} on the UI thread. If implementations need to process + * the results on the UI thread they may override {@link #deliverResult} and do so * there. * - * @return the result of the load + * @return Implementations must return the result of their load operation. */ - public abstract D loadInBackground(); + protected D onLoadInBackground() { + return loadInBackground(); + } /** * Locks the current thread until the loader completes the current load * operation. Returns immediately if there is no load operation running. * Should not be called from the UI thread. * <p> - * Used for testing. + * Use for testing only. <b>Never</b> call this from a UI thread. */ public void waitForLoader() { LoadTask task = mTask; @@ -132,4 +226,25 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> { } } } + + @Override + public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + super.dump(prefix, fd, writer, args); + if (mTask != null) { + writer.print(prefix); writer.print("mTask="); writer.print(mTask); + writer.print(" waiting="); writer.println(mTask.waiting); + } + if (mCancellingTask != null) { + writer.print(prefix); writer.print("mCancellingTask="); writer.print(mCancellingTask); + writer.print(" waiting="); writer.println(mCancellingTask.waiting); + } + if (mUpdateThrottle != 0) { + writer.print(prefix); writer.print("mUpdateThrottle="); + TimeUtils.formatDuration(mUpdateThrottle, writer); + writer.print(" mLastLoadCompleteTime="); + TimeUtils.formatDuration(mLastLoadCompleteTime, + SystemClock.uptimeMillis(), writer); + writer.println(); + } + } } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index b128d31..227df21 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -227,6 +227,12 @@ public abstract class Context { */ public abstract void setTheme(int resid); + /** @hide Needed for some internal implementation... not public because + * you can't assume this actually means anything. */ + public int getThemeResId() { + return 0; + } + /** * Return the Theme object associated with this Context. */ diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index f8928e4..545144e 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -106,6 +106,12 @@ public class ContextWrapper extends Context { mBase.setTheme(resid); } + /** @hide */ + @Override + public int getThemeResId() { + return mBase.getThemeResId(); + } + @Override public Resources.Theme getTheme() { return mBase.getTheme(); diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java index 8ab0973..38ebaf2 100644 --- a/core/java/android/content/CursorLoader.java +++ b/core/java/android/content/CursorLoader.java @@ -55,7 +55,7 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> { * Registers an observer to get notifications from the content provider * when the cursor needs to be refreshed. */ - public void registerContentObserver(Cursor cursor, ContentObserver observer) { + void registerContentObserver(Cursor cursor, ContentObserver observer) { cursor.registerContentObserver(mObserver); } diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java index ef81fe4..d63fe69 100644 --- a/core/java/android/content/Loader.java +++ b/core/java/android/content/Loader.java @@ -28,6 +28,13 @@ import java.io.PrintWriter; * they should monitor the source of their data and deliver new results when the contents * change. * + * <p><b>Note on threading:</b> Clients of loaders should as a rule perform + * any calls on to a Loader from the main thread of their process (that is, + * the thread the Activity callbacks and other things occur on). Subclasses + * of Loader (such as {@link AsyncTaskLoader}) will often perform their work + * in a separate thread, but when delivering their results this too should + * be done on the main thread.</p> + * * <p>Subclasses generally must implement at least {@link #onStartLoading()}, * {@link #onStopLoading()}, {@link #onForceLoad()}, and {@link #onReset()}. * @@ -80,7 +87,7 @@ public class Loader<D> { /** * Sends the result of the load to the registered listener. Should only be called by subclasses. * - * Must be called from the UI thread. + * Must be called from the process's main thread. * * @param data the result of the load */ @@ -105,10 +112,11 @@ public class Loader<D> { } /** - * Registers a class that will receive callbacks when a load is complete. The callbacks will - * be called on the UI thread so it's safe to pass the results to widgets. + * Registers a class that will receive callbacks when a load is complete. + * The callback will be called on the process's main thread so it's safe to + * pass the results to widgets. * - * Must be called from the UI thread + * <p>Must be called from the process's main thread. */ public void registerListener(int id, OnLoadCompleteListener<D> listener) { if (mListener != null) { @@ -119,7 +127,9 @@ public class Loader<D> { } /** - * Must be called from the UI thread + * Remove a listener that was previously added with {@link #registerListener}. + * + * Must be called from the process's main thread. */ public void unregisterListener(OnLoadCompleteListener<D> listener) { if (mListener == null) { @@ -150,17 +160,19 @@ public class Loader<D> { } /** - * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks - * will be called on the UI thread. If a previous load has been completed and is still valid - * the result may be passed to the callbacks immediately. The loader will monitor the source of - * the data set and may deliver future callbacks if the source changes. Calling - * {@link #stopLoading} will stop the delivery of callbacks. + * Starts an asynchronous load of the Loader's data. When the result + * is ready the callbacks will be called on the process's main thread. + * If a previous load has been completed and is still valid + * the result may be passed to the callbacks immediately. + * The loader will monitor the source of + * the data set and may deliver future callbacks if the source changes. + * Calling {@link #stopLoading} will stop the delivery of callbacks. * * <p>This updates the Loader's internal state so that * {@link #isStarted()} and {@link #isReset()} will return the correct * values, and then calls the implementation's {@link #onStartLoading()}. * - * <p>Must be called from the UI thread. + * <p>Must be called from the process's main thread. */ public final void startLoading() { mStarted = true; @@ -182,14 +194,15 @@ public class Loader<D> { * implementation's {@link #onForceLoad()}. You generally should only call this * when the loader is started -- that is, {@link #isStarted()} returns true. * - * <p>Must be called from the UI thread. + * <p>Must be called from the process's main thread. */ - public final void forceLoad() { + public void forceLoad() { onForceLoad(); } /** * Subclasses must implement this to take care of requests to {@link #forceLoad()}. + * This will always be called from the process's main thread. */ protected void onForceLoad() { } @@ -206,9 +219,9 @@ public class Loader<D> { * {@link #isStarted()} will return the correct * value, and then calls the implementation's {@link #onStopLoading()}. * - * <p>Must be called from the UI thread. + * <p>Must be called from the process's main thread. */ - public final void stopLoading() { + public void stopLoading() { mStarted = false; onStopLoading(); } @@ -217,6 +230,7 @@ public class Loader<D> { * Subclasses must implement this to take care of stopping their loader, * as per {@link #stopLoading()}. This is not called by clients directly, * but as a result of a call to {@link #stopLoading()}. + * This will always be called from the process's main thread. */ protected void onStopLoading() { } @@ -231,9 +245,9 @@ public class Loader<D> { * {@link #isStarted()} and {@link #isReset()} will return the correct * values, and then calls the implementation's {@link #onReset()}. * - * <p>Must be called from the UI thread. + * <p>Must be called from the process's main thread. */ - public final void reset() { + public void reset() { onReset(); mReset = true; mStarted = false; @@ -244,6 +258,7 @@ public class Loader<D> { * Subclasses must implement this to take care of resetting their loader, * as per {@link #reset()}. This is not called by clients directly, * but as a result of a call to {@link #reset()}. + * This will always be called from the process's main thread. */ protected void onReset() { } @@ -265,7 +280,7 @@ public class Loader<D> { * if so, it simply calls {@link #forceLoad()}; otherwise, it sets a flag * so that {@link #takeContentChanged()} returns true. * - * <p>Must be called from the UI thread. + * <p>Must be called from the process's main thread. */ public void onContentChanged() { if (mStarted) { diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java index 70a7fb6..f428aad 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -311,7 +311,6 @@ public class DatabaseUtils { /** * Concatenates two SQL WHERE clauses, handling empty or null values. - * @hide */ public static String concatenateWhere(String a, String b) { if (TextUtils.isEmpty(a)) { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 873674d..cec99e9 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3244,8 +3244,8 @@ public final class Settings { /** * Minimum percentage of free storage on the device that is used to determine if - * the device is running low on storage. - * Say this value is set to 10, the device is considered running low on storage + * the device is running low on storage. The default is 10. + * <p>Say this value is set to 10, the device is considered running low on storage * if 90% or more of the device storage is filled up. * @hide */ @@ -3253,6 +3253,16 @@ public final class Settings { "sys_storage_threshold_percentage"; /** + * Maximum byte size of the low storage threshold. This is to ensure + * that {@link #SYS_STORAGE_THRESHOLD_PERCENTAGE} does not result in + * an overly large threshold for large storage devices. Currently this + * must be less than 2GB. This default is 500MB. + * @hide + */ + public static final String SYS_STORAGE_THRESHOLD_MAX_BYTES = + "sys_storage_threshold_max_bytes"; + + /** * Minimum bytes of free storage on the device before the data * partition is considered full. By default, 1 MB is reserved * to avoid system-wide SQLite disk full exceptions. diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java index ae938e7..be4152b 100644 --- a/core/java/android/view/ContextThemeWrapper.java +++ b/core/java/android/view/ContextThemeWrapper.java @@ -51,6 +51,12 @@ public class ContextThemeWrapper extends ContextWrapper { initializeTheme(); } + /** @hide */ + @Override + public int getThemeResId() { + return mThemeResource; + } + @Override public Resources.Theme getTheme() { if (mTheme != null) { return mTheme; diff --git a/docs/html/guide/topics/fragments/index.jd b/docs/html/guide/topics/fragments/index.jd index 766146e..d07daf4 100644 --- a/docs/html/guide/topics/fragments/index.jd +++ b/docs/html/guide/topics/fragments/index.jd @@ -277,13 +277,13 @@ fragments to your activity layout. You simply need to specify a {@link android.v which to place the fragment.</p> <p>To make any fragment transactions in your activity (such as add, remove, or replace a fragment), you must use APIs from {@link android.app.FragmentTransaction}. You can get an instance -of {@link android.app.FragmentTransaction} from your {@link android.app.Activity} using {@link -android.app.Activity#openFragmentTransaction()}. You can then add a fragment using the {@link +of {@link android.app.FragmentTransaction} from your {@link android.app.FragmentManager} using {@link +android.app.FragmentManager#openTransaction()}. You can then add a fragment using the {@link android.app.FragmentTransaction#add add()} method, specifying the fragment to add and the view in which to insert it. For example:</p> <pre> MyFragment fragment = new MyFragment(); -openFragmentTransaction().add(R.id.fragment_container, fragment).commit(); +getFragmentManager().openTransaction().add(R.id.fragment_container, fragment).commit(); </pre> <p>The first argument passed to {@link android.app.FragmentTransaction#add add()} is the {@link android.view.ViewGroup} in which the fragment should be placed, specified by @@ -372,8 +372,8 @@ android.app.Fragment#onStop onStop()} and others that coincide with the fragment operations on a fragment as the user interacts with the activity, alowing for more rich user experiences without changing activities. In order to perform these operations, you must use {@link android.app.FragmentTransaction} to perform fragment "transactions." You can acquire {@link -android.app.FragmentTransaction} from your activity with {@link -android.app.Activity#openFragmentTransaction}.</p> +android.app.FragmentTransaction} from your FragmentManager with {@link +android.app.FragmentManager#openTransaction}.</p> <p>Common transactions you can perform with fragments include:</p> @@ -397,7 +397,7 @@ in the back stack:</p> <pre> // Create new fragment Fragment newFragment = new MyFragment(); -FragmentTransaction ft = openFragmentTransaction(); +FragmentTransaction ft = getFragmentManager().openTransaction(); // Replace and add to back stack ft.replace(R.id.myfragment, newFragment); ft.addToBackStack(null); @@ -519,7 +519,7 @@ View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Ac <p>Likewise, your activity can call public methods in the fragment when you have a reference to the {@link android.app.Fragment}. You can acquire a reference to the fragment with {@link -android.app.Activity#findFragmentById findFragmentById()} and cast it to your implementation of +android.app.FragmentManager#findFragmentById findFragmentById()} and cast it to your implementation of {@link android.app.Fragment}. For example:</p> <pre> diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 5ad0edb..3e8318e 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -34,6 +34,7 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.PixelFormat; import android.graphics.Rect; +import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.LocalPowerManager; @@ -1017,23 +1018,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { try { Context context = mContext; - boolean setTheme = false; //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel=" // + nonLocalizedLabel + " theme=" + Integer.toHexString(theme)); - if (theme != 0 || labelRes != 0) { + if (theme != context.getThemeResId() || labelRes != 0) { try { context = context.createPackageContext(packageName, 0); - if (theme != 0) { - context.setTheme(theme); - setTheme = true; - } + context.setTheme(theme); } catch (PackageManager.NameNotFoundException e) { // Ignore } } - if (!setTheme) { - context.setTheme(com.android.internal.R.style.Theme); - } Window win = PolicyManager.makeNewWindow(context); if (win.getWindowStyle().getBoolean( diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java index 0b1a4a3..0fba7c3 100644 --- a/services/java/com/android/server/DeviceStorageMonitorService.java +++ b/services/java/com/android/server/DeviceStorageMonitorService.java @@ -16,7 +16,6 @@ package com.android.server; -import com.android.server.am.ActivityManagerService; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -38,7 +37,6 @@ import android.provider.Settings; import android.util.Config; import android.util.EventLog; import android.util.Slog; -import android.provider.Settings; /** * This class implements a service to monitor the amount of disk @@ -66,6 +64,7 @@ class DeviceStorageMonitorService extends Binder { private static final int MONITOR_INTERVAL = 1; //in minutes private static final int LOW_MEMORY_NOTIFICATION_ID = 1; private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10; + private static final int DEFAULT_THRESHOLD_MAX_BYTES = 500*1024*1024; // 500MB private static final int DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES = 12*60; //in minutes private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000; @@ -271,13 +270,18 @@ class DeviceStorageMonitorService extends Binder { * any way */ private long getMemThreshold() { - int value = Settings.Secure.getInt( + long value = Settings.Secure.getInt( mContentResolver, Settings.Secure.SYS_STORAGE_THRESHOLD_PERCENTAGE, DEFAULT_THRESHOLD_PERCENTAGE); if(localLOGV) Slog.v(TAG, "Threshold Percentage="+value); + value *= mTotalMemory; + long maxValue = Settings.Secure.getInt( + mContentResolver, + Settings.Secure.SYS_STORAGE_THRESHOLD_MAX_BYTES, + DEFAULT_THRESHOLD_MAX_BYTES); //evaluate threshold value - return mTotalMemory*value; + return value < maxValue ? value : maxValue; } /* diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index f1d5489..3c8fb01 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1324,6 +1324,7 @@ public final class ActivityManagerService extends ActivityManagerNative ActivityThread at = ActivityThread.systemMain(); mSystemThread = at; Context context = at.getSystemContext(); + context.setTheme(android.R.style.Theme_Holo); m.mContext = context; m.mFactoryTest = factoryTest; m.mMainStack = new ActivityStack(m, context, true); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index caaae1f..72ea7ce 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -26,6 +26,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.os.Build; import android.os.Bundle; import android.os.Message; import android.os.Process; @@ -69,6 +70,7 @@ class ActivityRecord extends IApplicationToken.Stub { int labelRes; // the label information from the package mgr. int icon; // resource identifier of activity's icon. int theme; // resource identifier of activity's theme. + int realTheme; // actual theme resource we will use, never 0. int windowFlags; // custom window flags for preview window. TaskRecord task; // the task this is in. long launchTime; // when we starting launching this activity @@ -246,6 +248,13 @@ class ActivityRecord extends IApplicationToken.Stub { } icon = aInfo.getIconResource(); theme = aInfo.getThemeResource(); + realTheme = theme; + if (realTheme == 0) { + realTheme = aInfo.applicationInfo.targetSdkVersion + < Build.VERSION_CODES.HONEYCOMB + ? android.R.style.Theme + : android.R.style.Theme_Holo; + } if ((aInfo.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { windowFlags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } @@ -266,8 +275,7 @@ class ActivityRecord extends IApplicationToken.Stub { launchMode = aInfo.launchMode; AttributeCache.Entry ent = AttributeCache.instance().get(packageName, - theme != 0 ? theme : android.R.style.Theme, - com.android.internal.R.styleable.Window); + realTheme, com.android.internal.R.styleable.Window); fullscreen = ent != null && !ent.array.getBoolean( com.android.internal.R.styleable.Window_windowIsFloating, false) && !ent.array.getBoolean( |