From 7d93e0e544a76819f40831f3ad8fab0c60cb9132 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Mon, 13 Sep 2021 13:05:04 -0700 Subject: [PATCH 1/5] Update reference WM layout component interface Moved to androidx.window.extensions.layout package. Removed ExtensionProvider. Updated method signatures. Bug: 190433972 Test: Manual, using the sample app from AndroidX Change-Id: I6c98ced7b447f231455723a8dc601a46653a48de --- .../window/extensions/ExtensionProvider.java | 51 ---------- .../window/extensions/StubExtension.java | 72 -------------- .../ActivityEmbeddingComponentProvider.java | 65 +++++++++++++ .../WindowLayoutComponent.java} | 91 +++++++++++++++--- .../organizer/EmbeddingExtensionImpl.java | 48 --------- .../extensions/organizer/SplitController.java | 41 +++++--- .../extensions/organizer/SplitPresenter.java | 14 +++ .../Jetpack/window-extensions-release.aar | Bin 17281 -> 19169 bytes 8 files changed, 185 insertions(+), 197 deletions(-) delete mode 100644 libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionProvider.java delete mode 100644 libs/WindowManager/Jetpack/src/androidx/window/extensions/StubExtension.java create mode 100644 libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{SampleExtensionImpl.java => layout/WindowLayoutComponent.java} (60%) delete mode 100644 libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/EmbeddingExtensionImpl.java diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionProvider.java deleted file mode 100644 index ce4e10364ba24..0000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/ExtensionProvider.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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; - -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. - */ -public class ExtensionProvider { - /** - * Provides a simple implementation of {@link ExtensionInterface} that can be replaced by - * an OEM by overriding this method. - */ - public static ExtensionInterface getExtensionImpl(Context context) { - 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. - */ - public static String getApiVersion() { - return "1.0.0-settings_sample"; - } -} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/StubExtension.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/StubExtension.java deleted file mode 100644 index 6a53efee0e74d..0000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/StubExtension.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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; - -import android.app.Activity; - -import androidx.annotation.NonNull; - -import java.util.HashSet; -import java.util.Set; - -/** - * Basic implementation of the {@link ExtensionInterface}. An OEM can choose to use it as the base - * class for their implementation. - */ -abstract class StubExtension implements ExtensionInterface { - - private ExtensionCallback mExtensionCallback; - private final Set mWindowLayoutChangeListenerActivities = new HashSet<>(); - - StubExtension() { - } - - @Override - public void setExtensionCallback(@NonNull ExtensionCallback extensionCallback) { - this.mExtensionCallback = extensionCallback; - } - - @Override - public void onWindowLayoutChangeListenerAdded(@NonNull Activity activity) { - this.mWindowLayoutChangeListenerActivities.add(activity); - this.onListenersChanged(); - } - - @Override - public void onWindowLayoutChangeListenerRemoved(@NonNull Activity activity) { - this.mWindowLayoutChangeListenerActivities.remove(activity); - this.onListenersChanged(); - } - - void updateWindowLayout(@NonNull Activity activity, - @NonNull ExtensionWindowLayoutInfo newLayout) { - if (this.mExtensionCallback != null) { - mExtensionCallback.onWindowLayoutChanged(activity, newLayout); - } - } - - @NonNull - Set getActivitiesListeningForLayoutChanges() { - return mWindowLayoutChangeListenerActivities; - } - - protected boolean hasListeners() { - return !mWindowLayoutChangeListenerActivities.isEmpty(); - } - - protected abstract void onListenersChanged(); -} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java new file mode 100644 index 0000000000000..640455979e515 --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java @@ -0,0 +1,65 @@ +/* + * 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.embedding; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.window.extensions.organizer.SplitController; + +/** + * Provider for the reference implementation of androidx.window.extensions.embedding OEM interface + * for use with WindowManager Jetpack. + */ +public class ActivityEmbeddingComponentProvider { + private static SplitController sInstance; + + private ActivityEmbeddingComponentProvider() { + } + + /** + * Returns {@code true} if {@link ActivityEmbeddingComponent} is present on the device, + * {@code false} otherwise. If the component is not available the developer will receive a + * single callback with empty data or default values where possible. + */ + public static boolean isEmbeddingComponentAvailable() { + return true; + } + + /** + * Returns the OEM implementation of {@link ActivityEmbeddingComponent} if it is supported on + * the device. The implementation must match the API level reported in + * {@link androidx.window.extensions.WindowLibraryInfo}. An + * {@link UnsupportedOperationException} will be thrown if the device does not support + * Activity Embedding. Use + * {@link ActivityEmbeddingComponentProvider#isEmbeddingComponentAvailable()} to determine if + * {@link ActivityEmbeddingComponent} is present. + * @return the OEM implementation of {@link ActivityEmbeddingComponent} + */ + @NonNull + public static ActivityEmbeddingComponent getActivityEmbeddingComponent( + @NonNull Context context) { + if (sInstance == null) { + synchronized (ActivityEmbeddingComponentProvider.class) { + if (sInstance == null) { + sInstance = new SplitController(); + } + } + } + return sInstance; + } +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponent.java similarity index 60% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponent.java index a0d5b004ff1c0..df76894fb544a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/SampleExtensionImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions; +package androidx.window.extensions.layout; import static android.view.Display.DEFAULT_DISPLAY; @@ -27,6 +27,7 @@ import android.graphics.Rect; 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; @@ -36,19 +37,27 @@ import androidx.window.util.DataProducer; import androidx.window.util.PriorityDataProducer; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.function.Consumer; /** - * Reference implementation of androidx.window.extensions OEM interface for use with + * Reference implementation of androidx.window.extensions.layout OEM interface for use with * WindowManager Jetpack. * * NOTE: This version is a work in progress and under active development. It MUST NOT be used in * production builds since the interface can still change before reaching stable version. * Please refer to {@link androidx.window.sidecar.SampleSidecarImpl} instead. */ -class SampleExtensionImpl extends StubExtension { +public class WindowLayoutComponent { private static final String TAG = "SampleExtension"; + private static WindowLayoutComponent sInstance; + + private final Map> mWindowLayoutChangeListeners = + new HashMap<>(); private final SettingsDevicePostureProducer mSettingsDevicePostureProducer; private final DataProducer mDevicePostureProducer; @@ -56,7 +65,7 @@ class SampleExtensionImpl extends StubExtension { private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; private final DataProducer> mDisplayFeatureProducer; - SampleExtensionImpl(Context context) { + private WindowLayoutComponent(Context context) { mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); mDevicePostureProducer = new PriorityDataProducer<>(List.of( mSettingsDevicePostureProducer, @@ -73,28 +82,83 @@ class SampleExtensionImpl extends StubExtension { mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } + /** + * Returns a shared instance. + */ + @Nullable + public static WindowLayoutComponent getInstance(@NonNull Context context) { + if (sInstance == null) { + synchronized (WindowLayoutComponent.class) { + if (sInstance == null) { + sInstance = new WindowLayoutComponent(context); + } + } + } + return sInstance; + } + + /** + * Adds a listener interested in receiving updates to {@link WindowLayoutInfo} + * @param activity hosting a {@link android.view.Window} + * @param consumer interested in receiving updates to {@link WindowLayoutInfo} + */ + public void addWindowLayoutInfoListener(@NonNull Activity activity, + @NonNull Consumer consumer) { + mWindowLayoutChangeListeners.put(activity, consumer); + updateRegistrations(); + } + + /** + * Removes a listener no longer interested in receiving updates. + * @param consumer no longer interested in receiving updates to {@link WindowLayoutInfo} + */ + public void removeWindowLayoutInfoListener( + @NonNull Consumer consumer) { + mWindowLayoutChangeListeners.values().remove(consumer); + updateRegistrations(); + } + + void updateWindowLayout(@NonNull Activity activity, + @NonNull WindowLayoutInfo newLayout) { + Consumer consumer = mWindowLayoutChangeListeners.get(activity); + if (consumer != null) { + consumer.accept(newLayout); + } + } + + @NonNull + Set getActivitiesListeningForLayoutChanges() { + return mWindowLayoutChangeListeners.keySet(); + } + + protected boolean hasListeners() { + return !mWindowLayoutChangeListeners.isEmpty(); + } + private int getFeatureState(DisplayFeature feature) { Integer featureState = feature.getState(); Optional posture = mDevicePostureProducer.getData(); - int fallbackPosture = posture.orElse(ExtensionFoldingFeature.STATE_FLAT); + int fallbackPosture = posture.orElse(FoldingFeature.STATE_FLAT); return featureState == null ? fallbackPosture : featureState; } private void onDisplayFeaturesChanged() { for (Activity activity : getActivitiesListeningForLayoutChanges()) { - ExtensionWindowLayoutInfo newLayout = getWindowLayoutInfo(activity); + WindowLayoutInfo newLayout = getWindowLayoutInfo(activity); updateWindowLayout(activity, newLayout); } } @NonNull - private ExtensionWindowLayoutInfo getWindowLayoutInfo(@NonNull Activity activity) { - List displayFeatures = getDisplayFeatures(activity); - return new ExtensionWindowLayoutInfo(displayFeatures); + private WindowLayoutInfo getWindowLayoutInfo(@NonNull Activity activity) { + List displayFeatures = + getDisplayFeatures(activity); + return new WindowLayoutInfo(displayFeatures); } - private List getDisplayFeatures(@NonNull Activity activity) { - List features = new ArrayList<>(); + private List getDisplayFeatures( + @NonNull Activity activity) { + List features = new ArrayList<>(); int displayId = activity.getDisplay().getDisplayId(); if (displayId != DEFAULT_DISPLAY) { Log.w(TAG, "This sample doesn't support display features on secondary displays"); @@ -115,15 +179,14 @@ class SampleExtensionImpl extends StubExtension { rotateRectToDisplayRotation(displayId, featureRect); transformToWindowSpaceRect(activity, featureRect); - features.add(new ExtensionFoldingFeature(featureRect, baseFeature.getType(), + features.add(new FoldingFeature(featureRect, baseFeature.getType(), getFeatureState(baseFeature))); } } return features; } - @Override - protected void onListenersChanged() { + private void updateRegistrations() { if (hasListeners()) { mSettingsDevicePostureProducer.registerObserversIfNeeded(); mSettingsDisplayFeatureProducer.registerObserversIfNeeded(); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/EmbeddingExtensionImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/EmbeddingExtensionImpl.java deleted file mode 100644 index 9a8961f1d460b..0000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/EmbeddingExtensionImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java index a783fcde4f52e..24d384402f3b0 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java @@ -31,18 +31,17 @@ 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.embedding.ActivityRule; +import androidx.window.extensions.embedding.ActivityStack; 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; @@ -53,7 +52,8 @@ import java.util.function.Consumer; /** * Main controller class that manages split states and presentation. */ -public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback { +public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback, + androidx.window.extensions.embedding.ActivityEmbeddingComponent { private final SplitPresenter mPresenter; @@ -77,6 +77,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } /** Updates the embedding rules applied to future activity launches. */ + @Override public void setEmbeddingRules(@NonNull Set rules) { mSplitRules.clear(); mSplitRules.addAll(rules); @@ -103,7 +104,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen /** * Registers the split organizer callback to notify about changes to active splits. */ - public void setEmbeddingCallback(@NonNull Consumer> callback) { + @Override + public void setSplitInfoCallback(@NonNull Consumer> callback) { mEmbeddingCallback = callback; updateCallbackIfNecessary(); } @@ -175,7 +177,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen launchedActivity.getActivityToken(), launchedActivity); // Check if the activity is configured to always be expanded. - if (shouldExpand(launchedActivity, splitRules)) { + if (shouldExpand(launchedActivity, null, splitRules)) { if (shouldContainerBeExpanded(currentContainer)) { // Make sure that the existing container is expanded mPresenter.expandTaskFragment(currentContainer.getTaskFragmentToken()); @@ -525,11 +527,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen private List getActiveSplitStates() { List splitStates = new ArrayList<>(); for (SplitContainer container : mSplitContainers) { - TaskFragment primaryContainer = - new TaskFragment( + ActivityStack primaryContainer = + new ActivityStack( container.getPrimaryContainer().collectActivities()); - TaskFragment secondaryContainer = - new TaskFragment( + ActivityStack secondaryContainer = + new ActivityStack( container.getSecondaryContainer().collectActivities()); SplitInfo splitState = new SplitInfo(primaryContainer, secondaryContainer, container.getSplitRule().getSplitRatio()); @@ -611,7 +613,7 @@ 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 Activity activity, + private static boolean shouldExpand(@Nullable Activity activity, @Nullable Intent intent, List splitRules) { if (splitRules == null) { return false; @@ -624,7 +626,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen if (!activityRule.shouldAlwaysExpand()) { continue; } - if (activityRule.getActivityPredicate().test(activity)) { + if (activity != null && activityRule.getActivityPredicate().test(activity)) { + return true; + } + if (intent != null && activityRule.getIntentPredicate().test(intent)) { return true; } } @@ -703,13 +708,25 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } final Activity launchingActivity = (Activity) who; - if (!setLaunchingToSideContainer(launchingActivity, intent, options)) { + if (shouldExpand(null, intent, getSplitRules())) { + setLaunchingInExpandedContainer(launchingActivity, options); + } else if (!setLaunchingToSideContainer(launchingActivity, intent, options)) { setLaunchingInSameContainer(launchingActivity, intent, options); } return super.onStartActivity(who, intent, options); } + private void setLaunchingInExpandedContainer(Activity launchingActivity, Bundle options) { + TaskFragmentContainer newContainer = mPresenter.createNewExpandedContainer( + launchingActivity); + + // Amend the request to let the WM know that the activity should be placed in the + // dedicated container. + options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN, + newContainer.getTaskFragmentToken()); + } + /** * Returns {@code true} if the activity that is going to be started via the * {@code intent} should be paired with the {@code launchingActivity} and is set to be 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 ac85ac8cbc344..a3af70f07d5ce 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java @@ -152,6 +152,20 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { applyTransaction(wct); } + /** + * Creates a new expanded container. + */ + TaskFragmentContainer createNewExpandedContainer(@NonNull Activity launchingActivity) { + final TaskFragmentContainer newContainer = mController.newContainer(null); + + final WindowContainerTransaction wct = new WindowContainerTransaction(); + createTaskFragment(wct, newContainer.getTaskFragmentToken(), + launchingActivity.getActivityToken(), new Rect(), WINDOWING_MODE_MULTI_WINDOW); + + applyTransaction(wct); + return newContainer; + } + /** * Creates a new container or resizes an existing container for activity to the provided bounds. * @param activity The activity to be re-parented to the container if necessary. diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar index 097febf9770ae1dfb51be10e3da87f64c70b867c..b61b5bdf160f015ba3894146a2ba169cf1221085 100644 GIT binary patch delta 17737 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 Date: Thu, 2 Sep 2021 19:08:34 -0700 Subject: [PATCH 2/5] Update extensions embedding component package to match the package name in AndroidX. Bug: 190433398 Test: Manual, using demo application Change-Id: I985f8f95d6f0098bdadd53e204cb65d8f53c96bd --- .../ActivityEmbeddingComponentProvider.java | 1 - .../JetpackTaskFragmentOrganizer.java | 3 +- .../SplitContainer.java | 6 +--- .../SplitController.java | 33 +++++++------------ .../SplitPresenter.java | 6 ++-- .../TaskFragmentAnimationAdapter.java | 2 +- .../TaskFragmentAnimationController.java | 2 +- .../TaskFragmentAnimationRunner.java | 2 +- .../TaskFragmentAnimationSpec.java | 2 +- .../TaskFragmentContainer.java | 6 ++-- 10 files changed, 23 insertions(+), 40 deletions(-) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/JetpackTaskFragmentOrganizer.java (99%) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/SplitContainer.java (93%) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/SplitController.java (95%) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/SplitPresenter.java (98%) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/TaskFragmentAnimationAdapter.java (98%) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/TaskFragmentAnimationController.java (98%) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/TaskFragmentAnimationRunner.java (99%) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/TaskFragmentAnimationSpec.java (99%) rename libs/WindowManager/Jetpack/src/androidx/window/extensions/{organizer => embedding}/TaskFragmentContainer.java (98%) diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java index 640455979e515..56da30cb43831 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java @@ -19,7 +19,6 @@ package androidx.window.extensions.embedding; import android.content.Context; import androidx.annotation.NonNull; -import androidx.window.extensions.organizer.SplitController; /** * Provider for the reference implementation of androidx.window.extensions.embedding OEM interface diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java similarity index 99% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java index 46c8ffe286bdb..85ef270ac49da 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; @@ -36,7 +36,6 @@ import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.window.extensions.embedding.SplitRule; import java.util.Map; import java.util.concurrent.Executor; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java similarity index 93% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java index a41557d41e30f..06e7d14574179 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java @@ -14,15 +14,11 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import android.annotation.NonNull; import android.app.Activity; -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. */ diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java similarity index 95% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index 24d384402f3b0..c072f9ccb9e0f 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import android.annotation.NonNull; import android.annotation.Nullable; @@ -35,14 +35,6 @@ import android.window.TaskFragmentAppearedInfo; import android.window.TaskFragmentInfo; import android.window.WindowContainerTransaction; -import androidx.window.extensions.embedding.ActivityRule; -import androidx.window.extensions.embedding.ActivityStack; -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 java.util.ArrayList; import java.util.List; import java.util.Set; @@ -53,7 +45,7 @@ import java.util.function.Consumer; * Main controller class that manages split states and presentation. */ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback, - androidx.window.extensions.embedding.ActivityEmbeddingComponent { + ActivityEmbeddingComponent { private final SplitPresenter mPresenter; @@ -503,7 +495,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen continue; } SplitPlaceholderRule placeholderRule = (SplitPlaceholderRule) rule; - if (placeholderRule.getActivityPredicate().test(activity)) { + if (placeholderRule.matchesActivity(activity)) { return placeholderRule; } } @@ -569,8 +561,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen continue; } SplitPairRule pairRule = (SplitPairRule) rule; - if (pairRule.getActivityIntentPredicate().test( - new Pair(primaryActivity, secondaryActivityIntent))) { + if (pairRule.matchesActivityIntentPair(primaryActivity, secondaryActivityIntent)) { return pairRule; } } @@ -589,10 +580,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } 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)))) { + if (pairRule.matchesActivityPair(primaryActivity, secondaryActivity) + && (intent == null + || pairRule.matchesActivityIntentPair(primaryActivity, intent))) { return pairRule; } } @@ -626,10 +616,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen if (!activityRule.shouldAlwaysExpand()) { continue; } - if (activity != null && activityRule.getActivityPredicate().test(activity)) { + if (activity != null && activityRule.matchesActivity(activity)) { return true; - } - if (intent != null && activityRule.getIntentPredicate().test(intent)) { + } else if (intent != null && activityRule.matchesIntent(intent)) { return true; } } @@ -683,11 +672,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen /** Executor that posts on the main application thread. */ private static class MainThreadExecutor implements Executor { - private final Handler handler = new Handler(Looper.getMainLooper()); + private final Handler mHandler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { - handler.post(r); + mHandler.post(r); } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java similarity index 98% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java index a3af70f07d5ce..2c7b22f27206f 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; @@ -32,8 +32,6 @@ import android.window.WindowContainerTransaction; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.window.extensions.embedding.SplitPairRule; -import androidx.window.extensions.embedding.SplitRule; import java.util.concurrent.Executor; @@ -297,7 +295,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { // TODO(b/190433398): Supply correct insets. final WindowMetrics parentMetrics = new WindowMetrics(parentBounds, new WindowInsets(new Rect())); - return rule.getParentWindowMetricsPredicate().test(parentMetrics); + return rule.checkParentMetrics(parentMetrics); } @NonNull diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java similarity index 98% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationAdapter.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java index 155c649d72a43..65bd9f330e371 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationAdapter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import android.graphics.Rect; import android.view.Choreographer; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java similarity index 98% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationController.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java index 6631243494640..65797667687e1 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java similarity index 99% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationRunner.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java index da3d116455ef7..bb37fff297a7f 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationRunner.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationSpec.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java similarity index 99% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationSpec.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java index ddcb27ddb5124..71295900cd06a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentAnimationSpec.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import static android.view.RemoteAnimationTarget.MODE_CLOSING; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java similarity index 98% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java index 8503b9f4e3109..54e44a70ed408 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package androidx.window.extensions.organizer; +package androidx.window.extensions.embedding; import android.annotation.NonNull; import android.annotation.Nullable; @@ -212,7 +212,9 @@ class TaskFragmentContainer { @NonNull WindowContainerTransaction wct, @NonNull SplitController controller) { // Finish own activities for (Activity activity : collectActivities()) { - activity.finish(); + if (!activity.isFinishing()) { + activity.finish(); + } } if (!shouldFinishDependent) { From 47a107ad9a64081247802475eca0e6cf02984c86 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Thu, 9 Sep 2021 11:52:29 -0700 Subject: [PATCH 3/5] Deduplicate SplitInfo states from sidecar Also make sure that the split info is updated after an activity is appeared on the client side. Bug: 199144146 Test: Manual, using the test app Change-Id: I11e6dd9d1f55c107aaf40aed4d25b6b8fff7b9ca --- core/java/android/app/ActivityThread.java | 6 ++- .../extensions/embedding/SplitController.java | 54 ++++++++++++++++--- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 2e22b9231ac32..80554d7939f28 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3616,6 +3616,11 @@ public final class ActivityThread extends ClientTransactionHandler } activity.mLaunchedFromBubble = r.mLaunchedFromBubble; activity.mCalled = false; + // Assigning the activity to the record before calling onCreate() allows + // ActivityThread#getActivity() lookup for the callbacks triggered from + // ActivityLifecycleCallbacks#onActivityCreated() or + // ActivityLifecycleCallback#onActivityPostCreated(). + r.activity = activity; if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { @@ -3626,7 +3631,6 @@ public final class ActivityThread extends ClientTransactionHandler "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } - r.activity = activity; mLastReportedWindowingMode.put(activity.getActivityToken(), config.windowConfiguration.getWindowingMode()); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index c072f9ccb9e0f..e1c8b11a835cf 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -56,6 +56,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // Callback to Jetpack to notify about changes to split states. private @NonNull Consumer> mEmbeddingCallback; + private final List mLastReportedSplitStates = new ArrayList<>(); public SplitController() { mPresenter = new SplitPresenter(new MainThreadExecutor(), this); @@ -113,8 +114,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen container.setInfo(taskFragmentAppearedInfo.getTaskFragmentInfo()); if (container.isFinished()) { mPresenter.cleanupContainer(container, false /* shouldFinishDependent */); - updateCallbackIfNecessary(); } + updateCallbackIfNecessary(); } @Override @@ -133,8 +134,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen final boolean shouldFinishDependent = !taskFragmentInfo.isTaskClearedForReuse(); mPresenter.cleanupContainer(container, shouldFinishDependent); - updateCallbackIfNecessary(); } + updateCallbackIfNecessary(); } @Override @@ -158,12 +159,17 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } + void onActivityCreated(@NonNull Activity launchedActivity) { + handleActivityCreated(launchedActivity); + updateCallbackIfNecessary(); + } + /** * Checks if the activity start should be routed to a particular container. It can create a new * container for the activity and a new split container if necessary. */ // TODO(b/190433398): Break down into smaller functions. - void onActivityCreated(@NonNull Activity launchedActivity) { + void handleActivityCreated(@NonNull Activity launchedActivity) { final List splitRules = getSplitRules(); final TaskFragmentContainer currentContainer = getContainerWithActivity( launchedActivity.getActivityToken(), launchedActivity); @@ -234,8 +240,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mPresenter.createNewSplitContainer(activityBelow, launchedActivity, splitPairRule); - - updateCallbackIfNecessary(); } private void onActivityConfigurationChanged(@NonNull Activity activity) { @@ -509,8 +513,16 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen if (mEmbeddingCallback == null) { return; } - // TODO(b/190433398): Check if something actually changed - mEmbeddingCallback.accept(getActiveSplitStates()); + if (!allActivitiesCreated()) { + return; + } + List currentSplitStates = getActiveSplitStates(); + if (mLastReportedSplitStates.equals(currentSplitStates)) { + return; + } + mLastReportedSplitStates.clear(); + mLastReportedSplitStates.addAll(currentSplitStates); + mEmbeddingCallback.accept(currentSplitStates); } /** @@ -519,6 +531,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen private List getActiveSplitStates() { List splitStates = new ArrayList<>(); for (SplitContainer container : mSplitContainers) { + if (container.getPrimaryContainer().isEmpty() + || container.getSecondaryContainer().isEmpty()) { + // Skipping containers that do not have any activities to report. + continue; + } ActivityStack primaryContainer = new ActivityStack( container.getPrimaryContainer().collectActivities()); @@ -526,12 +543,33 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen new ActivityStack( container.getSecondaryContainer().collectActivities()); SplitInfo splitState = new SplitInfo(primaryContainer, - secondaryContainer, container.getSplitRule().getSplitRatio()); + secondaryContainer, + // Splits that are not showing side-by-side are reported as having 0 split + // ratio, since by definition in the API the primary container occupies no + // width of the split when covered by the secondary. + mPresenter.shouldShowSideBySide(container) + ? container.getSplitRule().getSplitRatio() + : 0.0f); splitStates.add(splitState); } return splitStates; } + /** + * Checks if all activities that are registered with the containers have already appeared in + * the client. + */ + private boolean allActivitiesCreated() { + for (TaskFragmentContainer container : mContainers) { + if (container.getInfo() == null + || container.getInfo().getActivities().size() + != container.collectActivities().size()) { + return false; + } + } + return true; + } + /** * Returns {@code true} if the container is expanded to occupy full task size. * Returns {@code false} if the container is included in an active split. From 00af00c4147f4d0669990ecbc41c67f5ad604343 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Mon, 20 Sep 2021 13:21:13 -0700 Subject: [PATCH 4/5] Add RTL support in split activity organizer Bug: 190433398 Test: Change locale to RLT, test in demo app Change-Id: I941020c422d4fdf5bcb1a4f03f6fbd8b7aef30c3 --- .../extensions/embedding/SplitPresenter.java | 98 ++++++++++++++----- 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java index 2c7b22f27206f..25292b905fe86 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -19,11 +19,14 @@ package androidx.window.extensions.embedding; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import android.app.Activity; +import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; +import android.util.LayoutDirection; +import android.view.View; import android.view.WindowInsets; import android.view.WindowMetrics; import android.window.TaskFragmentCreationParams; @@ -40,13 +43,13 @@ import java.util.concurrent.Executor; * {@link SplitController}. */ class SplitPresenter extends JetpackTaskFragmentOrganizer { - private static final int POSITION_LEFT = 0; - private static final int POSITION_RIGHT = 1; + private static final int POSITION_START = 0; + private static final int POSITION_END = 1; private static final int POSITION_FILL = 2; @IntDef(value = { - POSITION_LEFT, - POSITION_RIGHT, + POSITION_START, + POSITION_END, POSITION_FILL, }) private @interface Position {} @@ -94,13 +97,15 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { final WindowContainerTransaction wct = new WindowContainerTransaction(); final Rect parentBounds = getParentContainerBounds(primaryActivity); - final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule); + final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule, + isLtr(primaryActivity, rule)); final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct, primaryActivity, primaryRectBounds, null); // Create new empty task fragment - TaskFragmentContainer secondaryContainer = mController.newContainer(null); - final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule); + final TaskFragmentContainer secondaryContainer = mController.newContainer(null); + final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, + rule, isLtr(primaryActivity, rule)); createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(), primaryActivity.getActivityToken(), secondaryRectBounds, WINDOWING_MODE_MULTI_WINDOW); @@ -133,11 +138,13 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { final WindowContainerTransaction wct = new WindowContainerTransaction(); final Rect parentBounds = getParentContainerBounds(primaryActivity); - final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule); + final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule, + isLtr(primaryActivity, rule)); final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct, primaryActivity, primaryRectBounds, null); - final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule); + final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule, + isLtr(primaryActivity, rule)); final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct, secondaryActivity, secondaryRectBounds, primaryContainer); @@ -209,8 +216,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent activityIntent, @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); + final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule, + isLtr(launchingActivity, rule)); + final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule, + isLtr(launchingActivity, rule)); TaskFragmentContainer primaryContainer = mController.getContainerWithActivity( launchingActivity.getActivityToken()); @@ -243,8 +252,15 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { // Getting the parent bounds using the updated container - it will have the recent value. final Rect parentBounds = getParentContainerBounds(updatedContainer); final SplitRule rule = splitContainer.getSplitRule(); - final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule); - final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule); + final Activity activity = splitContainer.getPrimaryContainer().getTopNonFinishingActivity(); + if (activity == null) { + return; + } + final boolean isLtr = isLtr(activity, rule); + final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule, + isLtr); + final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule, + isLtr); // If the task fragments are not registered yet, the positions will be updated after they // are created again. @@ -300,31 +316,59 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { @NonNull private Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds, - @NonNull SplitRule rule) { + @NonNull SplitRule rule, boolean isLtr) { if (!shouldShowSideBySide(parentBounds, rule)) { return new Rect(); } - float splitRatio = rule.getSplitRatio(); + final float splitRatio = rule.getSplitRatio(); + final float rtlSplitRatio = 1 - splitRatio; switch (position) { - case POSITION_LEFT: - return new Rect( - parentBounds.left, - parentBounds.top, - (int) (parentBounds.left + parentBounds.width() * splitRatio), - parentBounds.bottom); - case POSITION_RIGHT: - return new Rect( - (int) (parentBounds.left + parentBounds.width() * splitRatio), - parentBounds.top, - parentBounds.right, - parentBounds.bottom); + case POSITION_START: + return isLtr ? getLeftContainerBounds(parentBounds, splitRatio) + : getRightContainerBounds(parentBounds, rtlSplitRatio); + case POSITION_END: + return isLtr ? getRightContainerBounds(parentBounds, splitRatio) + : getLeftContainerBounds(parentBounds, rtlSplitRatio); case POSITION_FILL: return parentBounds; } return parentBounds; } + private Rect getLeftContainerBounds(@NonNull Rect parentBounds, float splitRatio) { + return new Rect( + parentBounds.left, + parentBounds.top, + (int) (parentBounds.left + parentBounds.width() * splitRatio), + parentBounds.bottom); + } + + private Rect getRightContainerBounds(@NonNull Rect parentBounds, float splitRatio) { + return new Rect( + (int) (parentBounds.left + parentBounds.width() * splitRatio), + parentBounds.top, + parentBounds.right, + parentBounds.bottom); + } + + /** + * Checks if a split with the provided rule should be displays in left-to-right layout + * direction, either always or with the current configuration. + */ + private boolean isLtr(@NonNull Context context, @NonNull SplitRule rule) { + switch (rule.getLayoutDirection()) { + case LayoutDirection.LOCALE: + return context.getResources().getConfiguration().getLayoutDirection() + == View.LAYOUT_DIRECTION_LTR; + case LayoutDirection.RTL: + return false; + case LayoutDirection.LTR: + default: + return true; + } + } + @NonNull Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) { final Configuration parentConfig = mFragmentParentConfigs.get( From 322a5aee69fd28cdd458990b14875d489f19eda9 Mon Sep 17 00:00:00 2001 From: Diego Vela Date: Tue, 21 Sep 2021 13:58:40 -0700 Subject: [PATCH 5/5] Update Reference implementation for window-extensions. Update reference implementation for window-extensions. Bug: 200716579 Test: manual Change-Id: Iabcab8b2aba45d24ebcde825c26681079999d81c --- .../extensions/WindowExtensionsImpl.java | 91 ++++++++++++++++++ .../extensions/WindowExtensionsProvider.java | 38 ++++++++ .../ActivityEmbeddingComponentProvider.java | 64 ------------ ...nt.java => WindowLayoutComponentImpl.java} | 20 +--- .../Jetpack/window-extensions-release.aar | Bin 19169 -> 18278 bytes 5 files changed, 131 insertions(+), 82 deletions(-) create mode 100644 libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java create mode 100644 libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsProvider.java delete mode 100644 libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java rename libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/{WindowLayoutComponent.java => WindowLayoutComponentImpl.java} (93%) diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java new file mode 100644 index 0000000000000..990d7b6a0101c --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java @@ -0,0 +1,91 @@ +/* + * 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; + +import android.app.ActivityThread; +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.window.extensions.embedding.ActivityEmbeddingComponent; +import androidx.window.extensions.embedding.SplitController; +import androidx.window.extensions.layout.WindowLayoutComponent; +import androidx.window.extensions.layout.WindowLayoutComponentImpl; + +/** + * The reference implementation of {@link WindowExtensions} that implements the initial API version. + */ +public class WindowExtensionsImpl implements WindowExtensions { + + private final Object mLock = new Object(); + private volatile WindowLayoutComponent mWindowLayoutComponent; + private volatile SplitController mSplitController; + + @Override + public int getVendorApiLevel() { + return 1; + } + + @Override + public boolean isWindowLayoutComponentAvailable() { + return true; + } + + @Override + public WindowLayoutComponent getWindowLayoutComponent() { + if (mWindowLayoutComponent == null) { + synchronized (mLock) { + if (mWindowLayoutComponent == null) { + Context context = ActivityThread.currentApplication(); + mWindowLayoutComponent = new WindowLayoutComponentImpl(context); + } + } + } + return mWindowLayoutComponent; + } + + /** + * Returns {@code true} if {@link ActivityEmbeddingComponent} is present on the device, + * {@code false} otherwise. If the component is not available the developer will receive a + * single callback with empty data or default values where possible. + */ + @Override + public boolean isEmbeddingComponentAvailable() { + return true; + } + + /** + * Returns the OEM implementation of {@link ActivityEmbeddingComponent} if it is supported on + * the device. The implementation must match the API level reported in + * {@link androidx.window.extensions.WindowExtensions}. An + * {@link UnsupportedOperationException} will be thrown if the device does not support + * Activity Embedding. Use + * {@link WindowExtensions#isEmbeddingComponentAvailable()} to determine if + * {@link ActivityEmbeddingComponent} is present. + * @return the OEM implementation of {@link ActivityEmbeddingComponent} + */ + @NonNull + public ActivityEmbeddingComponent getActivityEmbeddingComponent() { + if (mSplitController == null) { + synchronized (mLock) { + if (mSplitController == null) { + mSplitController = new SplitController(); + } + } + } + return mSplitController; + } +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsProvider.java new file mode 100644 index 0000000000000..f9e1f077cffc0 --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsProvider.java @@ -0,0 +1,38 @@ +/* + * 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; + +import android.annotation.NonNull; + +/** + * Provides the OEM implementation of {@link WindowExtensions}. + */ +public class WindowExtensionsProvider { + + private static final WindowExtensions sWindowExtensions = new WindowExtensionsImpl(); + + /** + * Returns the OEM implementation of {@link WindowExtensions}. This method is implemented in + * the library provided on the device and overwrites one in the Jetpack library included in + * apps. + * @return the OEM implementation of {@link WindowExtensions} + */ + @NonNull + public static WindowExtensions getWindowExtensions() { + return sWindowExtensions; + } +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java deleted file mode 100644 index 56da30cb43831..0000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ActivityEmbeddingComponentProvider.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.embedding; - -import android.content.Context; - -import androidx.annotation.NonNull; - -/** - * Provider for the reference implementation of androidx.window.extensions.embedding OEM interface - * for use with WindowManager Jetpack. - */ -public class ActivityEmbeddingComponentProvider { - private static SplitController sInstance; - - private ActivityEmbeddingComponentProvider() { - } - - /** - * Returns {@code true} if {@link ActivityEmbeddingComponent} is present on the device, - * {@code false} otherwise. If the component is not available the developer will receive a - * single callback with empty data or default values where possible. - */ - public static boolean isEmbeddingComponentAvailable() { - return true; - } - - /** - * Returns the OEM implementation of {@link ActivityEmbeddingComponent} if it is supported on - * the device. The implementation must match the API level reported in - * {@link androidx.window.extensions.WindowLibraryInfo}. An - * {@link UnsupportedOperationException} will be thrown if the device does not support - * Activity Embedding. Use - * {@link ActivityEmbeddingComponentProvider#isEmbeddingComponentAvailable()} to determine if - * {@link ActivityEmbeddingComponent} is present. - * @return the OEM implementation of {@link ActivityEmbeddingComponent} - */ - @NonNull - public static ActivityEmbeddingComponent getActivityEmbeddingComponent( - @NonNull Context context) { - if (sInstance == null) { - synchronized (ActivityEmbeddingComponentProvider.class) { - if (sInstance == null) { - sInstance = new SplitController(); - } - } - } - return sInstance; - } -} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponent.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java similarity index 93% rename from libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponent.java rename to libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index df76894fb544a..383d91da6af80 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponent.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -27,7 +27,6 @@ import android.graphics.Rect; 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; @@ -52,7 +51,7 @@ import java.util.function.Consumer; * production builds since the interface can still change before reaching stable version. * Please refer to {@link androidx.window.sidecar.SampleSidecarImpl} instead. */ -public class WindowLayoutComponent { +public class WindowLayoutComponentImpl implements WindowLayoutComponent { private static final String TAG = "SampleExtension"; private static WindowLayoutComponent sInstance; @@ -65,7 +64,7 @@ public class WindowLayoutComponent { private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; private final DataProducer> mDisplayFeatureProducer; - private WindowLayoutComponent(Context context) { + public WindowLayoutComponentImpl(Context context) { mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); mDevicePostureProducer = new PriorityDataProducer<>(List.of( mSettingsDevicePostureProducer, @@ -82,21 +81,6 @@ public class WindowLayoutComponent { mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } - /** - * Returns a shared instance. - */ - @Nullable - public static WindowLayoutComponent getInstance(@NonNull Context context) { - if (sInstance == null) { - synchronized (WindowLayoutComponent.class) { - if (sInstance == null) { - sInstance = new WindowLayoutComponent(context); - } - } - } - return sInstance; - } - /** * Adds a listener interested in receiving updates to {@link WindowLayoutInfo} * @param activity hosting a {@link android.view.Window} diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar index b61b5bdf160f015ba3894146a2ba169cf1221085..42e829e3e5ab739c631ff56e53fe8d1c2109e291 100644 GIT binary patch delta 15869 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

4J7L00b%uAD~m` zP>hFG|@`!kF2+ts0Po(Z=niat+aGjQAG__w8BZVi4Ws@AT z)opGsAQth>C*{#i*5UloRxo8MFr~Y7@Q`807t@7rfB)I%da4`>1|Wh@)|~v7T3n4} zdFDy(v_cxB)o;l{hkf$Sx&H`lv9Ai(v_bwczWijERMkL#P5i*3d+}_G{PCNtkRsnX zmf=@sj|T<<;`txtuD|Qir2cL3n?$J~=2wzuKmd@{yI9vR*XFrh%F*o;dZ-~v3XoGP zQ_ngse`h8ooEi<0uH644&uiPE3W$sm483~Ae@t+9aPxlZ1g@(`@;Dl+%5v3SI7(vHJ;M;V zFFr1zW*X!F+(V>lOGDL8J!7x+B$aB)SUH^kf9iO8*<8o_)78j0;PbFCDH+s75F(@o zGY_G)$W}Z9yO%3M;&@0JK&B+7E4EAc;PK8Xs)bKR|CQ!Cny*20IhA5veD9#;1M&ET zcrM6j0?HIDx#OmI8PjR_P;xS3Lk5k#9u^G7LatmRvkPq2yIx&s(yuf7EDgNjwP2NJ ze>zAd*eY4PlhUXtVWsNNzQ~xqHAnij)`s~19!dWfzW7fAbjq5JGb#x0QO254@>T<3 z@q&WK3RqTD0-%DxyVLxF3g81;s}hCAoQfQ1LlVYAiN7p)8+{vll#tBbDTOVWs=u7f z*du#<+aRWbV-=E`1fI#$;yHfa*pi*Ef9m^j4ctj=BNE%Ggfi1K8HhnU+=L>6polmM z!Qlzwn1VhcCa4{{=>VeI>muJDSFM{^Ga6G&d*v}Ui%*T+{Hx92Ooifl*4DOcTAhVz zJs+pPO?XV&d%{fOT&)FND`jV`T3tA|FEiMf`Swz&Kljsmjs?n!O{;=uV3a!;f2Vz} zT1$uJdR|-Sz<8#~O1+`1WgDyKDlo@mq!QJ-Y>{5N88>SW&Gi8DnJLq(_5`L&q(x9} z2h;|$Pqf~OJ^L^rfIz*P&Dl}gwQ17ZaB^)w!SR|8<;NBWR90N$`6393&XLuoo@X3* z{hKgVrrt)WYhGu3=2}ZGm&cqPe{4}jUNb){LdkOLxC2>{>pQLh6EzHr)kA zI`jPm260O(k;&?w5yaAY!xsHFJQ-?(#6f~f+mpL9Qty1JBt6luEE zeV|gCgeLZo5&2cqf7!>R`)yFuPDRmPMa8~(jwe1eh#o{g1`&PcPEv2tpN&A4Qu&JO z?t#PheEc`!Q9xx5X7LfA&PzK8?r{aDE1#(hEc2q0#lLw9!tn~qEu%KrSGBtVwNyaK z$oU}5BP8*6D5c#(#hNA}=@NN?3aVJ;7CBXz%kI>%HK2$*f5upS!uJ-BdJPl6tN~3^ zwcIr2el)d@Qu*XNhwmnt^Nf3?vcpqMVcW7OV9sYL1Kub?cPor;T zXQofj044YJe-kj!=l{2u|KG0$f1v*bY5(tNzYF94KqLJ07i99kKmK>6_8*VG1pXIv z+rPv7E*bsyNkIHN?v>UPl*`FG?x`F+`JFN@XFvL;wJGVQh6}b1zU!1qJ{B T000UA3IJ>Z0087f00000VYj

f0DO*qR%;(Yl)37}>hge;T_v8QVCT+uAtN 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 ABme*a