Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does Android consider a window is leaked?

I checked the Android source code, and found the following method. (core/java/android/view/WindowManagerGlobal.java)

It seems that when who != null the window/view is leaked. Can anyone explain what's going on behind this?

public void closeAll(IBinder token, String who, String what) {
        synchronized (mLock) {
            int count = mViews.size();
            //Log.i("foo", "Closing all windows of " + token);
            for (int i = 0; i < count; i++) {
                //Log.i("foo", "@ " + i + " token " + mParams[i].token
                //        + " view " + mRoots[i].getView());
                if (token == null || mParams.get(i).token == token) {
                    ViewRootImpl root = mRoots.get(i);

                    //Log.i("foo", "Force closing " + root);
                    if (who != null) {
                        WindowLeaked leak = new WindowLeaked(
                                what + " " + who + " has leaked window "
                                + root.getView() + " that was originally added here");
                        leak.setStackTrace(root.getLocation().getStackTrace());
                        Log.e(TAG, "", leak);
                    }

                    removeViewLocked(i, false);
                }
            }
        }
    }
like image 606
JackWM Avatar asked Mar 21 '26 11:03

JackWM


1 Answers

I checked the source... I'm not totally sure about it but her goes my understanding...

"who" argument is Activity Name only

Checking closeAll() calling methods, you can see that who is just the Activity class name that was destroyed and left one window behind:

WindowManagerGlobal.getInstance().closeAll(wtoken,
                        r.activity.getClass().getName(), "Activity");

closeAll() is called if leaked occurred

It seems that WindowManagerGlobal.closeAll() is called when the Windows has leaked already. So, who != null it just a check to ensure that String is not NULL.

If not null, a WindowLeaked is created and log is printed. WindowLeaked is an Class that extends AndroidRuntimeException

final class WindowLeaked extends AndroidRuntimeException {
    public WindowLeaked(String msg) {
        super(msg);
    }
}

Most important is the fact that if WindowManagerGlobal.closeAll() is called, it means that the Windows has leaked already.

CloseAll() calling method

In View.java, we can see that WindowManagerGlobal.closeAll() is called when a leacked is detected:

ActivityThread.java

private void handleDestroyActivity(IBinder token, boolean finishing,
                                    int configChanges, boolean getNonConfigInstance) {
    ...
    IBinder wtoken = v.getWindowToken();
    ...
    if (wtoken != null && r.mPendingRemoveWindow == null) {
        WindowManagerGlobal.getInstance().closeAll(wtoken,
                r.activity.getClass().getName(), "Activity");
    }

In the code above, we can see that WindowManagerGlobal.closeAll() is fired when an inconsistency is found:

  1. wtoken != null wtoken shows that View has an mAttachInfo.mWindowToken information. In other words, it is still held by some window.
  2. r.mPendingRemoveWindow == null there's no pending view to be removed.

So, it is inconsistent. One view is attached (has an mAttachInfo yet) but I've already remove all pending windows (mPendingRemoveWindow is null)... So, that view has leaked.

Hope I could help you Regards

REF:

WindowManagerGlobal

ActivityThread

View

like image 186
W0rmH0le Avatar answered Mar 24 '26 01:03

W0rmH0le