Introduce a grace period for bg activity starts
We allow processes that either had an activity started in them
recently, or recently finished an activity while they were
participating in a visible task to start activities from background
within 10 seconds.
Bug: 132333960
Test: atest WmTests:ActivityStarterTests
Test: atest CtsWindowManagerDeviceTestCases:ActivityStarterTests
Test: atest BackgroundActivityLaunchTest
Test: manual with bugs on b/hotlistid:1573032
Change-Id: Ica2c1abecf881ff9bb0959f17456d816350e4e96
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 772e5e6..765c9d0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -311,6 +311,9 @@
public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;
// How long we wait until we timeout on key dispatching during instrumentation.
static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000;
+ // How long we permit background activity starts after an activity in the process
+ // started or finished.
+ static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000;
/** Used to indicate that an app transition should be animated. */
static final boolean ANIMATE = true;
@@ -1575,6 +1578,13 @@
}
}
}
+
+ // note down that the process has finished an activity and is in background activity
+ // starts grace period
+ if (r.app != null) {
+ r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis());
+ }
+
final long origId = Binder.clearCallingIdentity();
try {
boolean res;
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 12b62b9..2ad25cf 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -34,6 +34,7 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS;
import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.wm.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -50,6 +51,7 @@
import android.content.res.Configuration;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
@@ -163,6 +165,11 @@
private final ArrayList<TaskRecord> mRecentTasks = new ArrayList<>();
// The most recent top-most activity that was resumed in the process for pre-Q app.
private ActivityRecord mPreQTopResumedActivity = null;
+ // The last time an activity was launched in the process
+ private long mLastActivityLaunchTime;
+ // The last time an activity was finished in the process while the process participated
+ // in a visible task
+ private long mLastActivityFinishTime;
// Last configuration that was reported to the process.
private final Configuration mLastReportedConfiguration;
@@ -372,6 +379,20 @@
return mUsingWrapper;
}
+ void setLastActivityLaunchTime(long launchTime) {
+ if (launchTime <= mLastActivityLaunchTime) {
+ return;
+ }
+ mLastActivityLaunchTime = launchTime;
+ }
+
+ void setLastActivityFinishTimeIfNeeded(long finishTime) {
+ if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) {
+ return;
+ }
+ mLastActivityFinishTime = finishTime;
+ }
+
public void setAllowBackgroundActivityStarts(boolean allowBackgroundActivityStarts) {
mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
}
@@ -381,6 +402,12 @@
if (mAllowBackgroundActivityStarts) {
return true;
}
+ // allow if any activity in the caller has either started or finished very recently
+ final long now = SystemClock.uptimeMillis();
+ if (now - mLastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS
+ || now - mLastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) {
+ return true;
+ }
// allow if the proc is instrumenting with background activity starts privs
if (mInstrumentingWithBackgroundActivityStartPrivileges) {
return true;
@@ -457,6 +484,8 @@
}
void addActivityIfNeeded(ActivityRecord r) {
+ // even if we already track this activity, note down that it has been launched
+ setLastActivityLaunchTime(r.lastLaunchTime);
if (mActivities.contains(r)) {
return;
}