Remove the ActivityClientRecord reference once destroyed

The ActivityClientRecord was referenced in ActivityThread
#mNewActivities even after it was destroyed. That was possible
when the app main thread is busy without idle reported.

Use ArrayList to easier maintain the activities to report idle.

Bug: 161230418
Test: verified on sample app
Change-Id: I8a8c49da9d942bb6efdfd29dba5495eed896209c
This commit is contained in:
Louis Chang
2023-03-27 07:11:43 +00:00
parent dc8992c4b0
commit b576a7b4bd

View File

@@ -359,9 +359,8 @@ public final class ActivityThread extends ClientTransactionHandler
/** The activities to be truly destroyed (not include relaunch). */
final Map<IBinder, ClientTransactionItem> mActivitiesToBeDestroyed =
Collections.synchronizedMap(new ArrayMap<IBinder, ClientTransactionItem>());
// List of new activities (via ActivityRecord.nextIdle) that should
// be reported when next we idle.
ActivityClientRecord mNewActivities = null;
// List of new activities that should be reported when next we idle.
final ArrayList<ActivityClientRecord> mNewActivities = new ArrayList<>();
// Number of activities that are currently visible on-screen.
@UnsupportedAppUsage
int mNumVisibleActivities = 0;
@@ -562,7 +561,6 @@ public final class ActivityThread extends ClientTransactionHandler
private Configuration tmpConfig = new Configuration();
// Callback used for updating activity override config and camera compat control state.
ViewRootImpl.ActivityConfigCallback activityConfigCallback;
ActivityClientRecord nextIdle;
// Indicates whether this activity is currently the topmost resumed one in the system.
// This holds the last reported value from server.
@@ -656,7 +654,6 @@ public final class ActivityThread extends ClientTransactionHandler
paused = false;
stopped = false;
hideForNow = false;
nextIdle = null;
activityConfigCallback = new ViewRootImpl.ActivityConfigCallback() {
@Override
public void onConfigurationChanged(Configuration overrideConfig,
@@ -2482,29 +2479,22 @@ public final class ActivityThread extends ClientTransactionHandler
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
final ActivityClient ac = ActivityClient.getInstance();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
ac.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
final ActivityClient ac = ActivityClient.getInstance();
while (mNewActivities.size() > 0) {
final ActivityClientRecord a = mNewActivities.remove(0);
if (localLOGV) {
Slog.v(TAG, "Reporting idle of " + a + " finished="
+ (a.activity != null && a.activity.mFinished));
}
if (a.activity != null && !a.activity.mFinished) {
ac.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
}
}
if (stopProfiling) {
mProfiler.stopProfiling();
@@ -5104,8 +5094,7 @@ public final class ActivityThread extends ClientTransactionHandler
}
}
r.nextIdle = mNewActivities;
mNewActivities = r;
mNewActivities.add(r);
if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
@@ -5706,6 +5695,7 @@ public final class ActivityThread extends ClientTransactionHandler
}
if (finishing) {
ActivityClient.getInstance().activityDestroyed(r.token);
mNewActivities.remove(r);
}
mSomeActivitiesChanged = true;
}
@@ -5926,7 +5916,6 @@ public final class ActivityThread extends ClientTransactionHandler
r.activity = null;
r.window = null;
r.hideForNow = false;
r.nextIdle = null;
// Merge any pending results and pending intents; don't just replace them
if (pendingResults != null) {
if (r.pendingResults == null) {