Loading services/core/java/com/android/server/am/ActivityManagerService.java +81 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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. Loading Loading @@ -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); services/core/java/com/android/server/am/UidRecord.java +8 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } Loading services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java 0 → 100644 +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 Loading
services/core/java/com/android/server/am/ActivityManagerService.java +81 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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. Loading Loading @@ -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);
services/core/java/com/android/server/am/UidRecord.java +8 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } Loading
services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java 0 → 100644 +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