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

Commit b135f00d authored by riddle_hsu's avatar riddle_hsu Committed by Steve Kondik
Browse files

[ActivityManager] Avoid orphan ContentProviderRecord.

<Symptom>
Binder threads wait forever results ANR/system hang.

<Root cause>
When X is accessing Y's provider.
Before Y publishing its provider to notify X,
someone invokes killBackgroundProcesses to kill Y.
In removeProcessLocked, it will pass restarting=true
and allowRestart=true to handleAppDiedLocked.

When the clean flow going to removeDyingProviderLocked.
The variable will be inLaunching=true always=false.
Then it will not notify the ContentProviderRecord.
And also due to the ContentProviderConnection waiting=true,
it will do nothing and just return true to
cleanUpApplicationRecordLocked to set restart as true.

But due to restarting=true, the restart flow will not execute,
then the waiting ContentProviderRecord for X will be orphan
and keep waiting.

<Reproduce step>
Service X query provider Y when X's oom adj is SERVICE_ADJ,
before Y's publish provider, invoke killBackgroundProcesses
to Y's package.
Then use command "adb shell dumpsys activity prov"
Y will always in "Launching content providers".

<Solution>
For not restarting case, pass restarting=false to
handleAppDiedLocked to let the provider process can be restarted.

A more simple way maybe just change to keep below 2 lines:
  app.kill(reason, true);
  handleAppDiedLocked(app, callerWillRestart, allowRestart);

Change-Id: I8992cb851fce4dbe6255da71d60390e1a33cb9c7
parent 9ebefe12
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -6069,17 +6069,20 @@ public final class ActivityManagerService extends ActivityManagerNative
            if (app.isolated) {
                mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
            }
            app.kill(reason, true);
            handleAppDiedLocked(app, true, allowRestart);
            removeLruProcessLocked(app);
            boolean willRestart = false;
            if (app.persistent && !app.isolated) {
                if (!callerWillRestart) {
                    addAppLocked(app.info, false, null /* ABI override */);
                    willRestart = true;
                } else {
                    needRestart = true;
                }
            }
            app.kill(reason, true);
            handleAppDiedLocked(app, willRestart, allowRestart);
            if (willRestart) {
                removeLruProcessLocked(app);
                addAppLocked(app.info, false, null /* ABI override */);
            }
        } else {
            mRemovedProcesses.add(app);
        }