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

Commit ab67294b authored by wilsonshih's avatar wilsonshih
Browse files

Fix displayId unsynced between app and system server.

If an activity is launched on non-default display and calls setVrModeEnabled
at onCreate stage, the server will move this task to default display. Then
ActivityThread.handleResumeActivity will crash because ViewRootImpl still
use the old display.

First, the launch activity process will create a ClientTransaction
object, with first transaction item is LaunchActivityItem, and lifecycle state
set as ResumeActivityItem. When client side starts to execute this
transaction, ensureActivityConfiguration will schedule MoveToDisplayItem
to another transaction, however, it cannot be execute before first transaction
completes.

We can resolve this problem by using the display ID associated with the
WindowToken for a Window (when available), this will always have the most
up-to-date value from the server.

Also re-sort imports.

bug: 72181603
bug: 112330955
Test: atest CtsActivityManagerDeviceTestCases
Test: atest CtsWindowManagerDeviceTestCases
Test: wm-smoke
Change-Id: I39a59cf3520a15b486e675284f9aed275343d3cf
parent a2e28a4b
Loading
Loading
Loading
Loading
+46 −38
Original line number Diff line number Diff line
@@ -16,41 +16,7 @@

package com.android.server.wm;

import android.annotation.CallSuper;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.power.V1_0.PowerHint;
import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.WindowManager;

import com.android.internal.util.ArrayUtils;
import com.android.server.EventLogTags;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
@@ -60,6 +26,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -74,19 +43,46 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
import static com.android.server.wm.WindowManagerService.logSurface;
import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;

import android.annotation.CallSuper;
import android.content.res.Configuration;
import android.hardware.power.V1_0.PowerHint;
import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.WindowManager;

import com.android.internal.util.ArrayUtils;
import com.android.server.EventLogTags;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/** Root {@link WindowContainer} for the device. */
class RootWindowContainer extends WindowContainer<DisplayContent> {
@@ -301,6 +297,18 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
        return null;
    }

    /** Returns the window token for the input binder if it exist in the system. */
    WindowToken getWindowToken(IBinder binder) {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final DisplayContent dc = mChildren.get(i);
            final WindowToken wtoken = dc.getWindowToken(binder);
            if (wtoken != null) {
                return wtoken;
            }
        }
        return null;
    }

    /** Returns the display object the input window token is currently mapped on. */
    DisplayContent getWindowTokenDisplay(WindowToken token) {
        if (token == null) {
+14 −3
Original line number Diff line number Diff line
@@ -1151,7 +1151,7 @@ public class WindowManagerService extends IWindowManager.Stub
                throw new IllegalStateException("Display has not been initialialized");
            }

            final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);

            if (displayContent == null) {
                Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
@@ -1540,9 +1540,20 @@ public class WindowManagerService extends IWindowManager.Stub
     * that corresponds to a display just added to DisplayManager has not yet been created. This
     * usually means that the call of this method was initiated from outside of Activity or Window
     * Manager. In most cases the regular getter should be used.
     * @param displayId The preferred display Id.
     * @param token The window token associated with the window we are trying to get display for.
     *              if not null then the display of the window token will be returned. Set to null
     *              is there isn't an a token associated with the request.
     * @see RootWindowContainer#getDisplayContent(int)
     */
    private DisplayContent getDisplayContentOrCreate(int displayId) {
    private DisplayContent getDisplayContentOrCreate(int displayId, IBinder token) {
        if (token != null) {
            final WindowToken wToken = mRoot.getWindowToken(token);
            if (wToken != null) {
                return wToken.getDisplayContent();
            }
        }

        DisplayContent displayContent = mRoot.getDisplayContent(displayId);

        // Create an instance if possible instead of waiting for the ActivityManagerService to drive
@@ -7064,7 +7075,7 @@ public class WindowManagerService extends IWindowManager.Stub
        final long token = Binder.clearCallingIdentity();
        try {
            synchronized (mWindowMap) {
                final DisplayContent dc = getDisplayContentOrCreate(displayId);
                final DisplayContent dc = getDisplayContentOrCreate(displayId, null);
                if (dc == null) {
                    throw new IllegalArgumentException(
                            "Trying to register a non existent display.");