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

Commit db133abb authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "Listen to folding state change for SplitController" into tm-qpr-dev

parents 501b654c fe23ec48
Loading
Loading
Loading
Loading
+50 −5
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package androidx.window.extensions.embedding;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_OP_TYPE;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO;
import static android.window.TaskFragmentOrganizer.KEY_ERROR_CALLBACK_THROWABLE;
@@ -46,6 +47,7 @@ import android.app.Activity;
import android.app.ActivityClient;
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.Application;
import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
@@ -70,12 +72,16 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
import androidx.window.extensions.WindowExtensionsProvider;
import androidx.window.extensions.layout.WindowLayoutComponentImpl;

import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -106,26 +112,65 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    @GuardedBy("mLock")
    final SparseArray<TaskContainer> mTaskContainers = new SparseArray<>();

    // Callback to Jetpack to notify about changes to split states.
    @NonNull
    /** Callback to Jetpack to notify about changes to split states. */
    @Nullable
    private Consumer<List<SplitInfo>> mEmbeddingCallback;
    private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
    private final Handler mHandler;
    final Object mLock = new Object();
    private final ActivityStartMonitor mActivityStartMonitor;
    @NonNull
    final WindowLayoutComponentImpl mWindowLayoutComponent;

    public SplitController() {
        this((WindowLayoutComponentImpl) Objects.requireNonNull(WindowExtensionsProvider
                .getWindowExtensions().getWindowLayoutComponent()));
    }

    @VisibleForTesting
    SplitController(@NonNull WindowLayoutComponentImpl windowLayoutComponent) {
        final MainThreadExecutor executor = new MainThreadExecutor();
        mHandler = executor.mHandler;
        mPresenter = new SplitPresenter(executor, this);
        ActivityThread activityThread = ActivityThread.currentActivityThread();
        final ActivityThread activityThread = ActivityThread.currentActivityThread();
        final Application application = activityThread.getApplication();
        // Register a callback to be notified about activities being created.
        activityThread.getApplication().registerActivityLifecycleCallbacks(
                new LifecycleCallbacks());
        application.registerActivityLifecycleCallbacks(new LifecycleCallbacks());
        // Intercept activity starts to route activities to new containers if necessary.
        Instrumentation instrumentation = activityThread.getInstrumentation();

        mActivityStartMonitor = new ActivityStartMonitor();
        instrumentation.addMonitor(mActivityStartMonitor);
        mWindowLayoutComponent = windowLayoutComponent;
        mWindowLayoutComponent.addFoldingStateChangedCallback(new FoldingFeatureListener());
    }

    private class FoldingFeatureListener implements Consumer<List<CommonFoldingFeature>> {
        @Override
        public void accept(List<CommonFoldingFeature> foldingFeatures) {
            synchronized (mLock) {
                final WindowContainerTransaction wct = new WindowContainerTransaction();
                for (int i = 0; i < mTaskContainers.size(); i++) {
                    final TaskContainer taskContainer = mTaskContainers.valueAt(i);
                    if (!taskContainer.isVisible()) {
                        continue;
                    }
                    if (taskContainer.getDisplayId() != DEFAULT_DISPLAY) {
                        continue;
                    }
                    // TODO(b/238948678): Support reporting display features in all windowing modes.
                    if (taskContainer.isInMultiWindow()) {
                        continue;
                    }
                    if (taskContainer.isEmpty()) {
                        continue;
                    }
                    updateContainersInTask(wct, taskContainer);
                    updateAnimationOverride(taskContainer);
                }
                mPresenter.applyTransaction(wct);
            }
        }
    }

    /** Updates the embedding rules applied to future activity launches. */
+22 −3
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import androidx.window.common.RawFoldingFeatureProducer;
import androidx.window.util.DataProducer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -80,6 +81,11 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
        mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
    }

    /** Registers to listen to {@link CommonFoldingFeature} changes */
    public void addFoldingStateChangedCallback(Consumer<List<CommonFoldingFeature>> consumer) {
        mFoldingFeatureProducer.addDataChangedCallback(consumer);
    }

    /**
     * Adds a listener interested in receiving updates to {@link WindowLayoutInfo}
     *
@@ -225,12 +231,23 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
     */
    private List<DisplayFeature> getDisplayFeatures(
            @NonNull @UiContext Context context, List<CommonFoldingFeature> storedFeatures) {
        List<DisplayFeature> features = new ArrayList<>();
        if (!shouldReportDisplayFeatures(context)) {
            return Collections.emptyList();
        }
        return getDisplayFeatures(context.getDisplayId(),
                context.getResources().getConfiguration().windowConfiguration,
                storedFeatures);
    }

    /** @see #getDisplayFeatures(Context, List) */
    private List<DisplayFeature> getDisplayFeatures(int displayId,
            @NonNull WindowConfiguration windowConfiguration,
            List<CommonFoldingFeature> storedFeatures) {
        List<DisplayFeature> features = new ArrayList<>();
        if (displayId != DEFAULT_DISPLAY) {
            return features;
        }

        int displayId = context.getDisplay().getDisplayId();
        for (CommonFoldingFeature baseFeature : storedFeatures) {
            Integer state = convertToExtensionState(baseFeature.getState());
            if (state == null) {
@@ -238,7 +255,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
            }
            Rect featureRect = baseFeature.getRect();
            rotateRectToDisplayRotation(displayId, featureRect);
            transformToWindowSpaceRect(context, featureRect);
            transformToWindowSpaceRect(windowConfiguration, featureRect);

            if (!isZero(featureRect)) {
                // TODO(b/228641877): Remove guarding when fixed.
@@ -263,6 +280,8 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
            windowingMode = ActivityClient.getInstance().getTaskWindowingMode(
                    context.getActivityToken());
        } else {
            // TODO(b/242674941): use task windowing mode for window context that associates with
            //  activity.
            windowingMode = context.getResources().getConfiguration().windowConfiguration
                    .getWindowingMode();
        }
+13 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import android.app.WindowConfiguration;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
@@ -89,13 +90,21 @@ public final class ExtensionHelper {
    /** Transforms rectangle from absolute coordinate space to the window coordinate space. */
    public static void transformToWindowSpaceRect(@NonNull @UiContext Context context,
            Rect inOutRect) {
        Rect windowRect = getWindowBounds(context);
        if (!Rect.intersects(inOutRect, windowRect)) {
        transformToWindowSpaceRect(getWindowBounds(context), inOutRect);
    }

    /** @see ExtensionHelper#transformToWindowSpaceRect(Context, Rect) */
    public static void transformToWindowSpaceRect(@NonNull WindowConfiguration windowConfiguration,
            Rect inOutRect) {
        transformToWindowSpaceRect(windowConfiguration.getBounds(), inOutRect);
    }

    private static void transformToWindowSpaceRect(@NonNull Rect bounds, @NonNull Rect inOutRect) {
        if (!inOutRect.intersect(bounds)) {
            inOutRect.setEmpty();
            return;
        }
        inOutRect.intersect(windowRect);
        inOutRect.offset(-windowRect.left, -windowRect.top);
        inOutRect.offset(-bounds.left, -bounds.top);
    }

    /**