diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java similarity index 71% rename from libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java rename to libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java index eb9429747b663..a0c66fa1ff762 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java @@ -18,17 +18,60 @@ package androidx.window.common; import static androidx.window.util.ExtensionHelper.isZero; +import android.annotation.IntDef; import android.annotation.Nullable; import android.graphics.Rect; import androidx.annotation.NonNull; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -/** Wrapper for both Extension and Sidecar versions of DisplayFeature. */ -final class CommonDisplayFeature implements DisplayFeature { +/** A representation of a folding feature for both Extension and Sidecar. + * For Sidecar this is the same as combining {@link androidx.window.sidecar.SidecarDeviceState} and + * {@link androidx.window.sidecar.SidecarDisplayFeature}. For Extensions this is the mirror of + * {@link androidx.window.extensions.layout.FoldingFeature}. + */ +public final class CommonFoldingFeature { + + /** + * A common type to represent a hinge where the screen is continuous. + */ + public static final int COMMON_TYPE_FOLD = 1; + + /** + * A common type to represent a hinge where there is a physical gap separating multiple + * displays. + */ + public static final int COMMON_TYPE_HINGE = 2; + + @IntDef({COMMON_TYPE_FOLD, COMMON_TYPE_HINGE}) + @Retention(RetentionPolicy.SOURCE) + public @interface Type { + } + + /** + * A common state to represent a FLAT hinge. This is needed because the definitions in Sidecar + * and Extensions do not match exactly. + */ + public static final int COMMON_STATE_FLAT = 3; + /** + * A common state to represent a HALF_OPENED hinge. This is needed because the definitions in + * Sidecar and Extensions do not match exactly. + */ + public static final int COMMON_STATE_HALF_OPENED = 2; + + /** + * The possible states for a folding hinge. + */ + @IntDef({COMMON_STATE_FLAT, COMMON_STATE_HALF_OPENED}) + @Retention(RetentionPolicy.SOURCE) + public @interface State { + } + private static final Pattern FEATURE_PATTERN = Pattern.compile("([a-z]+)-\\[(\\d+),(\\d+),(\\d+),(\\d+)]-?(flat|half-opened)?"); @@ -38,8 +81,6 @@ final class CommonDisplayFeature implements DisplayFeature { private static final String PATTERN_STATE_FLAT = "flat"; private static final String PATTERN_STATE_HALF_OPENED = "half-opened"; - // TODO(b/183049815): Support feature strings that include the state of the feature. - /** * Parses a display feature from a string. * @@ -48,7 +89,7 @@ final class CommonDisplayFeature implements DisplayFeature { * @see #FEATURE_PATTERN */ @NonNull - static CommonDisplayFeature parseFromString(@NonNull String string) { + static CommonFoldingFeature parseFromString(@NonNull String string) { Matcher featureMatcher = FEATURE_PATTERN.matcher(string); if (!featureMatcher.matches()) { throw new IllegalArgumentException("Malformed feature description format: " + string); @@ -59,10 +100,10 @@ final class CommonDisplayFeature implements DisplayFeature { int type; switch (featureType) { case FEATURE_TYPE_FOLD: - type = 1 /* TYPE_FOLD */; + type = COMMON_TYPE_FOLD; break; case FEATURE_TYPE_HINGE: - type = 2 /* TYPE_HINGE */; + type = COMMON_TYPE_HINGE; break; default: { throw new IllegalArgumentException("Malformed feature type: " + featureType); @@ -91,7 +132,7 @@ final class CommonDisplayFeature implements DisplayFeature { state = null; break; } - return new CommonDisplayFeature(type, state, featureRect); + return new CommonFoldingFeature(type, state, featureRect); } catch (NumberFormatException e) { throw new IllegalArgumentException("Malformed feature description: " + string, e); } @@ -103,7 +144,7 @@ final class CommonDisplayFeature implements DisplayFeature { @NonNull private final Rect mRect; - CommonDisplayFeature(int type, @Nullable Integer state, @NonNull Rect rect) { + CommonFoldingFeature(int type, @Nullable Integer state, @NonNull Rect rect) { assertValidState(state); this.mType = type; this.mState = state; @@ -114,16 +155,20 @@ final class CommonDisplayFeature implements DisplayFeature { this.mRect = rect; } + /** Returns the type of the feature. */ + @Type public int getType() { return mType; } /** Returns the state of the feature, or {@code null} if the feature has no state. */ @Nullable + @State public Integer getState() { return mState; } + /** Returns the bounds of the feature. */ @NonNull public Rect getRect() { return mRect; @@ -133,7 +178,7 @@ final class CommonDisplayFeature implements DisplayFeature { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - CommonDisplayFeature that = (CommonDisplayFeature) o; + CommonFoldingFeature that = (CommonFoldingFeature) o; return mType == that.mType && Objects.equals(mState, that.mState) && mRect.equals(that.mRect); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java deleted file mode 100644 index 573641857b99a..0000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java +++ /dev/null @@ -1,60 +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.common; - -import android.annotation.IntDef; -import android.annotation.Nullable; -import android.graphics.Rect; - -import androidx.annotation.NonNull; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** Wrapper for both Extension and Sidecar versions of DisplayFeature. */ -public interface DisplayFeature { - /** Returns the type of the feature. */ - int getType(); - - /** Returns the state of the feature, or {@code null} if the feature has no state. */ - @Nullable - @State - Integer getState(); - - /** Returns the bounds of the feature. */ - @NonNull - Rect getRect(); - - /** - * A common state to represent a FLAT hinge. This is needed because the definitions in Sidecar - * and Extensions do not match exactly. - */ - int COMMON_STATE_FLAT = 3; - /** - * A common state to represent a HALF_OPENED hinge. This is needed because the definitions in - * Sidecar and Extensions do not match exactly. - */ - int COMMON_STATE_HALF_OPENED = 2; - - /** - * The possible states for a folding hinge. - */ - @IntDef({COMMON_STATE_FLAT, COMMON_STATE_HALF_OPENED}) - @Retention(RetentionPolicy.SOURCE) - @interface State {} - -} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java index cd2cadc082e15..a48d3ad797e6d 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java @@ -32,11 +32,11 @@ import java.util.Optional; /** * Implementation of {@link androidx.window.util.DataProducer} that produces - * {@link CommonDisplayFeature} parsed from a string stored in the resources config at + * {@link CommonFoldingFeature} parsed from a string stored in the resources config at * {@link R.string#config_display_features}. */ public final class ResourceConfigDisplayFeatureProducer extends - BaseDataProducer> { + BaseDataProducer> { private static final boolean DEBUG = false; private static final String TAG = "ResourceConfigDisplayFeatureProducer"; @@ -48,19 +48,19 @@ public final class ResourceConfigDisplayFeatureProducer extends @Override @Nullable - public Optional> getData() { + public Optional> getData() { String displayFeaturesString = mContext.getResources().getString( R.string.config_display_features); if (TextUtils.isEmpty(displayFeaturesString)) { return Optional.empty(); } - List features = new ArrayList<>(); + List features = new ArrayList<>(); String[] featureStrings = displayFeaturesString.split(";"); for (String featureString : featureStrings) { - CommonDisplayFeature feature; + CommonFoldingFeature feature; try { - feature = CommonDisplayFeature.parseFromString(featureString); + feature = CommonFoldingFeature.parseFromString(featureString); } catch (IllegalArgumentException e) { if (DEBUG) { Log.w(TAG, "Failed to parse display feature: " + featureString, e); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java index 040662657a746..f3d6150f11d19 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java @@ -36,10 +36,10 @@ import java.util.Optional; /** * Implementation of {@link androidx.window.util.DataProducer} that produces - * {@link CommonDisplayFeature} parsed from a string stored in {@link Settings}. + * {@link CommonFoldingFeature} parsed from a string stored in {@link Settings}. */ public final class SettingsDisplayFeatureProducer - extends BaseDataProducer> { + extends BaseDataProducer> { private static final boolean DEBUG = false; private static final String TAG = "SettingsDisplayFeatureProducer"; private static final String DISPLAY_FEATURES = "display_features"; @@ -58,22 +58,22 @@ public final class SettingsDisplayFeatureProducer @Override @Nullable - public Optional> getData() { + public Optional> getData() { String displayFeaturesString = Settings.Global.getString(mResolver, DISPLAY_FEATURES); if (displayFeaturesString == null) { return Optional.empty(); } - List features = new ArrayList<>(); + List features = new ArrayList<>(); if (TextUtils.isEmpty(displayFeaturesString)) { return Optional.of(features); } String[] featureStrings = displayFeaturesString.split(";"); for (String featureString : featureStrings) { - CommonDisplayFeature feature; + CommonFoldingFeature feature; try { - feature = CommonDisplayFeature.parseFromString(featureString); + feature = CommonFoldingFeature.parseFromString(featureString); } catch (IllegalArgumentException e) { if (DEBUG) { Log.w(TAG, "Failed to parse display feature: " + featureString, e); 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 fe9ce971d4d91..b4b75b4e9ca56 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -18,8 +18,8 @@ package androidx.window.extensions.layout; import static android.view.Display.DEFAULT_DISPLAY; -import static androidx.window.common.DisplayFeature.COMMON_STATE_FLAT; -import static androidx.window.common.DisplayFeature.COMMON_STATE_HALF_OPENED; +import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT; +import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED; import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation; import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; @@ -30,8 +30,8 @@ import android.graphics.Rect; import android.util.Log; import androidx.annotation.NonNull; +import androidx.window.common.CommonFoldingFeature; 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; @@ -56,7 +56,6 @@ import java.util.function.Consumer; */ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private static final String TAG = "SampleExtension"; - private static WindowLayoutComponent sInstance; private final Map> mWindowLayoutChangeListeners = new HashMap<>(); @@ -65,7 +64,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private final DataProducer mDevicePostureProducer; private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; - private final DataProducer> mDisplayFeatureProducer; + private final DataProducer> mDisplayFeatureProducer; public WindowLayoutComponentImpl(Context context) { mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); @@ -123,17 +122,18 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { } /** - * Calculate the {@link DisplayFeature.State} from the feature or the device posture producer. - * If the given {@link DisplayFeature.State} is not valid then {@code null} will be returned. - * The {@link FoldingFeature} should be ignored in the case of an invalid - * {@link DisplayFeature.State}. + * Calculate the {@link CommonFoldingFeature.State} from the feature or the device posture + * producer. + * If the given {@link CommonFoldingFeature.State} is not valid then {@code null} will be + * returned. The {@link FoldingFeature} should be ignored in the case of an invalid + * {@link CommonFoldingFeature.State}. * - * @param feature a {@link DisplayFeature} to provide the feature state if present. - * @return {@link DisplayFeature.State} of the hinge if present or the state from the posture - * produce if present. + * @param feature a {@link CommonFoldingFeature} to provide the feature state if present. + * @return {@link CommonFoldingFeature.State} of the hinge if present or the state from the + * posture produce if present. */ @Nullable - private Integer getFeatureState(DisplayFeature feature) { + private Integer getFeatureState(CommonFoldingFeature feature) { Integer featureState = feature.getState(); Optional posture = mDevicePostureProducer.getData(); Integer state = featureState == null ? posture.orElse(null) : featureState; @@ -142,13 +142,14 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { /** * A convenience method to translate from the common feature state to the extensions feature - * state. More specifically, translates from {@link DisplayFeature.State} to + * state. More specifically, translates from {@link CommonFoldingFeature.State} to * {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED}. If it is not * possible to translate, then we will return a {@code null} value. * - * @param state if it matches a value in {@link DisplayFeature.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 DisplayFeature.State} and {@code null} otherwise. + * @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. */ @Nullable private Integer convertToExtensionState(@Nullable Integer state) { @@ -172,33 +173,32 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { @NonNull private WindowLayoutInfo getWindowLayoutInfo(@NonNull Activity activity) { - List displayFeatures = + List displayFeatures = getDisplayFeatures(activity); return new WindowLayoutInfo(displayFeatures); } /** - * Translate from the {@link DisplayFeature} to - * {@link androidx.window.extensions.layout.DisplayFeature} for a given {@link Activity}. If a - * {@link DisplayFeature} is not valid then it will be omitted. + * Translate from the {@link CommonFoldingFeature} to + * {@link DisplayFeature} for a given {@link Activity}. If a + * {@link CommonFoldingFeature} is not valid then it will be omitted. * * For a {@link FoldingFeature} the bounds are localized into the {@link Activity} window - * coordinate space and the state is calculated either from {@link DisplayFeature#getState()} or - * {@link #mDisplayFeatureProducer}. The state from {@link #mDisplayFeatureProducer} may not be - * valid since {@link #mDisplayFeatureProducer} is a general state controller. If the state is - * not valid, the {@link FoldingFeature} is omitted from the {@link List} of - * {@link androidx.window.extensions.layout.DisplayFeature}. If the bounds are not valid, - * constructing a {@link FoldingFeature} will throw an {@link IllegalArgumentException} since - * this can cause negative UI effects down stream. + * coordinate space and the state is calculated either from + * {@link CommonFoldingFeature#getState()} or {@link #mDisplayFeatureProducer}. The state from + * {@link #mDisplayFeatureProducer} may not be valid since {@link #mDisplayFeatureProducer} is + * a general state controller. If the state is not valid, the {@link FoldingFeature} is omitted + * from the {@link List} of {@link DisplayFeature}. If the bounds are not valid, constructing a + * {@link FoldingFeature} will throw an {@link IllegalArgumentException} since this can cause + * negative UI effects down stream. * * @param activity a proxy for the {@link android.view.Window} that contains the - * {@link androidx.window.extensions.layout.DisplayFeature}. - * @return a {@link List} of valid {@link androidx.window.extensions.layout.DisplayFeature} that + * {@link DisplayFeature}. + * @return a {@link List} of valid {@link DisplayFeature} that * are within the {@link android.view.Window} of the {@link Activity} */ - 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"); @@ -211,10 +211,10 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { return features; } - Optional> storedFeatures = mDisplayFeatureProducer.getData(); + Optional> storedFeatures = mDisplayFeatureProducer.getData(); if (storedFeatures.isPresent()) { - for (DisplayFeature baseFeature : storedFeatures.get()) { + for (CommonFoldingFeature baseFeature : storedFeatures.get()) { Integer state = getFeatureState(baseFeature); if (state == null) { continue; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java index aa949f1261548..65e2a5e34f191 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java @@ -29,8 +29,8 @@ import android.os.IBinder; import android.util.Log; import androidx.annotation.NonNull; +import androidx.window.common.CommonFoldingFeature; 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; @@ -54,7 +54,7 @@ class SampleSidecarImpl extends StubSidecar { private final DataProducer mDevicePostureProducer; private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; - private final DataProducer> mDisplayFeatureProducer; + private final DataProducer> mDisplayFeatureProducer; SampleSidecarImpl(Context context) { mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); @@ -95,19 +95,19 @@ class SampleSidecarImpl extends StubSidecar { } private int deviceStateFromFeature() { - List storedFeatures = mDisplayFeatureProducer.getData() + List storedFeatures = mDisplayFeatureProducer.getData() .orElse(Collections.emptyList()); for (int i = 0; i < storedFeatures.size(); i++) { - DisplayFeature feature = storedFeatures.get(i); + CommonFoldingFeature feature = storedFeatures.get(i); final int state = feature.getState() == null ? -1 : feature.getState(); if (DEBUG && feature.getState() == null) { Log.d(TAG, "feature#getState was null for DisplayFeature: " + feature); } switch (state) { - case DisplayFeature.COMMON_STATE_FLAT: + case CommonFoldingFeature.COMMON_STATE_FLAT: return SidecarDeviceState.POSTURE_OPENED; - case DisplayFeature.COMMON_STATE_HALF_OPENED: + case CommonFoldingFeature.COMMON_STATE_HALF_OPENED: return SidecarDeviceState.POSTURE_HALF_OPENED; } } @@ -127,7 +127,7 @@ class SampleSidecarImpl extends StubSidecar { } private List getDisplayFeatures(@NonNull Activity activity) { - List features = new ArrayList(); + 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"); @@ -140,9 +140,9 @@ class SampleSidecarImpl extends StubSidecar { return features; } - Optional> storedFeatures = mDisplayFeatureProducer.getData(); + Optional> storedFeatures = mDisplayFeatureProducer.getData(); if (storedFeatures.isPresent()) { - for (DisplayFeature baseFeature : storedFeatures.get()) { + for (CommonFoldingFeature baseFeature : storedFeatures.get()) { SidecarDisplayFeature feature = new SidecarDisplayFeature(); Rect featureRect = baseFeature.getRect(); rotateRectToDisplayRotation(displayId, featureRect);