Skip to content
Snippets Groups Projects
Commit 4bc4a9cd authored by Diego Vela's avatar Diego Vela
Browse files

Report folds in SupportedWindowFeatures.

Report folds in SupportedWindowFeatures.
Add utility test method to check if device supports half opened mode.

Bug: 293340299
Test: atest CtsWindowManagerJetpackTestCases
Change-Id: I76ae0db0af2e7982149959f946641d4b9473d18e
parent adfb5266
No related branches found
No related tags found
No related merge requests found
......@@ -126,7 +126,7 @@ public final class CommonFoldingFeature {
* @see #FEATURE_PATTERN
* @return {@link List} of {@link CommonFoldingFeature}.
*/
static List<CommonFoldingFeature> parseListFromString(@NonNull String value,
public static List<CommonFoldingFeature> parseListFromString(@NonNull String value,
@State int hingeState) {
List<CommonFoldingFeature> features = new ArrayList<>();
String[] featureStrings = value.split(";");
......
......@@ -36,6 +36,7 @@ import androidx.window.util.BaseDataProducer;
import com.android.internal.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
......@@ -78,7 +79,9 @@ public final class DeviceStateManagerFoldingFeatureProducer
private int mCurrentBaseDeviceState = INVALID_DEVICE_STATE;
@NonNull
private final BaseDataProducer<String> mRawFoldSupplier;
private final RawFoldingFeatureProducer mRawFoldSupplier;
private final boolean mIsHalfOpenedSupported;
private final DeviceStateCallback mDeviceStateCallback = new DeviceStateCallback() {
@Override
......@@ -101,10 +104,12 @@ public final class DeviceStateManagerFoldingFeatureProducer
};
public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context,
@NonNull BaseDataProducer<String> rawFoldSupplier) {
@NonNull RawFoldingFeatureProducer rawFoldSupplier,
@NonNull DeviceStateManager deviceStateManager) {
mRawFoldSupplier = rawFoldSupplier;
String[] deviceStatePosturePairs = context.getResources()
.getStringArray(R.array.config_device_state_postures);
boolean isHalfOpenedSupported = false;
for (String deviceStatePosturePair : deviceStatePosturePairs) {
String[] deviceStatePostureMapping = deviceStatePosturePair.split(":");
if (deviceStatePostureMapping.length != 2) {
......@@ -128,12 +133,13 @@ public final class DeviceStateManagerFoldingFeatureProducer
}
continue;
}
isHalfOpenedSupported = isHalfOpenedSupported
|| posture == CommonFoldingFeature.COMMON_STATE_HALF_OPENED;
mDeviceStateToPostureMap.put(deviceState, posture);
}
mIsHalfOpenedSupported = isHalfOpenedSupported;
if (mDeviceStateToPostureMap.size() > 0) {
Objects.requireNonNull(context.getSystemService(DeviceStateManager.class))
Objects.requireNonNull(deviceStateManager)
.registerCallback(context.getMainExecutor(), mDeviceStateCallback);
}
}
......@@ -187,6 +193,31 @@ public final class DeviceStateManagerFoldingFeatureProducer
}
}
/**
* Returns a {@link List} of all the {@link CommonFoldingFeature} with the state set to
* {@link CommonFoldingFeature#COMMON_STATE_UNKNOWN}. This method parses a {@link String} so a
* caller should consider caching the value or the derived value.
*/
@NonNull
public List<CommonFoldingFeature> getFoldsWithUnknownState() {
Optional<String> optionalFoldingFeatureString = mRawFoldSupplier.getCurrentData();
if (optionalFoldingFeatureString.isPresent()) {
return CommonFoldingFeature.parseListFromString(
optionalFoldingFeatureString.get(), CommonFoldingFeature.COMMON_STATE_UNKNOWN
);
}
return Collections.emptyList();
}
/**
* Returns {@code true} if the device supports half-opened mode, {@code false} otherwise.
*/
public boolean isHalfOpenedSupported() {
return mIsHalfOpenedSupported;
}
/**
* Adds the data to the storeFeaturesConsumer when the data is ready.
* @param storeFeaturesConsumer a consumer to collect the data when it is first available.
......
......@@ -20,6 +20,7 @@ import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.Application;
import android.content.Context;
import android.hardware.devicestate.DeviceStateManager;
import android.util.Log;
import androidx.annotation.NonNull;
......@@ -63,6 +64,11 @@ public class WindowExtensionsImpl implements WindowExtensions {
return Objects.requireNonNull(ActivityThread.currentApplication());
}
@NonNull
private DeviceStateManager getDeviceStateManager() {
return Objects.requireNonNull(getApplication().getSystemService(DeviceStateManager.class));
}
@NonNull
private DeviceStateManagerFoldingFeatureProducer getFoldingFeatureProducer() {
if (mFoldingFeatureProducer == null) {
......@@ -73,7 +79,7 @@ public class WindowExtensionsImpl implements WindowExtensions {
new RawFoldingFeatureProducer(context);
mFoldingFeatureProducer =
new DeviceStateManagerFoldingFeatureProducer(context,
foldingFeatureProducer);
foldingFeatureProducer, getDeviceStateManager());
}
}
}
......
/*
* Copyright (C) 2024 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.layout;
import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import java.util.ArrayList;
import java.util.List;
/**
* Util functions for working with {@link androidx.window.extensions.layout.DisplayFoldFeature}.
*/
public class DisplayFoldFeatureUtil {
private DisplayFoldFeatureUtil() {}
private static DisplayFoldFeature create(CommonFoldingFeature foldingFeature,
boolean isHalfOpenedSupported) {
final int foldType;
if (foldingFeature.getType() == CommonFoldingFeature.COMMON_TYPE_HINGE) {
foldType = DisplayFoldFeature.TYPE_HINGE;
} else {
foldType = DisplayFoldFeature.TYPE_SCREEN_FOLD_IN;
}
DisplayFoldFeature.Builder featureBuilder = new DisplayFoldFeature.Builder(foldType);
if (isHalfOpenedSupported) {
featureBuilder.addProperty(DisplayFoldFeature.FOLD_PROPERTY_SUPPORTS_HALF_OPENED);
}
return featureBuilder.build();
}
/**
* Returns the list of supported {@link DisplayFeature} calculated from the
* {@link DeviceStateManagerFoldingFeatureProducer}.
*/
public static List<DisplayFoldFeature> extractDisplayFoldFeatures(
DeviceStateManagerFoldingFeatureProducer producer) {
List<DisplayFoldFeature> foldFeatures = new ArrayList<>();
List<CommonFoldingFeature> folds = producer.getFoldsWithUnknownState();
final boolean isHalfOpenedSupported = producer.isHalfOpenedSupported();
for (CommonFoldingFeature fold : folds) {
foldFeatures.add(DisplayFoldFeatureUtil.create(fold, isHalfOpenedSupported));
}
return foldFeatures;
}
}
......@@ -45,7 +45,6 @@ import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
import androidx.window.extensions.core.util.function.Consumer;
import androidx.window.util.DataProducer;
import java.util.ArrayList;
import java.util.Collections;
......@@ -56,10 +55,6 @@ import java.util.Set;
/**
* 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.
*/
public class WindowLayoutComponentImpl implements WindowLayoutComponent {
private static final String TAG = WindowLayoutComponentImpl.class.getSimpleName();
......@@ -71,7 +66,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
new ArrayMap<>();
@GuardedBy("mLock")
private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer;
private final DeviceStateManagerFoldingFeatureProducer mFoldingFeatureProducer;
@GuardedBy("mLock")
private final List<CommonFoldingFeature> mLastReportedFoldingFeatures = new ArrayList<>();
......@@ -87,12 +82,17 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
private final RawConfigurationChangedListener mRawConfigurationChangedListener =
new RawConfigurationChangedListener();
private final SupportedWindowFeatures mSupportedWindowFeatures;
public WindowLayoutComponentImpl(@NonNull Context context,
@NonNull DeviceStateManagerFoldingFeatureProducer foldingFeatureProducer) {
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
mFoldingFeatureProducer = foldingFeatureProducer;
mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
final List<DisplayFoldFeature> displayFoldFeatures =
DisplayFoldFeatureUtil.extractDisplayFoldFeatures(mFoldingFeatureProducer);
mSupportedWindowFeatures = new SupportedWindowFeatures.Builder(displayFoldFeatures).build();
}
/**
......@@ -283,6 +283,15 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
}
}
/**
* Returns the {@link SupportedWindowFeatures} for the device. This list does not change over
* time.
*/
@NonNull
public SupportedWindowFeatures getSupportedWindowFeatures() {
return mSupportedWindowFeatures;
}
/** @see #getWindowLayoutInfo(Context, List) */
private WindowLayoutInfo getWindowLayoutInfo(int displayId,
@NonNull WindowConfiguration windowConfiguration,
......
......@@ -17,6 +17,7 @@
package androidx.window.sidecar;
import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation;
import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect;
......@@ -25,6 +26,7 @@ import android.app.ActivityThread;
import android.app.Application;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Bundle;
import android.os.IBinder;
......@@ -49,10 +51,11 @@ class SampleSidecarImpl extends StubSidecar {
SampleSidecarImpl(Context context) {
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
BaseDataProducer<String> settingsFeatureProducer = new RawFoldingFeatureProducer(context);
RawFoldingFeatureProducer settingsFeatureProducer = new RawFoldingFeatureProducer(context);
BaseDataProducer<List<CommonFoldingFeature>> foldingFeatureProducer =
new DeviceStateManagerFoldingFeatureProducer(context,
settingsFeatureProducer);
settingsFeatureProducer,
context.getSystemService(DeviceStateManager.class));
foldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment