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

Commit ac34500c authored by Jing Ji's avatar Jing Ji Committed by Automerger Merge Worker
Browse files

Merge "Skip resetting the shouldNotFreeze flag while re-evaluating oom adj"...

Merge "Skip resetting the shouldNotFreeze flag while re-evaluating oom adj" into sc-dev am: 98b57c30 am: 93f2d74b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15141325

Change-Id: Ie80e559d31a7066d6fc870287c61a8a196c24e45
parents 6693ecac 93f2d74b
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -212,6 +212,23 @@ public final class CachedAppOptimizer {
                }
                }
            };
            };


    private final OnPropertiesChangedListener mOnNativeBootFlagsChangedListener =
            new OnPropertiesChangedListener() {
                @Override
                public void onPropertiesChanged(Properties properties) {
                    synchronized (mPhenotypeFlagLock) {
                        for (String name : properties.getKeyset()) {
                            if (KEY_FREEZER_DEBOUNCE_TIMEOUT.equals(name)) {
                                updateFreezerDebounceTimeout();
                            }
                        }
                    }
                    if (mTestCallback != null) {
                        mTestCallback.onPropertyChanged();
                    }
                }
            };

    private final class SettingsContentObserver extends ContentObserver {
    private final class SettingsContentObserver extends ContentObserver {
        SettingsContentObserver() {
        SettingsContentObserver() {
            super(mAm.mHandler);
            super(mAm.mHandler);
@@ -328,6 +345,10 @@ public final class CachedAppOptimizer {
        // TODO: initialize flags to default and only update them if values are set in DeviceConfig
        // TODO: initialize flags to default and only update them if values are set in DeviceConfig
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
                ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
        DeviceConfig.addOnPropertiesChangedListener(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
                ActivityThread.currentApplication().getMainExecutor(),
                mOnNativeBootFlagsChangedListener);
        mAm.mContext.getContentResolver().registerContentObserver(
        mAm.mContext.getContentResolver().registerContentObserver(
                CACHED_APP_FREEZER_ENABLED_URI, false, mSettingsObserver);
                CACHED_APP_FREEZER_ENABLED_URI, false, mSettingsObserver);
        synchronized (mPhenotypeFlagLock) {
        synchronized (mPhenotypeFlagLock) {
+13 −8
Original line number Original line Diff line number Diff line
@@ -1530,9 +1530,11 @@ public class OomAdjuster {
        state.setAdjTarget(null);
        state.setAdjTarget(null);
        state.setEmpty(false);
        state.setEmpty(false);
        state.setCached(false);
        state.setCached(false);
        state.setNoKillOnForcedAppStandbyAndIdle(false);
        state.resetAllowStartFgsState();
        state.resetAllowStartFgsState();
        if (!cycleReEval) {
            // Don't reset this flag when doing cycles re-evaluation.
            app.mOptRecord.setShouldNotFreeze(false);
            app.mOptRecord.setShouldNotFreeze(false);
        }


        final int appUid = app.info.uid;
        final int appUid = app.info.uid;
        final int logUid = mService.mCurOomAdjUid;
        final int logUid = mService.mCurOomAdjUid;
@@ -1983,6 +1985,11 @@ public class OomAdjuster {


                    final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
                    final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;


                    if (client.mOptRecord.shouldNotFreeze()) {
                        // Propagate the shouldNotFreeze flag down the bindings.
                        app.mOptRecord.setShouldNotFreeze(true);
                    }

                    if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
                    if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
                        if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                        if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
                            continue;
                            continue;
@@ -2019,9 +2026,6 @@ public class OomAdjuster {
                            // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
                            // Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
                            if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
                            if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
                                app.mOptRecord.setShouldNotFreeze(true);
                                app.mOptRecord.setShouldNotFreeze(true);
                                // Similarly, we shouldn't kill it when it's in forced-app-standby
                                // mode and cached & idle state.
                                app.mState.setNoKillOnForcedAppStandbyAndIdle(true);
                            }
                            }
                            // Not doing bind OOM management, so treat
                            // Not doing bind OOM management, so treat
                            // this guy more like a started service.
                            // this guy more like a started service.
@@ -2226,9 +2230,6 @@ public class OomAdjuster {
                        // unfrozen.
                        // unfrozen.
                        if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
                        if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
                            app.mOptRecord.setShouldNotFreeze(true);
                            app.mOptRecord.setShouldNotFreeze(true);
                            // Similarly, we shouldn't kill it when it's in forced-app-standby
                            // mode and cached & idle state.
                            app.mState.setNoKillOnForcedAppStandbyAndIdle(true);
                        }
                        }
                    }
                    }
                    if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                    if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
@@ -2302,6 +2303,10 @@ public class OomAdjuster {
                    // we are going to consider it empty.
                    // we are going to consider it empty.
                    clientProcState = PROCESS_STATE_CACHED_EMPTY;
                    clientProcState = PROCESS_STATE_CACHED_EMPTY;
                }
                }
                if (client.mOptRecord.shouldNotFreeze()) {
                    // Propagate the shouldNotFreeze flag down the bindings.
                    app.mOptRecord.setShouldNotFreeze(true);
                }
                String adjType = null;
                String adjType = null;
                if (adj > clientAdj) {
                if (adj > clientAdj) {
                    if (state.hasShownUi() && !state.getCachedIsHomeProcess()
                    if (state.hasShownUi() && !state.getCachedIsHomeProcess()
+0 −17
Original line number Original line Diff line number Diff line
@@ -357,13 +357,6 @@ final class ProcessStateRecord {
    @ElapsedRealtimeLong
    @ElapsedRealtimeLong
    private long mLastInvisibleTime;
    private long mLastInvisibleTime;


    /**
     * Whether or not this process could be killed when it's in forced-app-standby mode
     * and cached &amp; idle state.
     */
    @GuardedBy("mService")
    private boolean mNoKillOnForcedAppStandbyAndIdle;

    // Below are the cached task info for OomAdjuster only
    // Below are the cached task info for OomAdjuster only
    private static final int VALUE_INVALID = -1;
    private static final int VALUE_INVALID = -1;
    private static final int VALUE_FALSE = 0;
    private static final int VALUE_FALSE = 0;
@@ -1134,16 +1127,6 @@ final class ProcessStateRecord {
        return mLastInvisibleTime;
        return mLastInvisibleTime;
    }
    }


    @GuardedBy("mService")
    void setNoKillOnForcedAppStandbyAndIdle(boolean shouldNotKill) {
        mNoKillOnForcedAppStandbyAndIdle = shouldNotKill;
    }

    @GuardedBy("mService")
    boolean shouldNotKillOnForcedAppStandbyAndIdle() {
        return mNoKillOnForcedAppStandbyAndIdle;
    }

    @GuardedBy({"mService", "mProcLock"})
    @GuardedBy({"mService", "mProcLock"})
    void dump(PrintWriter pw, String prefix, long nowUptime) {
    void dump(PrintWriter pw, String prefix, long nowUptime) {
        if (mReportedInteraction || mFgInteractionTime != 0) {
        if (mReportedInteraction || mFgInteractionTime != 0) {
+75 −3
Original line number Original line Diff line number Diff line
@@ -94,6 +94,17 @@ public class ActivityManagerTest {
            "com.android.servicestests.apps.simpleservicetestapp.ACTION_FGS_STATS_TEST";
            "com.android.servicestests.apps.simpleservicetestapp.ACTION_FGS_STATS_TEST";
    private static final String EXTRA_MESSENGER = "extra_messenger";
    private static final String EXTRA_MESSENGER = "extra_messenger";


    private static final String EXTRA_CALLBACK = "callback";
    private static final String EXTRA_COMMAND = "command";
    private static final String EXTRA_FLAGS = "flags";
    private static final String EXTRA_TARGET_PACKAGE = "target_package";

    private static final int COMMAND_INVALID = 0;
    private static final int COMMAND_EMPTY = 1;
    private static final int COMMAND_BIND_SERVICE = 2;
    private static final int COMMAND_UNBIND_SERVICE = 3;
    private static final int COMMAND_STOP_SELF = 4;

    private IActivityManager mService;
    private IActivityManager mService;
    private IRemoteCallback mCallback;
    private IRemoteCallback mCallback;
    private Context mContext;
    private Context mContext;
@@ -333,6 +344,12 @@ public class ActivityManagerTest {
        SettingsSession<String> amConstantsSettings = null;
        SettingsSession<String> amConstantsSettings = null;
        DeviceConfigSession<Long> freezerDebounceTimeout = null;
        DeviceConfigSession<Long> freezerDebounceTimeout = null;
        MyServiceConnection autoConnection = null;
        MyServiceConnection autoConnection = null;
        final ActivityManager am = mContext.getSystemService(ActivityManager.class);
        final PackageManager pm = mContext.getPackageManager();
        final int uid1 = pm.getPackageUid(TEST_APP1, 0);
        final int uid2 = pm.getPackageUid(TEST_APP2, 0);
        final MyUidImportanceListener uid1Listener = new MyUidImportanceListener(uid1);
        final MyUidImportanceListener uid2Listener = new MyUidImportanceListener(uid2);
        try {
        try {
            if (!freezerWasEnabled) {
            if (!freezerWasEnabled) {
                freezerEnabled = new SettingsSession<>(
                freezerEnabled = new SettingsSession<>(
@@ -346,7 +363,7 @@ public class ActivityManagerTest {
                }
                }
            }
            }
            freezerDebounceTimeout = new DeviceConfigSession<>(
            freezerDebounceTimeout = new DeviceConfigSession<>(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
                    CachedAppOptimizer.KEY_FREEZER_DEBOUNCE_TIMEOUT,
                    CachedAppOptimizer.KEY_FREEZER_DEBOUNCE_TIMEOUT,
                    DeviceConfig::getLong, CachedAppOptimizer.DEFAULT_FREEZER_DEBOUNCE_TIMEOUT);
                    DeviceConfig::getLong, CachedAppOptimizer.DEFAULT_FREEZER_DEBOUNCE_TIMEOUT);
            freezerDebounceTimeout.set(waitFor);
            freezerDebounceTimeout.set(waitFor);
@@ -359,13 +376,20 @@ public class ActivityManagerTest {
            amConstantsSettings.set(
            amConstantsSettings.set(
                    ActivityManagerConstants.KEY_MAX_SERVICE_INACTIVITY + "=" + waitFor);
                    ActivityManagerConstants.KEY_MAX_SERVICE_INACTIVITY + "=" + waitFor);


            runShellCommand("cmd deviceidle whitelist +" + TEST_APP1);
            runShellCommand("cmd deviceidle whitelist +" + TEST_APP2);

            am.addOnUidImportanceListener(uid1Listener,
                    RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE);
            am.addOnUidImportanceListener(uid2Listener, RunningAppProcessInfo.IMPORTANCE_CACHED);

            final Intent intent = new Intent();
            final Intent intent = new Intent();
            intent.setClassName(TEST_APP1, TEST_CLASS);
            intent.setClassName(TEST_APP1, TEST_CLASS);


            final CountDownLatch latch = new CountDownLatch(1);
            CountDownLatch latch = new CountDownLatch(1);
            autoConnection = new MyServiceConnection(latch);
            autoConnection = new MyServiceConnection(latch);
            mContext.bindService(intent, autoConnection,
            mContext.bindService(intent, autoConnection,
                    Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_OOM_MANAGEMENT);
                    Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);
            try {
            try {
                assertTrue("Timeout to bind to service " + intent.getComponent(),
                assertTrue("Timeout to bind to service " + intent.getComponent(),
                        latch.await(AWAIT_TIMEOUT, TimeUnit.MILLISECONDS));
                        latch.await(AWAIT_TIMEOUT, TimeUnit.MILLISECONDS));
@@ -383,6 +407,37 @@ public class ActivityManagerTest {


            // It still shouldn't be frozen, although it's been in cached state.
            // It still shouldn't be frozen, although it's been in cached state.
            assertFalse(TEST_APP1 + " shouldn't be frozen now.", isAppFrozen(TEST_APP1));
            assertFalse(TEST_APP1 + " shouldn't be frozen now.", isAppFrozen(TEST_APP1));

            final CountDownLatch[] latchHolder = new CountDownLatch[1];
            final IRemoteCallback callback = new IRemoteCallback.Stub() {
                @Override
                public void sendResult(Bundle bundle) {
                    if (bundle != null) {
                        latchHolder[0].countDown();
                    }
                }
            };

            // Bind from app1 to app2 without BIND_WAIVE_PRIORITY.
            final Bundle extras = new Bundle();
            extras.putBinder(EXTRA_CALLBACK, callback.asBinder());
            latchHolder[0] = new CountDownLatch(1);
            sendCommand(COMMAND_BIND_SERVICE, TEST_APP1, TEST_APP2, extras);
            assertTrue("Timed out to bind to " + TEST_APP2, latchHolder[0].await(
                    waitFor, TimeUnit.MILLISECONDS));

            // Stop service in app1
            extras.clear();
            sendCommand(COMMAND_STOP_SELF, TEST_APP1, TEST_APP1, extras);

            assertTrue(TEST_APP2 + " should be in cached", uid2Listener.waitFor(
                    RunningAppProcessInfo.IMPORTANCE_CACHED, waitFor));

            // Wait for the freezer kick in if there is any.
            Thread.sleep(waitFor * 4);

            // It still shouldn't be frozen, although it's been in cached state.
            assertFalse(TEST_APP2 + " shouldn't be frozen now.", isAppFrozen(TEST_APP2));
        } finally {
        } finally {
            toggleScreenOn(true);
            toggleScreenOn(true);
            if (amConstantsSettings != null) {
            if (amConstantsSettings != null) {
@@ -397,7 +452,24 @@ public class ActivityManagerTest {
            if (autoConnection != null) {
            if (autoConnection != null) {
                mContext.unbindService(autoConnection);
                mContext.unbindService(autoConnection);
            }
            }
            am.removeOnUidImportanceListener(uid1Listener);
            am.removeOnUidImportanceListener(uid2Listener);
            sendCommand(COMMAND_UNBIND_SERVICE, TEST_APP1, TEST_APP2, null);
            sendCommand(COMMAND_UNBIND_SERVICE, TEST_APP2, TEST_APP1, null);
            runShellCommand("cmd deviceidle whitelist -" + TEST_APP1);
            runShellCommand("cmd deviceidle whitelist -" + TEST_APP2);
        }
    }
    }

    private void sendCommand(int command, String sourcePkg, String targetPkg, Bundle extras) {
        final Intent intent = new Intent();
        intent.setClassName(sourcePkg, TEST_CLASS);
        intent.putExtra(EXTRA_COMMAND, command);
        intent.putExtra(EXTRA_TARGET_PACKAGE, targetPkg);
        if (extras != null) {
            intent.putExtras(extras);
        }
        mContext.startService(intent);
    }
    }


    private boolean isFreezerEnabled() throws Exception {
    private boolean isFreezerEnabled() throws Exception {
+78 −1
Original line number Original line Diff line number Diff line
@@ -16,29 +16,106 @@
package com.android.servicestests.apps.simpleservicetestapp;
package com.android.servicestests.apps.simpleservicetestapp;


import android.app.Service;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.IRemoteCallback;
import android.os.Process;
import android.os.Process;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Log;


public class SimpleService extends Service {
public class SimpleService extends Service {
    private static final String TAG = "SimpleService";
    private static final String TAG = "SimpleService";


    private static final String TEST_CLASS =
            "com.android.servicestests.apps.simpleservicetestapp.SimpleService";

    private static final String EXTRA_CALLBACK = "callback";
    private static final String EXTRA_COMMAND = "command";
    private static final String EXTRA_FLAGS = "flags";
    private static final String EXTRA_TARGET_PACKAGE = "target_package";

    private static final int COMMAND_INVALID = 0;
    private static final int COMMAND_EMPTY = 1;
    private static final int COMMAND_BIND_SERVICE = 2;
    private static final int COMMAND_UNBIND_SERVICE = 3;
    private static final int COMMAND_STOP_SELF = 4;

    private ArrayMap<String, ServiceConnection> mServiceConnections = new ArrayMap<>();

    private final IRemoteCallback.Stub mBinder = new IRemoteCallback.Stub() {
    private final IRemoteCallback.Stub mBinder = new IRemoteCallback.Stub() {
        @Override
        @Override
        public void sendResult(Bundle bundle) {
        public void sendResult(Bundle bundle) {
            if (bundle == null) {
                Process.killProcess(Process.myPid());
                Process.killProcess(Process.myPid());
            } else {
                // No-op for now.
            }
        }
        }
    };
    };


    @Override
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand");
        Log.i(TAG, "onStartCommand");
        int command = intent.getIntExtra(EXTRA_COMMAND, COMMAND_INVALID);
        if (command != COMMAND_INVALID) {
            final String targetPkg = intent.getStringExtra(EXTRA_TARGET_PACKAGE);
            Log.i(TAG, "Received command " + command + " targetPkg=" + targetPkg);
            switch (command) {
                case COMMAND_BIND_SERVICE:
                    final Bundle extras = intent.getExtras();
                    bindToService(targetPkg, intent.getIntExtra(EXTRA_FLAGS, 0),
                            IRemoteCallback.Stub.asInterface(extras.getBinder(EXTRA_CALLBACK)));
                    break;
                case COMMAND_UNBIND_SERVICE:
                    unbindService(targetPkg);
                    break;
                case COMMAND_STOP_SELF:
                    stopSelf();
                    return START_NOT_STICKY;
            }
        }
        return START_STICKY;
        return START_STICKY;
    }
    }


    private void bindToService(String targetPkg, int flags, IRemoteCallback callback) {
        Intent intent = new Intent();
        intent.setClassName(targetPkg, TEST_CLASS);
        final ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                if (callback != null) {
                    try {
                        callback.sendResult(new Bundle());
                    } catch (RemoteException e) {
                    }
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
        };
        if (getApplicationContext().bindService(intent, conn, BIND_AUTO_CREATE | flags)) {
            mServiceConnections.put(targetPkg, conn);
        } else if (callback != null) {
            try {
                callback.sendResult(null);
            } catch (RemoteException e) {
            }
        }
    }

    private void unbindService(String targetPkg) {
        final ServiceConnection conn = mServiceConnections.remove(targetPkg);
        if (conn != null) {
            getApplicationContext().unbindService(conn);
        }
    }

    @Override
    @Override
    public IBinder onBind(Intent intent) {
    public IBinder onBind(Intent intent) {
        return mBinder;
        return mBinder;