Merge "Fix emulator not emitting folding feature." into tm-dev am: dbda026b6f am: 94d417a62c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17511593
Change-Id: Ibc0abfac92e08f547c7ff1418de0bb4771c6a48a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
index 6987401..fdcb7be 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
@@ -31,11 +31,13 @@
import android.util.SparseIntArray;
import androidx.window.util.BaseDataProducer;
+import androidx.window.util.DataProducer;
import com.android.internal.R;
import java.util.List;
import java.util.Optional;
+import java.util.Set;
/**
* An implementation of {@link androidx.window.util.DataProducer} that returns the device's posture
@@ -48,7 +50,6 @@
DeviceStateManagerFoldingFeatureProducer.class.getSimpleName();
private static final boolean DEBUG = false;
- private final Context mContext;
private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray();
private int mCurrentDeviceState = INVALID_DEVICE_STATE;
@@ -57,9 +58,12 @@
mCurrentDeviceState = state;
notifyDataChanged();
};
+ @NonNull
+ private final DataProducer<String> mRawFoldSupplier;
- public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context) {
- mContext = context;
+ public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context,
+ @NonNull DataProducer<String> rawFoldSupplier) {
+ mRawFoldSupplier = rawFoldSupplier;
String[] deviceStatePosturePairs = context.getResources()
.getStringArray(R.array.config_device_state_postures);
for (String deviceStatePosturePair : deviceStatePosturePairs) {
@@ -97,12 +101,21 @@
@Nullable
public Optional<List<CommonFoldingFeature>> getData() {
final int globalHingeState = globalHingeState();
- String displayFeaturesString = mContext.getResources().getString(
- R.string.config_display_features);
- if (TextUtils.isEmpty(displayFeaturesString)) {
+ Optional<String> displayFeaturesString = mRawFoldSupplier.getData();
+ if (displayFeaturesString.isEmpty() || TextUtils.isEmpty(displayFeaturesString.get())) {
return Optional.empty();
}
- return Optional.of(parseListFromString(displayFeaturesString, globalHingeState));
+ return Optional.of(parseListFromString(displayFeaturesString.get(), globalHingeState));
+ }
+
+ @Override
+ protected void onListenersChanged(Set<Runnable> callbacks) {
+ super.onListenersChanged(callbacks);
+ if (callbacks.isEmpty()) {
+ mRawFoldSupplier.removeDataChangedCallback(this::notifyDataChanged);
+ } else {
+ mRawFoldSupplier.addDataChangedCallback(this::notifyDataChanged);
+ }
}
private int globalHingeState() {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java
new file mode 100644
index 0000000..69ad1ba
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/RawFoldingFeatureProducer.java
@@ -0,0 +1,132 @@
+/*
+ * 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.NonNull;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import androidx.window.util.BaseDataProducer;
+
+import com.android.internal.R;
+
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Implementation of {@link androidx.window.util.DataProducer} that produces a
+ * {@link String} that can be parsed to a {@link CommonFoldingFeature}.
+ * {@link RawFoldingFeatureProducer} searches for the value in two places. The first check is in
+ * settings where the {@link String} property is saved with the key
+ * {@link RawFoldingFeatureProducer#DISPLAY_FEATURES}. If this value is null or empty then the
+ * value in {@link android.content.res.Resources} is used. If both are empty then
+ * {@link RawFoldingFeatureProducer#getData()} returns an empty object.
+ * {@link RawFoldingFeatureProducer} listens to changes in the setting so that it can override
+ * the system {@link CommonFoldingFeature} data.
+ */
+public final class RawFoldingFeatureProducer extends BaseDataProducer<String> {
+ private static final String DISPLAY_FEATURES = "display_features";
+
+ private final Uri mDisplayFeaturesUri =
+ Settings.Global.getUriFor(DISPLAY_FEATURES);
+
+ private final ContentResolver mResolver;
+ private final ContentObserver mObserver;
+ private final String mResourceFeature;
+ private boolean mRegisteredObservers;
+
+ public RawFoldingFeatureProducer(@NonNull Context context) {
+ mResolver = context.getContentResolver();
+ mObserver = new SettingsObserver();
+ mResourceFeature = context.getResources().getString(R.string.config_display_features);
+ }
+
+ @Override
+ @NonNull
+ public Optional<String> getData() {
+ String displayFeaturesString = getFeatureString();
+ if (displayFeaturesString == null) {
+ return Optional.empty();
+ }
+ return Optional.of(displayFeaturesString);
+ }
+
+ /**
+ * Returns the {@link String} representation for a {@link CommonFoldingFeature} from settings if
+ * present and falls back to the resource value if empty or {@code null}.
+ */
+ private String getFeatureString() {
+ String settingsFeature = Settings.Global.getString(mResolver, DISPLAY_FEATURES);
+ if (TextUtils.isEmpty(settingsFeature)) {
+ return mResourceFeature;
+ }
+ return settingsFeature;
+ }
+
+ @Override
+ protected void onListenersChanged(Set<Runnable> callbacks) {
+ if (callbacks.isEmpty()) {
+ unregisterObserversIfNeeded();
+ } else {
+ registerObserversIfNeeded();
+ }
+ }
+
+ /**
+ * Registers settings observers, if needed. When settings observers are registered for this
+ * producer callbacks for changes in data will be triggered.
+ */
+ private void registerObserversIfNeeded() {
+ if (mRegisteredObservers) {
+ return;
+ }
+ mRegisteredObservers = true;
+ mResolver.registerContentObserver(mDisplayFeaturesUri, false /* notifyForDescendants */,
+ mObserver /* ContentObserver */);
+ }
+
+ /**
+ * Unregisters settings observers, if needed. When settings observers are unregistered for this
+ * producer callbacks for changes in data will not be triggered.
+ */
+ private void unregisterObserversIfNeeded() {
+ if (!mRegisteredObservers) {
+ return;
+ }
+ mRegisteredObservers = false;
+ mResolver.unregisterContentObserver(mObserver);
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ SettingsObserver() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mDisplayFeaturesUri.equals(uri)) {
+ notifyDataChanged();
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java
deleted file mode 100644
index 0e696eb..0000000
--- a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java
+++ /dev/null
@@ -1,124 +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 static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT;
-import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED;
-import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN;
-import static androidx.window.common.CommonFoldingFeature.parseListFromString;
-
-import android.annotation.NonNull;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import androidx.window.util.BaseDataProducer;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Implementation of {@link androidx.window.util.DataProducer} that produces
- * {@link CommonFoldingFeature} parsed from a string stored in {@link Settings}.
- */
-public final class SettingsDisplayFeatureProducer
- extends BaseDataProducer<List<CommonFoldingFeature>> {
- private static final String DISPLAY_FEATURES = "display_features";
- private static final String DEVICE_POSTURE = "device_posture";
-
- private final Uri mDevicePostureUri =
- Settings.Global.getUriFor(DEVICE_POSTURE);
- private final Uri mDisplayFeaturesUri =
- Settings.Global.getUriFor(DISPLAY_FEATURES);
-
- private final ContentResolver mResolver;
- private final ContentObserver mObserver;
- private boolean mRegisteredObservers;
-
- public SettingsDisplayFeatureProducer(@NonNull Context context) {
- mResolver = context.getContentResolver();
- mObserver = new SettingsObserver();
- }
-
- private int getPosture() {
- int posture = Settings.Global.getInt(mResolver, DEVICE_POSTURE, COMMON_STATE_UNKNOWN);
- if (posture == COMMON_STATE_HALF_OPENED || posture == COMMON_STATE_FLAT) {
- return posture;
- } else {
- return COMMON_STATE_UNKNOWN;
- }
- }
-
- @Override
- @NonNull
- public Optional<List<CommonFoldingFeature>> getData() {
- String displayFeaturesString = Settings.Global.getString(mResolver, DISPLAY_FEATURES);
- if (displayFeaturesString == null) {
- return Optional.empty();
- }
-
- if (TextUtils.isEmpty(displayFeaturesString)) {
- return Optional.of(Collections.emptyList());
- }
- return Optional.of(parseListFromString(displayFeaturesString, getPosture()));
- }
-
- /**
- * Registers settings observers, if needed. When settings observers are registered for this
- * producer callbacks for changes in data will be triggered.
- */
- public void registerObserversIfNeeded() {
- if (mRegisteredObservers) {
- return;
- }
- mRegisteredObservers = true;
- mResolver.registerContentObserver(mDisplayFeaturesUri, false /* notifyForDescendants */,
- mObserver /* ContentObserver */);
- mResolver.registerContentObserver(mDevicePostureUri, false, mObserver);
- }
-
- /**
- * Unregisters settings observers, if needed. When settings observers are unregistered for this
- * producer callbacks for changes in data will not be triggered.
- */
- public void unregisterObserversIfNeeded() {
- if (!mRegisteredObservers) {
- return;
- }
- mRegisteredObservers = false;
- mResolver.unregisterContentObserver(mObserver);
- }
-
- private final class SettingsObserver extends ContentObserver {
- SettingsObserver() {
- super(new Handler(Looper.getMainLooper()));
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (mDisplayFeaturesUri.equals(uri) || mDevicePostureUri.equals(uri)) {
- notifyDataChanged();
- }
- }
- }
-}
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 a4fbdbc..2f7d958 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -37,9 +37,8 @@
import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
-import androidx.window.common.SettingsDisplayFeatureProducer;
+import androidx.window.common.RawFoldingFeatureProducer;
import androidx.window.util.DataProducer;
-import androidx.window.util.PriorityDataProducer;
import java.util.ArrayList;
import java.util.List;
@@ -62,17 +61,14 @@
private final Map<Activity, Consumer<WindowLayoutInfo>> mWindowLayoutChangeListeners =
new ArrayMap<>();
- private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer;
private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer;
public WindowLayoutComponentImpl(Context context) {
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
- mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context);
- mFoldingFeatureProducer = new PriorityDataProducer<>(List.of(
- mSettingsDisplayFeatureProducer,
- new DeviceStateManagerFoldingFeatureProducer(context)
- ));
+ RawFoldingFeatureProducer foldingFeatureProducer = new RawFoldingFeatureProducer(context);
+ mFoldingFeatureProducer = new DeviceStateManagerFoldingFeatureProducer(context,
+ foldingFeatureProducer);
mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
}
@@ -85,7 +81,7 @@
public void addWindowLayoutInfoListener(@NonNull Activity activity,
@NonNull Consumer<WindowLayoutInfo> consumer) {
mWindowLayoutChangeListeners.put(activity, consumer);
- updateRegistrations();
+ onDisplayFeaturesChanged();
}
/**
@@ -96,7 +92,7 @@
public void removeWindowLayoutInfoListener(
@NonNull Consumer<WindowLayoutInfo> consumer) {
mWindowLayoutChangeListeners.values().remove(consumer);
- updateRegistrations();
+ onDisplayFeaturesChanged();
}
void updateWindowLayout(@NonNull Activity activity,
@@ -210,15 +206,6 @@
return features;
}
- private void updateRegistrations() {
- if (hasListeners()) {
- mSettingsDisplayFeatureProducer.registerObserversIfNeeded();
- } else {
- mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded();
- }
- onDisplayFeaturesChanged();
- }
-
private final class NotifyOnConfigurationChanged extends EmptyLifecycleCallbacksAdapter {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
index c7b7093..970f0a2 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java
@@ -34,9 +34,8 @@
import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
-import androidx.window.common.SettingsDisplayFeatureProducer;
+import androidx.window.common.RawFoldingFeatureProducer;
import androidx.window.util.DataProducer;
-import androidx.window.util.PriorityDataProducer;
import java.util.ArrayList;
import java.util.Collections;
@@ -52,16 +51,13 @@
private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer;
- private final SettingsDisplayFeatureProducer mSettingsFoldingFeatureProducer;
SampleSidecarImpl(Context context) {
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
- mSettingsFoldingFeatureProducer = new SettingsDisplayFeatureProducer(context);
- mFoldingFeatureProducer = new PriorityDataProducer<>(List.of(
- mSettingsFoldingFeatureProducer,
- new DeviceStateManagerFoldingFeatureProducer(context)
- ));
+ DataProducer<String> settingsFeatureProducer = new RawFoldingFeatureProducer(context);
+ mFoldingFeatureProducer = new DeviceStateManagerFoldingFeatureProducer(context,
+ settingsFeatureProducer);
mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
}
@@ -142,10 +138,7 @@
@Override
protected void onListenersChanged() {
if (hasListeners()) {
- mSettingsFoldingFeatureProducer.registerObserversIfNeeded();
onDisplayFeaturesChanged();
- } else {
- mSettingsFoldingFeatureProducer.unregisterObserversIfNeeded();
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java
index 0a46703451..930db3b 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/BaseDataProducer.java
@@ -33,13 +33,17 @@
@Override
public final void addDataChangedCallback(@NonNull Runnable callback) {
mCallbacks.add(callback);
+ onListenersChanged(mCallbacks);
}
@Override
public final void removeDataChangedCallback(@NonNull Runnable callback) {
mCallbacks.remove(callback);
+ onListenersChanged(mCallbacks);
}
+ protected void onListenersChanged(Set<Runnable> callbacks) {}
+
/**
* Called to notify all registered callbacks that the data provided by {@link #getData()} has
* changed.
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/PriorityDataProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/util/PriorityDataProducer.java
deleted file mode 100644
index 990ae20..0000000
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/PriorityDataProducer.java
+++ /dev/null
@@ -1,56 +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.util;
-
-import android.annotation.Nullable;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Implementation of {@link DataProducer} that delegates calls to {@link #getData()} to the list of
- * provided child producers.
- * <p>
- * The value returned is based on the precedence of the supplied children where the producer with
- * index 0 has a higher precedence than producers that come later in the list. When a producer with
- * a higher precedence has a non-empty value returned from {@link #getData()}, its value will be
- * returned from an instance of this class, ignoring all other producers with lower precedence.
- *
- * @param <T> The type of data this producer returns through {@link #getData()}.
- */
-public final class PriorityDataProducer<T> extends BaseDataProducer<T> {
- private final List<DataProducer<T>> mChildProducers;
-
- public PriorityDataProducer(List<DataProducer<T>> childProducers) {
- mChildProducers = childProducers;
- for (DataProducer<T> childProducer : mChildProducers) {
- childProducer.addDataChangedCallback(this::notifyDataChanged);
- }
- }
-
- @Nullable
- @Override
- public Optional<T> getData() {
- for (DataProducer<T> childProducer : mChildProducers) {
- final Optional<T> data = childProducer.getData();
- if (data.isPresent()) {
- return data;
- }
- }
- return Optional.empty();
- }
-}