Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c68c913d authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Various work on out of memory managment.

- Improve how we handle processes that have shown UI, to take care
  of more cases where we want to push them into the background LRU
  list.
- New trim memory level for when an application that has done UI
  is no longer visible to the user.
- Add APIs to get new trim memory callback.
- Add a host of new bind flags to tweak how the system will adjust
  the OOM level of the target process.

Change-Id: I23ba354112f411a9f8773a67426b4dff85fa2439
parent 3970f683
Loading
Loading
Loading
Loading
+37 −5
Original line number Diff line number Diff line
@@ -2331,7 +2331,7 @@ package android.app {
    method public abstract void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
  }
  public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
  public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
    ctor public Activity();
    method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
    method public void closeContextMenu();
@@ -2436,6 +2436,7 @@ package android.app {
    method protected void onTitleChanged(java.lang.CharSequence, int);
    method public boolean onTouchEvent(android.view.MotionEvent);
    method public boolean onTrackballEvent(android.view.MotionEvent);
    method public void onTrimMemory(int);
    method public void onUserInteraction();
    method protected void onUserLeaveHint();
    method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -2731,12 +2732,25 @@ package android.app {
    ctor public AliasActivity();
  }
  public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks {
  public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
    ctor public Application();
    method public void onConfigurationChanged(android.content.res.Configuration);
    method public void onCreate();
    method public void onLowMemory();
    method public void onTerminate();
    method public void onTrimMemory(int);
    method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
    method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
  }
  public static abstract interface Application.ActivityLifecycleCallbacks {
    method public abstract void onActivityCreated(android.app.Activity, android.os.Bundle);
    method public abstract void onActivityDestroyed(android.app.Activity);
    method public abstract void onActivityPaused(android.app.Activity);
    method public abstract void onActivityResumed(android.app.Activity);
    method public abstract void onActivitySaveInstanceState(android.app.Activity, android.os.Bundle);
    method public abstract void onActivityStarted(android.app.Activity);
    method public abstract void onActivityStopped(android.app.Activity);
  }
  public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
@@ -2955,7 +2969,7 @@ package android.app {
    method public void setSelectedGroup(int);
  }
  public class Fragment implements android.content.ComponentCallbacks android.view.View.OnCreateContextMenuListener {
  public class Fragment implements android.content.ComponentCallbacks2 android.view.View.OnCreateContextMenuListener {
    ctor public Fragment();
    method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
    method public final boolean equals(java.lang.Object);
@@ -3009,6 +3023,7 @@ package android.app {
    method public void onSaveInstanceState(android.os.Bundle);
    method public void onStart();
    method public void onStop();
    method public void onTrimMemory(int);
    method public void onViewCreated(android.view.View, android.os.Bundle);
    method public void registerForContextMenu(android.view.View);
    method public void setArguments(android.os.Bundle);
@@ -3545,7 +3560,7 @@ package android.app {
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public abstract class Service extends android.content.ContextWrapper implements android.content.ComponentCallbacks {
  public abstract class Service extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
    ctor public Service();
    method protected void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
    method public final android.app.Application getApplication();
@@ -3558,6 +3573,7 @@ package android.app {
    method public deprecated void onStart(android.content.Intent, int);
    method public int onStartCommand(android.content.Intent, int, int);
    method public void onTaskRemoved(android.content.Intent);
    method public void onTrimMemory(int);
    method public boolean onUnbind(android.content.Intent);
    method public final void startForeground(int, android.app.Notification);
    method public final void stopForeground(boolean);
@@ -4442,6 +4458,14 @@ package android.content {
    method public abstract void onLowMemory();
  }
  public abstract interface ComponentCallbacks2 implements android.content.ComponentCallbacks {
    method public abstract void onTrimMemory(int);
    field public static final int TRIM_MEMORY_BACKGROUND = 40; // 0x28
    field public static final int TRIM_MEMORY_COMPLETE = 80; // 0x50
    field public static final int TRIM_MEMORY_MODERATE = 60; // 0x3c
    field public static final int TRIM_MEMORY_UI_HIDDEN = 20; // 0x14
  }
  public final class ComponentName implements java.lang.Cloneable java.lang.Comparable android.os.Parcelable {
    ctor public ComponentName(java.lang.String, java.lang.String);
    ctor public ComponentName(android.content.Context, java.lang.String);
@@ -4463,7 +4487,7 @@ package android.content {
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public abstract class ContentProvider implements android.content.ComponentCallbacks {
  public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
    ctor public ContentProvider();
    method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
    method public void attachInfo(android.content.Context, android.content.pm.ProviderInfo);
@@ -4481,6 +4505,7 @@ package android.content {
    method public void onConfigurationChanged(android.content.res.Configuration);
    method public abstract boolean onCreate();
    method public void onLowMemory();
    method public void onTrimMemory(int);
    method public android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
    method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
    method protected final android.os.ParcelFileDescriptor openFileHelper(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -4734,6 +4759,7 @@ package android.content {
    method public abstract android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
    method public abstract android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
    method public abstract deprecated android.graphics.drawable.Drawable peekWallpaper();
    method public void registerComponentCallbacks(android.content.ComponentCallbacks);
    method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter);
    method public abstract android.content.Intent registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler);
    method public abstract void removeStickyBroadcast(android.content.Intent);
@@ -4754,15 +4780,21 @@ package android.content {
    method public abstract android.content.ComponentName startService(android.content.Intent);
    method public abstract boolean stopService(android.content.Intent);
    method public abstract void unbindService(android.content.ServiceConnection);
    method public void unregisterComponentCallbacks(android.content.ComponentCallbacks);
    method public abstract void unregisterReceiver(android.content.BroadcastReceiver);
    field public static final java.lang.String ACCESSIBILITY_SERVICE = "accessibility";
    field public static final java.lang.String ACCOUNT_SERVICE = "account";
    field public static final java.lang.String ACTIVITY_SERVICE = "activity";
    field public static final java.lang.String ALARM_SERVICE = "alarm";
    field public static final java.lang.String AUDIO_SERVICE = "audio";
    field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
    field public static final int BIND_ADJUST_WITH_ACTIVITY = 64; // 0x40
    field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10
    field public static final int BIND_AUTO_CREATE = 1; // 0x1
    field public static final int BIND_DEBUG_UNBIND = 2; // 0x2
    field public static final int BIND_IMPORTANT = 64; // 0x40
    field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
    field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
    field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
    field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
    field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
+18 −4
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package android.app;
import com.android.internal.app.ActionBarImpl;
import com.android.internal.policy.PolicyManager;

import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -626,7 +626,7 @@ import java.util.HashMap;
public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
        OnCreateContextMenuListener, ComponentCallbacks2 {
    private static final String TAG = "Activity";

    /** Standard activity result: operation canceled. */
@@ -859,6 +859,7 @@ public class Activity extends ContextThemeWrapper
                    ? mLastNonConfigurationInstances.fragments : null);
        }
        mFragments.dispatchCreate();
        getApplication().dispatchActivityCreated(this, savedInstanceState);
        mCalled = true;
    }

@@ -1001,6 +1002,8 @@ public class Activity extends ContextThemeWrapper
            }
            mCheckedForLoaderManager = true;
        }

        getApplication().dispatchActivityStarted(this);
    }

    /**
@@ -1048,6 +1051,7 @@ public class Activity extends ContextThemeWrapper
     * @see #onPause
     */
    protected void onResume() {
        getApplication().dispatchActivityResumed(this);
        mCalled = true;
    }

@@ -1158,6 +1162,7 @@ public class Activity extends ContextThemeWrapper
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
        getApplication().dispatchActivitySaveInstanceState(this, outState);
    }

    /**
@@ -1234,6 +1239,7 @@ public class Activity extends ContextThemeWrapper
     * @see #onStop
     */
    protected void onPause() {
        getApplication().dispatchActivityPaused(this);
        mCalled = true;
    }

@@ -1320,6 +1326,7 @@ public class Activity extends ContextThemeWrapper
     */
    protected void onStop() {
        if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
        getApplication().dispatchActivityStopped(this);
        mCalled = true;
    }

@@ -1382,6 +1389,8 @@ public class Activity extends ContextThemeWrapper
        if (mSearchManager != null) {
            mSearchManager.stopSearch();
        }

        getApplication().dispatchActivityDestroyed(this);
    }

    /**
@@ -1586,6 +1595,11 @@ public class Activity extends ContextThemeWrapper
        mFragments.dispatchLowMemory();
    }

    public void onTrimMemory(int level) {
        mCalled = true;
        mFragments.dispatchTrimMemory(level);
    }

    /**
     * Return the FragmentManager for interacting with fragments associated
     * with this activity.
+22 −10
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ package android.app;

import android.app.backup.BackupAgent;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.Context;
@@ -3258,10 +3258,10 @@ public final class ActivityThread {
        }
    }

    ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
    ArrayList<ComponentCallbacks2> collectComponentCallbacksLocked(
            boolean allActivities, Configuration newConfig) {
        ArrayList<ComponentCallbacks> callbacks
                = new ArrayList<ComponentCallbacks>();
        ArrayList<ComponentCallbacks2> callbacks
                = new ArrayList<ComponentCallbacks2>();

        if (mActivities.size() > 0) {
            Iterator<ActivityClientRecord> it = mActivities.values().iterator();
@@ -3311,10 +3311,10 @@ public final class ActivityThread {
        return callbacks;
    }

    private void performConfigurationChanged(
            ComponentCallbacks cb, Configuration config) {
    private final void performConfigurationChanged(
            ComponentCallbacks2 cb, Configuration config) {
        // Only for Activity objects, check that they actually call up to their
        // superclass implementation.  ComponentCallbacks is an interface, so
        // superclass implementation.  ComponentCallbacks2 is an interface, so
        // we check the runtime type and act accordingly.
        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
        if (activity != null) {
@@ -3418,7 +3418,7 @@ public final class ActivityThread {
    
    final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {

        ArrayList<ComponentCallbacks> callbacks = null;
        ArrayList<ComponentCallbacks2> callbacks = null;

        synchronized (mPackages) {
            if (mPendingConfiguration != null) {
@@ -3558,7 +3558,7 @@ public final class ActivityThread {
    }
        
    final void handleLowMemory() {
        ArrayList<ComponentCallbacks> callbacks;
        ArrayList<ComponentCallbacks2> callbacks;

        synchronized (mPackages) {
            callbacks = collectComponentCallbacksLocked(true, null);
@@ -3583,6 +3583,16 @@ public final class ActivityThread {

    final void handleTrimMemory(int level) {
        WindowManagerImpl.getDefault().trimMemory(level);
        ArrayList<ComponentCallbacks2> callbacks;

        synchronized (mPackages) {
            callbacks = collectComponentCallbacksLocked(true, null);
        }

        final int N = callbacks.size();
        for (int i=0; i<N; i++) {
            callbacks.get(i).onTrimMemory(level);
        }
    }

    private void handleBindApplication(AppBindData data) {
@@ -4128,7 +4138,7 @@ public final class ActivityThread {
            }
        }
        
        ViewRootImpl.addConfigCallback(new ComponentCallbacks() {
        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
            public void onConfigurationChanged(Configuration newConfig) {
                synchronized (mPackages) {
                    // We need to apply this change to the resources
@@ -4148,6 +4158,8 @@ public final class ActivityThread {
            }
            public void onLowMemory() {
            }
            public void onTrimMemory(int level) {
            }
        });
    }

+156 −4
Original line number Diff line number Diff line
@@ -16,10 +16,14 @@

package android.app;

import java.util.ArrayList;

import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.os.Bundle;

/**
 * Base class for those who need to maintain global application state. You can
@@ -36,10 +40,25 @@ import android.content.res.Configuration;
 * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
 * when first constructing the singleton.</p>
 */
public class Application extends ContextWrapper implements ComponentCallbacks {
public class Application extends ContextWrapper implements ComponentCallbacks2 {
    private ArrayList<ComponentCallbacks> mComponentCallbacks =
            new ArrayList<ComponentCallbacks>();
    private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
            new ArrayList<ActivityLifecycleCallbacks>();

    /** @hide */
    public LoadedApk mLoadedApk;

    public interface ActivityLifecycleCallbacks {
        void onActivityCreated(Activity activity, Bundle savedInstanceState);
        void onActivityStarted(Activity activity);
        void onActivityResumed(Activity activity);
        void onActivityPaused(Activity activity);
        void onActivityStopped(Activity activity);
        void onActivitySaveInstanceState(Activity activity, Bundle outState);
        void onActivityDestroyed(Activity activity);
    }

    public Application() {
        super(null);
    }
@@ -65,9 +84,57 @@ public class Application extends ContextWrapper implements ComponentCallbacks {
    }

    public void onConfigurationChanged(Configuration newConfig) {
        Object[] callbacks = collectComponentCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
            }
        }
    }

    public void onLowMemory() {
        Object[] callbacks = collectComponentCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ComponentCallbacks)callbacks[i]).onLowMemory();
            }
        }
    }

    public void onTrimMemory(int level) {
        Object[] callbacks = collectComponentCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                Object c = callbacks[i];
                if (c instanceof ComponentCallbacks2) {
                    ((ComponentCallbacks2)c).onTrimMemory(level);
                }
            }
        }
    }

    public void registerComponentCallbacks(ComponentCallbacks callback) {
        synchronized (mComponentCallbacks) {
            mComponentCallbacks.add(callback);
        }
    }

    public void unregisterComponentCallbacks(ComponentCallbacks callback) {
        synchronized (mComponentCallbacks) {
            mComponentCallbacks.remove(callback);
        }
    }

    public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
        synchronized (mActivityLifecycleCallbacks) {
            mActivityLifecycleCallbacks.add(callback);
        }
    }

    public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
        synchronized (mActivityLifecycleCallbacks) {
            mActivityLifecycleCallbacks.remove(callback);
        }
    }
    
    // ------------------ Internal API ------------------
@@ -79,4 +146,89 @@ public class Application extends ContextWrapper implements ComponentCallbacks {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

    /* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
                        savedInstanceState);
            }
        }
    }

    /* package */ void dispatchActivityStarted(Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity);
            }
        }
    }

    /* package */ void dispatchActivityResumed(Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity);
            }
        }
    }

    /* package */ void dispatchActivityPaused(Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);
            }
        }
    }

    /* package */ void dispatchActivityStopped(Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity);
            }
        }
    }

    /* package */ void dispatchActivitySaveInstanceState(Activity activity, Bundle outState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity,
                        outState);
            }
        }
    }

    /* package */ void dispatchActivityDestroyed(Activity activity) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i=0; i<callbacks.length; i++) {
                ((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
            }
        }
    }

    private Object[] collectComponentCallbacks() {
        Object[] callbacks = null;
        synchronized (mComponentCallbacks) {
            if (mComponentCallbacks.size() > 0) {
                callbacks = mComponentCallbacks.toArray();
            }
        }
        return callbacks;
    }

    private Object[] collectActivityLifecycleCallbacks() {
        Object[] callbacks = null;
        synchronized (mActivityLifecycleCallbacks) {
            if (mActivityLifecycleCallbacks.size() > 0) {
                callbacks = mActivityLifecycleCallbacks.toArray();
            }
        }
        return callbacks;
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -1109,6 +1109,12 @@ class ContextImpl extends Context {
            throw new RuntimeException("Not supported in system context");
        }
        try {
            IBinder token = getActivityToken();
            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                    && mPackageInfo.getApplicationInfo().targetSdkVersion
                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                flags |= BIND_WAIVE_PRIORITY;
            }
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(),
                service, service.resolveTypeIfNeeded(getContentResolver()),
Loading