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

Commit f4ac3072 authored by Garfield Tan's avatar Garfield Tan
Browse files

Add a null check in case the display is missing.

This is guarding null at last minute to avoid framework crash on a race
condition. If orientation sensor updates proposed rotation and primary
display is disconnected right after that, it's possible that framework
is handling display rotation before it knows primary display is gone,
and surface flinger returns null handle for BUILT_IN_DISPLAY_ID_MAIN.

Bug: 75273516
Test: go/wm-smoke on walleye, with necessary modifications to adapt to
new Pixel Launcher.
Change-Id: I98173a74548f81a23cd1b8e7ad52bd45ee9ef9fb
parent d65f5ed0
Loading
Loading
Loading
Loading
+17 −8
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import static com.android.server.wm.proto.ScreenRotationAnimationProto.STARTED;
import android.content.Context;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.Slog;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.Display;
@@ -268,15 +269,23 @@ class ScreenRotationAnimation {
                    .build();
                    .build();


            // capture a screenshot into the surface we just created
            // capture a screenshot into the surface we just created
            // TODO(multidisplay): we should use the proper display
            final int displayId = SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN;
            final IBinder displayHandle = SurfaceControl.getBuiltInDisplay(displayId);
            // This null check below is to guard a race condition where WMS didn't have a chance to
            // respond to display disconnection before handling rotation , that surfaceflinger may
            // return a null handle here because it doesn't think that display is valid anymore.
            if (displayHandle != null) {
                Surface sur = new Surface();
                Surface sur = new Surface();
                sur.copyFrom(mSurfaceControl);
                sur.copyFrom(mSurfaceControl);
            // TODO(multidisplay): we should use the proper display
                SurfaceControl.screenshot(displayHandle, sur);
            SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
                            SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur);
                t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
                t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
                t.setAlpha(mSurfaceControl, 0);
                t.setAlpha(mSurfaceControl, 0);
                t.show(mSurfaceControl);
                t.show(mSurfaceControl);
                sur.destroy();
                sur.destroy();
            } else {
                Slog.w(TAG, "Built-in display " + displayId + " is null.");
            }
        } catch (OutOfResourcesException e) {
        } catch (OutOfResourcesException e) {
            Slog.w(TAG, "Unable to allocate freeze surface", e);
            Slog.w(TAG, "Unable to allocate freeze surface", e);
        }
        }