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

Commit 18d62bec authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add a process state seq counter to UidRecord."

parents c5e74cc2 88c4d1ce
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ import static android.os.Process.PROC_CHAR;
import static android.os.Process.PROC_OUT_LONG;
import static android.os.Process.PROC_PARENS;
import static android.os.Process.PROC_SPACE_TERM;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
@@ -320,6 +322,7 @@ import com.google.android.collect.Maps;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
import com.android.internal.app.DumpHeapActivity;
import com.android.internal.app.IAppOpsCallback;
@@ -1441,6 +1444,17 @@ public class ActivityManagerService extends IActivityManager.Stub
    private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
    /**
     * A global counter for generating sequence numbers.
     * This value will be used when incrementing sequence numbers in individual uidRecords.
     *
     * Having a global counter ensures that seq numbers are monotonically increasing for a
     * particular uid even when the uidRecord is re-created.
     */
    @GuardedBy("this")
    @VisibleForTesting
    long mProcStateSeqCounter = 0;
    static final class ProcessChangeItem {
        static final int CHANGE_ACTIVITIES = 1<<0;
        int changes;
@@ -2606,6 +2620,33 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    @VisibleForTesting
    public ActivityManagerService() {
        GL_ES_VERSION = 0;
        mActivityStarter = null;
        mAppErrors = null;
        mAppOpsService = null;
        mBatteryStatsService = null;
        mCompatModePackages = null;
        mConstants = null;
        mGrantFile = null;
        mHandler = null;
        mHandlerThread = null;
        mIntentFirewall = null;
        mKeyguardController = null;
        mPermissionReviewRequired = false;
        mProcessCpuThread = null;
        mProcessStats = null;
        mProviderMap = null;
        mRecentTasks = null;
        mServices = null;
        mStackSupervisor = null;
        mSystemThread = null;
        mTaskChangeNotificationController = null;
        mUiHandler = null;
        mUserController = null;
    }
    // Note: This method is invoked on the main thread but may need to attach various
    // handlers to other threads.  So take care to be explicit about the looper.
    public ActivityManagerService(Context systemContext) {
@@ -21752,6 +21793,10 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        for (int i = mActiveUids.size() - 1; i >= 0; --i) {
            incrementProcStateSeqIfNeeded(mActiveUids.valueAt(i));
        }
        mNumServiceProcs = mNewNumServiceProcs;
        // Now determine the memory trimming level of background processes.
@@ -22101,6 +22146,42 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    /**
     * If {@link UidRecord#curProcStateSeq} needs to be updated, then increments the global seq
     * counter {@link #mProcStateSeqCounter} and uses that value for {@param uidRec}.
     */
    @VisibleForTesting
    void incrementProcStateSeqIfNeeded(UidRecord uidRec) {
        if (uidRec.curProcState != uidRec.setProcState && shouldIncrementProcStateSeq(uidRec)) {
            uidRec.curProcStateSeq = ++mProcStateSeqCounter;
        }
    }
    /**
     * Checks if {@link UidRecord#curProcStateSeq} needs to be incremented depending on whether
     * the uid is coming from background to foreground state or vice versa.
     *
     * @return Returns true if the uid is coming from background to foreground state or vice versa,
     *                 false otherwise.
     */
    @VisibleForTesting
    boolean shouldIncrementProcStateSeq(UidRecord uidRec) {
        final boolean isAllowedOnRestrictBackground
                = isProcStateAllowedWhileOnRestrictBackground(uidRec.curProcState);
        final boolean isAllowedOnDeviceIdleOrPowerSaveMode
                = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.curProcState);
        final boolean wasAllowedOnRestrictBackground
                = isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
        final boolean wasAllowedOnDeviceIdleOrPowerSaveMode
                = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState);
        // If the uid is coming from background to foreground or vice versa,
        // then return true. Otherwise false.
        return (wasAllowedOnDeviceIdleOrPowerSaveMode != isAllowedOnDeviceIdleOrPowerSaveMode)
                || (wasAllowedOnRestrictBackground != isAllowedOnRestrictBackground);
    }
    final void runInBackgroundDisabled(int uid) {
        synchronized (this) {
            UidRecord uidRec = mActiveUids.get(uid);
+8 −0
Original line number Diff line number Diff line
@@ -34,6 +34,12 @@ public final class UidRecord {
    boolean setWhitelist;
    boolean idle;
    int numProcs;
    /**
     * Sequence number associated with the {@link #curProcState}. This is incremented using
     * {@link ActivityManagerService#mProcStateSeqCounter}
     * when {@link #curProcState} changes from background to foreground or vice versa.
     */
    long curProcStateSeq;

    static final int CHANGE_PROCSTATE = 0;
    static final int CHANGE_GONE = 1;
@@ -83,6 +89,8 @@ public final class UidRecord {
        }
        sb.append(" procs:");
        sb.append(numProcs);
        sb.append(" curProcStateSeq:");
        sb.append(curProcStateSeq);
        sb.append("}");
        return sb.toString();
    }
+148 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.am;

import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.util.DebugUtils.valueToString;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.app.ActivityManager;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.function.Function;

/**
 * Test class for {@link ActivityManagerService}.
 *
 * To run the tests, use
 *
 * runtest -c com.android.server.am.ActivityManagerServiceTest frameworks-services
 *
 * or the following steps:
 *
 * Build: m FrameworksServicesTests
 * Install: adb install -r \
 *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
 * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerServiceTest -w \
 *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ActivityManagerServiceTest {
    private static final int TEST_UID = 111;

    @Test
    public void testIncrementProcStateSeqIfNeeded() {
        final ActivityManagerService ams = new ActivityManagerService();
        final UidRecord uidRec = new UidRecord(TEST_UID);

        assertEquals("Initially global seq counter should be 0", 0, ams.mProcStateSeqCounter);
        assertEquals("Initially seq counter in uidRecord should be 0", 0, uidRec.curProcStateSeq);

        // Uid state is not moving from background to foreground or vice versa.
        uidRec.setProcState = PROCESS_STATE_TOP;
        uidRec.curProcState = PROCESS_STATE_TOP;
        ams.incrementProcStateSeqIfNeeded(uidRec);
        assertEquals(0, ams.mProcStateSeqCounter);
        assertEquals(0, uidRec.curProcStateSeq);

        // Uid state is moving from foreground to background.
        uidRec.curProcState = PROCESS_STATE_FOREGROUND_SERVICE;
        uidRec.setProcState = PROCESS_STATE_SERVICE;
        ams.incrementProcStateSeqIfNeeded(uidRec);
        assertEquals(1, ams.mProcStateSeqCounter);
        assertEquals(1, uidRec.curProcStateSeq);

        // Explicitly setting the seq counter for more verification.
        ams.mProcStateSeqCounter = 42;

        // Uid state is not moving from background to foreground or vice versa.
        uidRec.setProcState = PROCESS_STATE_IMPORTANT_BACKGROUND;
        uidRec.curProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
        ams.incrementProcStateSeqIfNeeded(uidRec);
        assertEquals(42, ams.mProcStateSeqCounter);
        assertEquals(1, uidRec.curProcStateSeq);

        // Uid state is moving from background to foreground.
        uidRec.setProcState = PROCESS_STATE_LAST_ACTIVITY;
        uidRec.curProcState = PROCESS_STATE_TOP;
        ams.incrementProcStateSeqIfNeeded(uidRec);
        assertEquals(43, ams.mProcStateSeqCounter);
        assertEquals(43, uidRec.curProcStateSeq);
    }

    @Test
    public void testShouldIncrementProcStateSeq() {
        final ActivityManagerService ams = new ActivityManagerService();
        final UidRecord uidRec = new UidRecord(TEST_UID);

        final String error1 = "Seq should be incremented: prevState: %s, curState: %s";
        final String error2 = "Seq should not be incremented: prevState: %s, curState: %s";
        Function<String, String> errorMsg = errorTemplate -> {
            return String.format(errorTemplate,
                    valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.setProcState),
                    valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.curProcState));
        };

        // No change in uid state
        uidRec.setProcState = PROCESS_STATE_RECEIVER;
        uidRec.curProcState = PROCESS_STATE_RECEIVER;
        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));

        // Foreground to foreground
        uidRec.setProcState = PROCESS_STATE_FOREGROUND_SERVICE;
        uidRec.curProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));

        // Background to background
        uidRec.setProcState = PROCESS_STATE_CACHED_ACTIVITY;
        uidRec.curProcState = PROCESS_STATE_CACHED_EMPTY;
        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));

        // Background to background
        uidRec.setProcState = PROCESS_STATE_NONEXISTENT;
        uidRec.curProcState = PROCESS_STATE_CACHED_ACTIVITY;
        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));

        // Background to foreground
        uidRec.setProcState = PROCESS_STATE_SERVICE;
        uidRec.curProcState = PROCESS_STATE_FOREGROUND_SERVICE;
        assertTrue(errorMsg.apply(error1), ams.shouldIncrementProcStateSeq(uidRec));

        // Foreground to background
        uidRec.setProcState = PROCESS_STATE_TOP;
        uidRec.curProcState = PROCESS_STATE_LAST_ACTIVITY;
        assertTrue(errorMsg.apply(error1), ams.shouldIncrementProcStateSeq(uidRec));
    }
}
 No newline at end of file