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

Commit c77e0e6f authored by Kenneth Ford's avatar Kenneth Ford Committed by Automerger Merge Worker
Browse files

Fixes concurrent display test flakiness am: c3b80dc7 am: e3f0e8ae

parents e4dd3926 e3f0e8ae
Loading
Loading
Loading
Loading
+8 −28
Original line number Diff line number Diff line
@@ -20,9 +20,6 @@ import static androidx.window.extensions.area.WindowAreaComponent.SESSION_STATE_
import static androidx.window.extensions.area.WindowAreaComponent.SESSION_STATE_INACTIVE;

import android.content.Context;
import android.hardware.devicestate.DeviceStateRequest;
import android.hardware.display.DisplayManager;
import android.util.Log;
import android.view.Display;

import androidx.annotation.NonNull;
@@ -32,17 +29,12 @@ import androidx.window.extensions.core.util.function.Consumer;
import java.util.Objects;

/**
 * Controller class that keeps track of the status of the device state request
 * to enable the rear display presentation feature. This controller notifies the session callback
 * when the state request is active, and notifies the callback when the request is canceled.
 *
 * Clients are notified via {@link Consumer} provided with
 * {@link androidx.window.extensions.area.WindowAreaComponent.WindowAreaStatus} values to signify
 * when the request becomes active and cancelled.
 * Controller class that manages the creation of the {@link android.app.Presentation} object used
 * to show content on the rear facing display. This controller notifies the session callback with
 * {@link androidx.window.extensions.area.WindowAreaComponent.WindowAreaStatus} values when the
 * feature is active, or when the feature has been ended.
 */
class RearDisplayPresentationController implements DeviceStateRequest.Callback {

    private static final String TAG = "RearDisplayPresentationController";
class RearDisplayPresentationController {

    // Original context that requested to enable rear display presentation mode
    @NonNull
@@ -51,8 +43,6 @@ class RearDisplayPresentationController implements DeviceStateRequest.Callback {
    private final Consumer<@WindowAreaComponent.WindowAreaSessionState Integer> mStateConsumer;
    @Nullable
    private ExtensionWindowAreaPresentation mExtensionWindowAreaPresentation;
    @NonNull
    private final DisplayManager mDisplayManager;

    /**
     * Creates the RearDisplayPresentationController
@@ -71,25 +61,15 @@ class RearDisplayPresentationController implements DeviceStateRequest.Callback {

        mContext = context;
        mStateConsumer = stateConsumer;
        mDisplayManager = context.getSystemService(DisplayManager.class);
    }

    @Override
    public void onRequestActivated(@NonNull DeviceStateRequest request) {
        Display[] rearDisplays = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_REAR);
        if (rearDisplays.length == 0) {
            mStateConsumer.accept(SESSION_STATE_INACTIVE);
            Log.e(TAG, "Rear display list should not be empty");
            return;
    }

    public void startSession(@NonNull Display rearDisplay) {
        mExtensionWindowAreaPresentation =
                new RearDisplayPresentation(mContext, rearDisplays[0], mStateConsumer);
                new RearDisplayPresentation(mContext, rearDisplay, mStateConsumer);
        mStateConsumer.accept(SESSION_STATE_ACTIVE);
    }

    @Override
    public void onRequestCanceled(@NonNull DeviceStateRequest request) {
    public void endSession() {
        mStateConsumer.accept(SESSION_STATE_INACTIVE);
    }

+115 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.window.extensions.area;

import android.content.Context;
import android.hardware.devicestate.DeviceStateRequest;
import android.hardware.display.DisplayManager;
import android.view.Display;

import androidx.annotation.NonNull;

/**
 * Callback class to be notified of updates to a {@link DeviceStateRequest} for the rear display
 * presentation state. This class notifies the {@link RearDisplayPresentationController} when the
 * device is ready to enable the rear display presentation feature.
 */
public class RearDisplayPresentationRequestCallback implements DeviceStateRequest.Callback {

    private static final String TAG = RearDisplayPresentationRequestCallback.class.getSimpleName();

    @NonNull
    private final DisplayManager mDisplayManager;
    @NonNull
    private final DisplayManager.DisplayListener mRearDisplayListener = new RearDisplayListener();
    @NonNull
    private final RearDisplayPresentationController mRearDisplayPresentationController;
    private boolean mWaitingForRearDisplay = false;

    public RearDisplayPresentationRequestCallback(@NonNull Context context,
            @NonNull RearDisplayPresentationController rearDisplayPresentationController) {
        mDisplayManager = context.getSystemService(DisplayManager.class);
        mDisplayManager.registerDisplayListener(mRearDisplayListener,
                context.getMainThreadHandler(), DisplayManager.EVENT_FLAG_DISPLAY_ADDED
                        | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED);

        mRearDisplayPresentationController = rearDisplayPresentationController;
    }

    @Override
    public void onRequestActivated(@NonNull DeviceStateRequest request) {
        Display[] rearDisplays = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_REAR);
        if (rearDisplays.length == 0) {
            // No rear facing display found, marking waiting for display flag as true.
            mWaitingForRearDisplay = true;
            return;
        }
        mDisplayManager.unregisterDisplayListener(mRearDisplayListener);
        mRearDisplayPresentationController.startSession(rearDisplays[0]);
    }

    @Override
    public void onRequestCanceled(@NonNull DeviceStateRequest request) {
        mDisplayManager.unregisterDisplayListener(mRearDisplayListener);
        mRearDisplayPresentationController.endSession();
    }

    /**
     * {@link DisplayManager.DisplayListener} to be used if a rear facing {@link Display} isn't
     * available synchronously when the device is entered into the rear display presentation state.
     * A rear facing {@link Display} is a {@link Display} that is categorized as
     * {@link DisplayManager#DISPLAY_CATEGORY_REAR}. This can occur if {@link DisplayManager} is
     * still in the process of configuring itself for this state when
     * {@link DeviceStateRequest.Callback#onRequestActivated} is called.
     *
     * The {@link DisplayManager.DisplayListener} removes itself when a rear facing display is
     * found.
     */
    private class RearDisplayListener implements DisplayManager.DisplayListener {
        @Override
        public void onDisplayAdded(int displayId) {
            Display display = mDisplayManager.getDisplay(displayId);
            if (mWaitingForRearDisplay && (display.getFlags() & Display.FLAG_REAR) != 0) {
                startRearDisplayPresentation(display);
            }
        }

        @Override
        public void onDisplayRemoved(int displayId) {}

        @Override
        public void onDisplayChanged(int displayId) {
            Display display = mDisplayManager.getDisplay(displayId);
            if (mWaitingForRearDisplay && (display.getFlags() & Display.FLAG_REAR) != 0) {
                startRearDisplayPresentation(display);
            }
        }

        /**
         * Starts a new {@link RearDisplayPresentation} with the updated {@link Display} with a
         * category of {@link DisplayManager#DISPLAY_CATEGORY_REAR}.
         */
        private void startRearDisplayPresentation(Display rearDisplay) {
            // We have been notified of a change to a rear display, we can unregister the
            // callback and stop waiting for a display
            mDisplayManager.unregisterDisplayListener(this);
            mWaitingForRearDisplay = false;

            mRearDisplayPresentationController.startSession(rearDisplay);
        }
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -337,13 +337,15 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
                            consumer.accept(stateStatus);
                        }
                    });

            RearDisplayPresentationRequestCallback deviceStateCallback =
                    new RearDisplayPresentationRequestCallback(activity,
                            mRearDisplayPresentationController);
            DeviceStateRequest concurrentDisplayStateRequest = DeviceStateRequest.newBuilder(
                    mConcurrentDisplayState).build();
            mDeviceStateManager.requestState(
                    concurrentDisplayStateRequest,
                    mExecutor,
                    mRearDisplayPresentationController
                    deviceStateCallback
            );
        }
    }