From 6c39d4fb3c851b024498c271d5660ac773d4f2fc Mon Sep 17 00:00:00 2001 From: Diego Vela Date: Thu, 2 Dec 2021 10:39:05 -0800 Subject: DO NOT MERGE Listen for config changes when updating features. Listen for configuration changes to push out folding feature changes. Fixes a bug where the reference implementation would not emit the correct folding feature if a configuration changed. The effect was that you would see the folding feature for portait while in landscape or vice-versa. Maintains parity with Sidecar providing updates for Activities that do not handle configuration changes. Bug: 205342008, 206697963 Test: Manual - Open the sample app and use the application that && handles configuration changes. && Expect the folding feature to match the physical orientation Test: Manual - open an app that handles PiP and folding features && Flattend the device and put app into PiP && Fold device and put PiP app in full screen. && Expect the app to react to fold. Test: atest CtsWindowManagerJetpackTestCases Change-Id: I726827c9f1482ddd0b55a6839e34660deb340767 --- .../layout/WindowLayoutComponentImpl.java | 46 ++++++++++++++++++++-- .../androidx/window/sidecar/SampleSidecarImpl.java | 27 +++++++++++++ .../src/androidx/window/sidecar/StubSidecar.java | 2 +- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index df059bb64dc7..ee8cb48e3c4c 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -25,13 +25,17 @@ import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; import android.annotation.Nullable; import android.app.Activity; +import android.app.Application; import android.content.Context; import android.graphics.Rect; +import android.os.Bundle; +import android.os.IBinder; import android.util.Log; import androidx.annotation.NonNull; import androidx.window.common.CommonFoldingFeature; import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; +import androidx.window.common.EmptyLifecycleCallbacksAdapter; import androidx.window.common.SettingsDisplayFeatureProducer; import androidx.window.util.DataProducer; import androidx.window.util.PriorityDataProducer; @@ -62,6 +66,8 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private final DataProducer> mFoldingFeatureProducer; public WindowLayoutComponentImpl(Context context) { + ((Application) context.getApplicationContext()) + .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context); mFoldingFeatureProducer = new PriorityDataProducer<>(List.of( mSettingsDisplayFeatureProducer, @@ -72,6 +78,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { /** * 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} */ @@ -83,6 +90,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { /** * Removes a listener no longer interested in receiving updates. + * * @param consumer no longer interested in receiving updates to {@link WindowLayoutInfo} */ public void removeWindowLayoutInfoListener( @@ -104,6 +112,16 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { return mWindowLayoutChangeListeners.keySet(); } + @NonNull + private Boolean isListeningForLayoutChanges(IBinder token) { + for (Activity activity: getActivitiesListeningForLayoutChanges()) { + if (token.equals(activity.getWindow().getAttributes().token)) { + return true; + } + } + return false; + } + protected boolean hasListeners() { return !mWindowLayoutChangeListeners.isEmpty(); } @@ -115,9 +133,9 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { * possible to translate, then we will return a {@code null} value. * * @param state if it matches a value in {@link CommonFoldingFeature.State}, {@code null} - * otherwise. @return a {@link FoldingFeature.STATE_FLAT} or - * {@link FoldingFeature.STATE_HALF_OPENED} if the given state matches a value in - * {@link CommonFoldingFeature.State} and {@code null} otherwise. + * otherwise. @return a {@link FoldingFeature.STATE_FLAT} or + * {@link FoldingFeature.STATE_HALF_OPENED} if the given state matches a value in + * {@link CommonFoldingFeature.State} and {@code null} otherwise. */ @Nullable private Integer convertToExtensionState(int state) { @@ -198,7 +216,27 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { } else { mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded(); } - onDisplayFeaturesChanged(); } + + private final class NotifyOnConfigurationChanged extends EmptyLifecycleCallbacksAdapter { + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + super.onActivityCreated(activity, savedInstanceState); + onDisplayFeaturesChangedIfListening(activity); + } + + @Override + public void onActivityConfigurationChanged(Activity activity) { + super.onActivityConfigurationChanged(activity); + onDisplayFeaturesChangedIfListening(activity); + } + + private void onDisplayFeaturesChangedIfListening(Activity activity) { + IBinder token = activity.getWindow().getAttributes().token; + if (token == null || isListeningForLayoutChanges(token)) { + onDisplayFeaturesChanged(); + } + } + } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java index 458bb77b047f..c7b709347060 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java @@ -23,14 +23,17 @@ import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; import android.app.Activity; import android.app.ActivityThread; +import android.app.Application; import android.content.Context; import android.graphics.Rect; +import android.os.Bundle; import android.os.IBinder; import android.util.Log; import androidx.annotation.NonNull; import androidx.window.common.CommonFoldingFeature; import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; +import androidx.window.common.EmptyLifecycleCallbacksAdapter; import androidx.window.common.SettingsDisplayFeatureProducer; import androidx.window.util.DataProducer; import androidx.window.util.PriorityDataProducer; @@ -52,6 +55,8 @@ class SampleSidecarImpl extends StubSidecar { private final SettingsDisplayFeatureProducer mSettingsFoldingFeatureProducer; SampleSidecarImpl(Context context) { + ((Application) context.getApplicationContext()) + .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); mSettingsFoldingFeatureProducer = new SettingsDisplayFeatureProducer(context); mFoldingFeatureProducer = new PriorityDataProducer<>(List.of( mSettingsFoldingFeatureProducer, @@ -138,8 +143,30 @@ class SampleSidecarImpl extends StubSidecar { protected void onListenersChanged() { if (hasListeners()) { mSettingsFoldingFeatureProducer.registerObserversIfNeeded(); + onDisplayFeaturesChanged(); } else { mSettingsFoldingFeatureProducer.unregisterObserversIfNeeded(); } } + + private final class NotifyOnConfigurationChanged extends EmptyLifecycleCallbacksAdapter { + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + super.onActivityCreated(activity, savedInstanceState); + onDisplayFeaturesChangedForActivity(activity); + } + + @Override + public void onActivityConfigurationChanged(Activity activity) { + super.onActivityConfigurationChanged(activity); + onDisplayFeaturesChangedForActivity(activity); + } + + private void onDisplayFeaturesChangedForActivity(@NonNull Activity activity) { + IBinder token = activity.getWindow().getAttributes().token; + if (token == null || mWindowLayoutChangeListenerTokens.contains(token)) { + onDisplayFeaturesChanged(); + } + } + } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java index 199c37315c07..b9c808a6569b 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java @@ -30,7 +30,7 @@ import java.util.Set; abstract class StubSidecar implements SidecarInterface { private SidecarCallback mSidecarCallback; - private final Set mWindowLayoutChangeListenerTokens = new HashSet<>(); + final Set mWindowLayoutChangeListenerTokens = new HashSet<>(); private boolean mDeviceStateChangeListenerRegistered; StubSidecar() { -- cgit v1.2.3-59-g8ed1b