diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 45db0f6ff3e29..fd6fa57b9e8d1 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -749,7 +749,8 @@ public class Instrumentation { * @see #onStartActivity(Intent) * @hide */ - public ActivityResult onStartActivity(Context who, Intent intent, Bundle options) { + public ActivityResult onStartActivity(@NonNull Context who, @NonNull Intent intent, + @NonNull Bundle options) { return onStartActivity(intent); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionProvider.java index b7a60392c5125..ce4e10364ba24 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionProvider.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionProvider.java @@ -18,6 +18,10 @@ package androidx.window.extensions; import android.content.Context; +import androidx.annotation.NonNull; +import androidx.window.extensions.embedding.ActivityEmbeddingComponent; +import androidx.window.extensions.organizer.EmbeddingExtensionImpl; + /** * Provider class that will instantiate the library implementation. It must be included in the * vendor library, and the vendor implementation must match the signature of this class. @@ -31,6 +35,12 @@ public class ExtensionProvider { return new SampleExtensionImpl(context); } + /** Provides a reference implementation of {@link ActivityEmbeddingComponent}. */ + public static ActivityEmbeddingComponent getActivityEmbeddingExtensionImpl( + @NonNull Context context) { + return new EmbeddingExtensionImpl(); + } + /** * The support library will use this method to check API version compatibility. * @return API version string in MAJOR.MINOR.PATCH-description format. diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java index cafc2337a022c..a0d5b004ff1c0 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java @@ -23,19 +23,15 @@ import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; import android.app.Activity; import android.content.Context; -import android.content.Intent; import android.graphics.Rect; -import android.os.Bundle; import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.window.common.DeviceStateManagerPostureProducer; import androidx.window.common.DisplayFeature; import androidx.window.common.ResourceConfigDisplayFeatureProducer; import androidx.window.common.SettingsDevicePostureProducer; import androidx.window.common.SettingsDisplayFeatureProducer; -import androidx.window.extensions.organizer.SplitController; import androidx.window.util.DataProducer; import androidx.window.util.PriorityDataProducer; @@ -60,8 +56,6 @@ class SampleExtensionImpl extends StubExtension { private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; private final DataProducer> mDisplayFeatureProducer; - private final SplitController mSplitController; - SampleExtensionImpl(Context context) { mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); mDevicePostureProducer = new PriorityDataProducer<>(List.of( @@ -77,8 +71,6 @@ class SampleExtensionImpl extends StubExtension { mDevicePostureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); - - mSplitController = new SplitController(); } private int getFeatureState(DisplayFeature feature) { @@ -142,28 +134,4 @@ class SampleExtensionImpl extends StubExtension { onDisplayFeaturesChanged(); } - - @Override - public void setSplitRules(@NonNull List splitRules) { - mSplitController.setSplitRules(splitRules); - } - - @Override - @NonNull - public List getSplitRules() { - return new ArrayList<>(mSplitController.getSplitRules()); - } - - @Override - public void setSplitOrganizerCallback(@Nullable SplitOrganizerCallback callback) { - mSplitController.setSplitOrganizerCallback(callback); - } - - @Override - public void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent intent, - @Nullable Bundle options, @NonNull ExtensionSplitPairRule splitPairRule, - int startRequestId) { - mSplitController.startActivityToSide(launchingActivity, intent, options, splitPairRule, - startRequestId); - } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/EmbeddingExtensionImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/EmbeddingExtensionImpl.java new file mode 100644 index 0000000000000..9a8961f1d460b --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/EmbeddingExtensionImpl.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 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.organizer; + +import androidx.annotation.NonNull; +import androidx.window.extensions.embedding.ActivityEmbeddingComponent; +import androidx.window.extensions.embedding.EmbeddingRule; +import androidx.window.extensions.embedding.SplitInfo; + +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +/** + * Reference implementation of the activity embedding interface defined in WM Jetpack. + */ +public class EmbeddingExtensionImpl implements ActivityEmbeddingComponent { + + private final SplitController mSplitController; + + public EmbeddingExtensionImpl() { + mSplitController = new SplitController(); + } + + @Override + public void setEmbeddingRules(@NonNull Set rules) { + mSplitController.setEmbeddingRules(rules); + } + + @Override + public void setEmbeddingCallback(@NonNull Consumer> consumer) { + mSplitController.setEmbeddingCallback(consumer); + } +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java index ade8573589877..8fd710a7986d3 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java @@ -19,7 +19,9 @@ package androidx.window.extensions.organizer; import android.annotation.NonNull; import android.app.Activity; -import androidx.window.extensions.ExtensionSplitPairRule; +import androidx.window.extensions.embedding.SplitPairRule; +import androidx.window.extensions.embedding.SplitPlaceholderRule; +import androidx.window.extensions.embedding.SplitRule; /** * Client-side descriptor of a split that holds two containers. @@ -27,20 +29,26 @@ import androidx.window.extensions.ExtensionSplitPairRule; class SplitContainer { private final TaskFragmentContainer mPrimaryContainer; private final TaskFragmentContainer mSecondaryContainer; - private final ExtensionSplitPairRule mSplitPairRule; + private final SplitRule mSplitRule; SplitContainer(@NonNull TaskFragmentContainer primaryContainer, @NonNull Activity primaryActivity, @NonNull TaskFragmentContainer secondaryContainer, - @NonNull ExtensionSplitPairRule splitPairRule) { + @NonNull SplitRule splitRule) { mPrimaryContainer = primaryContainer; mSecondaryContainer = secondaryContainer; - mSplitPairRule = splitPairRule; + mSplitRule = splitRule; - if (mSplitPairRule.finishPrimaryWithSecondary || mSplitPairRule.useAsPlaceholder) { + final boolean isPlaceholderContainer = isPlaceholderContainer(); + final boolean shouldFinishPrimaryWithSecondary = (mSplitRule instanceof SplitPairRule) + && ((SplitPairRule) mSplitRule).shouldFinishPrimaryWithSecondary(); + final boolean shouldFinishSecondaryWithPrimary = (mSplitRule instanceof SplitPairRule) + && ((SplitPairRule) mSplitRule).shouldFinishSecondaryWithPrimary(); + + if (shouldFinishPrimaryWithSecondary || isPlaceholderContainer) { mSecondaryContainer.addActivityToFinishOnExit(primaryActivity); } - if (mSplitPairRule.finishSecondaryWithPrimary || mSplitPairRule.useAsPlaceholder) { + if (shouldFinishSecondaryWithPrimary || isPlaceholderContainer) { mPrimaryContainer.addContainerToFinishOnExit(mSecondaryContainer); } } @@ -56,7 +64,11 @@ class SplitContainer { } @NonNull - ExtensionSplitPairRule getSplitPairRule() { - return mSplitPairRule; + SplitRule getSplitRule() { + return mSplitRule; + } + + boolean isPlaceholderContainer() { + return (mSplitRule instanceof SplitPlaceholderRule); } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java index c4ec4627f6cb8..05c6792a3fc75 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java @@ -24,7 +24,6 @@ import android.app.ActivityOptions; import android.app.ActivityThread; import android.app.Application.ActivityLifecycleCallbacks; import android.app.Instrumentation; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; @@ -32,20 +31,24 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.util.Pair; import android.window.TaskFragmentAppearedInfo; import android.window.TaskFragmentInfo; import android.window.WindowContainerTransaction; -import androidx.window.extensions.ExtensionInterface.SplitOrganizerCallback; -import androidx.window.extensions.ExtensionSplitActivityRule; -import androidx.window.extensions.ExtensionSplitInfo; -import androidx.window.extensions.ExtensionSplitPairRule; -import androidx.window.extensions.ExtensionSplitRule; -import androidx.window.extensions.ExtensionTaskFragment; +import androidx.window.extensions.embedding.ActivityRule; +import androidx.window.extensions.embedding.EmbeddingRule; +import androidx.window.extensions.embedding.SplitInfo; +import androidx.window.extensions.embedding.SplitPairRule; +import androidx.window.extensions.embedding.SplitPlaceholderRule; +import androidx.window.extensions.embedding.SplitRule; +import androidx.window.extensions.embedding.TaskFragment; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.Executor; +import java.util.function.Consumer; /** * Main controller class that manages split states and presentation. @@ -55,12 +58,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen private final SplitPresenter mPresenter; // Currently applied split configuration. - private final List mSplitRules = new ArrayList<>(); + private final List mSplitRules = new ArrayList<>(); private final List mContainers = new ArrayList<>(); private final List mSplitContainers = new ArrayList<>(); // Callback to Jetpack to notify about changes to split states. - private SplitOrganizerCallback mSplitOrganizerCallback; + private @NonNull Consumer> mEmbeddingCallback; public SplitController() { mPresenter = new SplitPresenter(new MainThreadExecutor(), this); @@ -73,13 +76,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen instrumentation.addMonitor(new ActivityStartMonitor()); } - public void setSplitRules(@NonNull List splitRules) { + /** Updates the embedding rules applied to future activity launches. */ + public void setEmbeddingRules(@NonNull Set rules) { mSplitRules.clear(); - mSplitRules.addAll(splitRules); + mSplitRules.addAll(rules); } @NonNull - public List getSplitRules() { + public List getSplitRules() { return mSplitRules; } @@ -87,22 +91,20 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen * Starts an activity to side of the launchingActivity with the provided split config. */ public void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent intent, - @Nullable Bundle options, @NonNull ExtensionSplitPairRule splitPairRule, - int startRequestId) { + @Nullable Bundle options, @NonNull SplitRule sideRule, + @NonNull Consumer failureCallback) { try { - mPresenter.startActivityToSide(launchingActivity, intent, options, splitPairRule); + mPresenter.startActivityToSide(launchingActivity, intent, options, sideRule); } catch (Exception e) { - if (mSplitOrganizerCallback != null && startRequestId != -1) { - mSplitOrganizerCallback.onActivityFailedToStartInContainer(startRequestId, e); - } + failureCallback.accept(e); } } /** * Registers the split organizer callback to notify about changes to active splits. */ - public void setSplitOrganizerCallback(@NonNull SplitOrganizerCallback callback) { - mSplitOrganizerCallback = callback; + public void setEmbeddingCallback(@NonNull Consumer> callback) { + mEmbeddingCallback = callback; updateCallbackIfNecessary(); } @@ -160,14 +162,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen */ // TODO(b/190433398): Break down into smaller functions. void onActivityCreated(@NonNull Activity launchedActivity) { - final ComponentName componentName = launchedActivity.getComponentName(); - - final List splitRules = getSplitRules(); + final List splitRules = getSplitRules(); final TaskFragmentContainer currentContainer = getContainerWithActivity( launchedActivity.getActivityToken(), launchedActivity); // Check if the activity is configured to always be expanded. - if (shouldExpand(componentName, splitRules)) { + if (shouldExpand(launchedActivity, splitRules)) { if (shouldContainerBeExpanded(currentContainer)) { // Make sure that the existing container is expanded mPresenter.expandTaskFragment(currentContainer.getTaskFragmentToken()); @@ -224,8 +224,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } - final ExtensionSplitPairRule splitPairRule = getSplitRule( - activityBelow.getComponentName(), componentName, splitRules); + final SplitPairRule splitPairRule = getSplitRule(activityBelow, launchedActivity, + splitRules); if (splitPairRule == null) { return; } @@ -302,11 +302,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen void registerSplit(@NonNull WindowContainerTransaction wct, @NonNull TaskFragmentContainer primaryContainer, @NonNull Activity primaryActivity, @NonNull TaskFragmentContainer secondaryContainer, - @NonNull ExtensionSplitPairRule splitPairRule) { - removeExistingSecondaryContainers(wct, primaryContainer); - + @NonNull SplitRule splitRule) { + if (splitRule instanceof SplitPairRule && ((SplitPairRule) splitRule).shouldClearTop()) { + removeExistingSecondaryContainers(wct, primaryContainer); + } SplitContainer splitContainer = new SplitContainer(primaryContainer, primaryActivity, - secondaryContainer, splitPairRule); + secondaryContainer, splitRule); mSplitContainers.add(splitContainer); } @@ -456,22 +457,20 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } // Check if there is enough space for launch - final ExtensionSplitPairRule placeholderRule = getPlaceholderRule( - activity.getComponentName()); + final SplitPlaceholderRule placeholderRule = getPlaceholderRule(activity); if (placeholderRule == null || !mPresenter.shouldShowSideBySide( mPresenter.getParentContainerBounds(activity), placeholderRule)) { return false; } - Intent placeholderIntent = new Intent(); - placeholderIntent.setComponent(placeholderRule.secondaryActivityName); // TODO(b/190433398): Handle failed request - startActivityToSide(activity, placeholderIntent, null, placeholderRule, -1); + startActivityToSide(activity, placeholderRule.getPlaceholderIntent(), null, + placeholderRule, null); return true; } private boolean dismissPlaceholderIfNecessary(@NonNull SplitContainer splitContainer) { - if (!splitContainer.getSplitPairRule().useAsPlaceholder) { + if (!splitContainer.isPlaceholderContainer()) { return false; } @@ -488,15 +487,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen * Returns the rule to launch a placeholder for the activity with the provided component name * if it is configured in the split config. */ - private ExtensionSplitPairRule getPlaceholderRule(@NonNull ComponentName componentName) { - for (ExtensionSplitRule rule : mSplitRules) { - if (!(rule instanceof ExtensionSplitPairRule)) { + private SplitPlaceholderRule getPlaceholderRule(@NonNull Activity activity) { + for (EmbeddingRule rule : mSplitRules) { + if (!(rule instanceof SplitPlaceholderRule)) { continue; } - ExtensionSplitPairRule pairRule = (ExtensionSplitPairRule) rule; - if (componentName.equals(pairRule.primaryActivityName) - && pairRule.useAsPlaceholder) { - return pairRule; + SplitPlaceholderRule placeholderRule = (SplitPlaceholderRule) rule; + if (placeholderRule.getActivityPredicate().test(activity)) { + return placeholderRule; } } return null; @@ -506,27 +504,27 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen * Notifies listeners about changes to split states if necessary. */ private void updateCallbackIfNecessary() { - if (mSplitOrganizerCallback == null) { + if (mEmbeddingCallback == null) { return; } // TODO(b/190433398): Check if something actually changed - mSplitOrganizerCallback.onSplitInfoChanged(getActiveSplitStates()); + mEmbeddingCallback.accept(getActiveSplitStates()); } /** * Returns a list of descriptors for currently active split states. */ - private List getActiveSplitStates() { - List splitStates = new ArrayList<>(); + private List getActiveSplitStates() { + List splitStates = new ArrayList<>(); for (SplitContainer container : mSplitContainers) { - ExtensionTaskFragment primaryContainer = - new ExtensionTaskFragment( + TaskFragment primaryContainer = + new TaskFragment( container.getPrimaryContainer().collectActivities()); - ExtensionTaskFragment secondaryContainer = - new ExtensionTaskFragment( + TaskFragment secondaryContainer = + new TaskFragment( container.getSecondaryContainer().collectActivities()); - ExtensionSplitInfo splitState = new ExtensionSplitInfo(primaryContainer, - secondaryContainer, container.getSplitPairRule().splitRatio); + SplitInfo splitState = new SplitInfo(primaryContainer, + secondaryContainer, container.getSplitRule().getSplitRatio()); splitStates.add(splitState); } return splitStates; @@ -550,23 +548,41 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } /** - * Returns a split rule for the provided pair of component names if available. + * Returns a split rule for the provided pair of primary activity and secondary activity intent + * if available. */ @Nullable - private static ExtensionSplitPairRule getSplitRule(@NonNull ComponentName primaryActivityName, - @NonNull ComponentName secondaryActivityName, - @NonNull List splitRules) { - if (splitRules == null || primaryActivityName == null || secondaryActivityName == null) { - return null; - } - - for (ExtensionSplitRule rule : splitRules) { - if (!(rule instanceof ExtensionSplitPairRule)) { + private static SplitPairRule getSplitRule(@NonNull Activity primaryActivity, + @NonNull Intent secondaryActivityIntent, @NonNull List splitRules) { + for (EmbeddingRule rule : splitRules) { + if (!(rule instanceof SplitPairRule)) { continue; } - ExtensionSplitPairRule pairRule = (ExtensionSplitPairRule) rule; - if (match(secondaryActivityName, pairRule.secondaryActivityName) - && match(primaryActivityName, pairRule.primaryActivityName)) { + SplitPairRule pairRule = (SplitPairRule) rule; + if (pairRule.getActivityIntentPredicate().test( + new Pair(primaryActivity, secondaryActivityIntent))) { + return pairRule; + } + } + return null; + } + + /** + * Returns a split rule for the provided pair of primary and secondary activities if available. + */ + @Nullable + private static SplitPairRule getSplitRule(@NonNull Activity primaryActivity, + @NonNull Activity secondaryActivity, @NonNull List splitRules) { + for (EmbeddingRule rule : splitRules) { + if (!(rule instanceof SplitPairRule)) { + continue; + } + SplitPairRule pairRule = (SplitPairRule) rule; + final Intent intent = secondaryActivity.getIntent(); + if (pairRule.getActivityPairPredicate().test( + new Pair(primaryActivity, secondaryActivity)) + && (intent == null || pairRule.getActivityIntentPredicate().test( + new Pair(primaryActivity, intent)))) { return pairRule; } } @@ -587,55 +603,26 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen * Returns {@code true} if an Activity with the provided component name should always be * expanded to occupy full task bounds. Such activity must not be put in a split. */ - private static boolean shouldExpand(@NonNull ComponentName componentName, - List splitRules) { + private static boolean shouldExpand(@NonNull Activity activity, + List splitRules) { if (splitRules == null) { return false; } - for (ExtensionSplitRule rule : splitRules) { - if (!(rule instanceof ExtensionSplitActivityRule)) { + for (EmbeddingRule rule : splitRules) { + if (!(rule instanceof ActivityRule)) { continue; } - ExtensionSplitActivityRule activityRule = (ExtensionSplitActivityRule) rule; - if (match(componentName, activityRule.activityName) - && activityRule.alwaysExpand) { + ActivityRule activityRule = (ActivityRule) rule; + if (!activityRule.shouldAlwaysExpand()) { + continue; + } + if (activityRule.getActivityPredicate().test(activity)) { return true; } } return false; } - /** Match check allowing wildcards for activity class name but not package name. */ - private static boolean match(@NonNull ComponentName activityComponent, - @NonNull ComponentName ruleComponent) { - if (activityComponent.toString().contains("*")) { - throw new IllegalArgumentException("Wildcard can only be part of the rule."); - } - final boolean packagesMatch = - activityComponent.getPackageName().equals(ruleComponent.getPackageName()); - final boolean classesMatch = - activityComponent.getClassName().equals(ruleComponent.getClassName()); - return packagesMatch && (classesMatch - || wildcardMatch(activityComponent.getClassName(), ruleComponent.getClassName())); - } - - /** - * Checks if the provided name matches the pattern. - */ - private static boolean wildcardMatch(@NonNull String name, @NonNull String pattern) { - if (!pattern.contains("*")) { - return false; - } - if (pattern.equals("*")) { - return true; - } - if (pattern.indexOf("*") != pattern.lastIndexOf("*") || !pattern.endsWith("*")) { - throw new IllegalArgumentException( - "Name pattern with a wildcard must only contain a single * in the end"); - } - return name.startsWith(pattern.substring(0, pattern.length() - 1)); - } - private final class LifecycleCallbacks implements ActivityLifecycleCallbacks { @Override @@ -698,8 +685,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen private class ActivityStartMonitor extends Instrumentation.ActivityMonitor { @Override - public Instrumentation.ActivityResult onStartActivity(Context who, Intent intent, - Bundle options) { + public Instrumentation.ActivityResult onStartActivity(@NonNull Context who, + @NonNull Intent intent, @NonNull Bundle options) { // TODO(b/190433398): Check if the activity is configured to always be expanded. // Check if activity should be put in a split with the activity that launched it. @@ -722,8 +709,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen */ private boolean setLaunchingToSideContainer(Activity launchingActivity, Intent intent, Bundle options) { - final ExtensionSplitPairRule splitPairRule = getSplitRule( - launchingActivity.getComponentName(), intent.getComponent(), getSplitRules()); + final SplitPairRule splitPairRule = getSplitRule(launchingActivity, intent, + getSplitRules()); if (splitPairRule == null) { return false; } @@ -770,8 +757,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } - final ExtensionSplitPairRule splitPairRule = getSplitRule( - primaryActivity.getComponentName(), intent.getComponent(), getSplitRules()); + final SplitPairRule splitPairRule = getSplitRule(primaryActivity, intent, + getSplitRules()); if (splitPairRule == null) { return; } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java index 47a1519ee6052..a7bce20cae8b8 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java @@ -24,13 +24,16 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; +import android.view.WindowInsets; +import android.view.WindowMetrics; import android.window.TaskFragmentCreationParams; import android.window.WindowContainerTransaction; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.window.extensions.ExtensionSplitPairRule; +import androidx.window.extensions.embedding.SplitPairRule; +import androidx.window.extensions.embedding.SplitRule; import java.util.concurrent.Executor; @@ -89,7 +92,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { * @return The newly created secondary container. */ TaskFragmentContainer createNewSplitWithEmptySideContainer(@NonNull Activity primaryActivity, - @NonNull ExtensionSplitPairRule rule) { + @NonNull SplitPairRule rule) { final WindowContainerTransaction wct = new WindowContainerTransaction(); final Rect parentBounds = getParentContainerBounds(primaryActivity); @@ -128,7 +131,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { * @param rule The split rule to be applied to the container. */ void createNewSplitContainer(@NonNull Activity primaryActivity, - @NonNull Activity secondaryActivity, @NonNull ExtensionSplitPairRule rule) { + @NonNull Activity secondaryActivity, @NonNull SplitPairRule rule) { final WindowContainerTransaction wct = new WindowContainerTransaction(); final Rect parentBounds = getParentContainerBounds(primaryActivity); @@ -192,7 +195,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { * @param rule The split rule to be applied to the container. */ void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent activityIntent, - @Nullable Bundle activityOptions, @NonNull ExtensionSplitPairRule rule) { + @Nullable Bundle activityOptions, @NonNull SplitRule rule) { final Rect parentBounds = getParentContainerBounds(launchingActivity); final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule); final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule); @@ -227,7 +230,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { @NonNull WindowContainerTransaction wct) { // Getting the parent bounds using the updated container - it will have the recent value. final Rect parentBounds = getParentContainerBounds(updatedContainer); - final ExtensionSplitPairRule rule = splitContainer.getSplitPairRule(); + final SplitRule rule = splitContainer.getSplitRule(); final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule); final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule); @@ -273,24 +276,24 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { boolean shouldShowSideBySide(@NonNull SplitContainer splitContainer) { final Rect parentBounds = getParentContainerBounds(splitContainer.getPrimaryContainer()); - return shouldShowSideBySide(parentBounds, splitContainer.getSplitPairRule()); + return shouldShowSideBySide(parentBounds, splitContainer.getSplitRule()); } - boolean shouldShowSideBySide(@Nullable Rect parentBounds, - @NonNull ExtensionSplitPairRule rule) { - return parentBounds != null && parentBounds.width() >= rule.minWidth - // TODO(b/190433398): Consider proper smallest width computation. - && Math.min(parentBounds.width(), parentBounds.height()) >= rule.minSmallestWidth; + boolean shouldShowSideBySide(@Nullable Rect parentBounds, @NonNull SplitRule rule) { + // TODO(b/190433398): Supply correct insets. + final WindowMetrics parentMetrics = new WindowMetrics(parentBounds, + new WindowInsets(new Rect())); + return rule.getParentWindowMetricsPredicate().test(parentMetrics); } @NonNull private Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds, - @NonNull ExtensionSplitPairRule rule) { + @NonNull SplitRule rule) { if (!shouldShowSideBySide(parentBounds, rule)) { return new Rect(); } - float splitRatio = rule.splitRatio; + float splitRatio = rule.getSplitRatio(); switch (position) { case POSITION_LEFT: return new Rect( diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar index fdbc5f61c4513..097febf9770ae 100644 Binary files a/libs/WindowManager/Jetpack/window-extensions-release.aar and b/libs/WindowManager/Jetpack/window-extensions-release.aar differ