diff options
author | Matt Lee <matthewhlee@google.com> | 2022-06-12 23:19:47 +0000 |
---|---|---|
committer | Matt Lee <matthewhlee@google.com> | 2022-06-12 23:19:47 +0000 |
commit | 2ee3b28251c8f6864a6dbcd229b7a1641a4782e4 (patch) | |
tree | 3577b78cd7727ed3695b831753db86a62462ed7b /libs | |
parent | 64c414abd49acc8d488837ab90b51d822c23e66d (diff) |
Revert "Merge s-mpr-2022-06"
Revert submission 732792
Reason for revert: build failure
Reverted Changes:
I3cbe7c924:Merge s-mpr-2022-06
I9881453ba:Don't set background color if TDA doesn't have a v...
I57fa88c6f:Use TDA for background color instead of new color ...
Ic2fa89b76:Dialing phone state should update active sub
Change-Id: I9709841558bfcb325f7e205f5f5ec89c620d14dd
Diffstat (limited to 'libs')
20 files changed, 465 insertions, 489 deletions
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java index 8733c152dca9..eb9429747b66 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java @@ -18,73 +18,17 @@ package androidx.window.common; import static androidx.window.util.ExtensionHelper.isZero; -import android.annotation.IntDef; import android.annotation.Nullable; import android.graphics.Rect; -import android.util.Log; import androidx.annotation.NonNull; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -/** 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 { - - private static final boolean DEBUG = false; - - public static final String TAG = CommonFoldingFeature.class.getSimpleName(); - - /** - * 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 when the state is not known. One example is if the device is - * closed. We do not emit this value for developers but is useful for implementation reasons. - */ - public static final int COMMON_STATE_UNKNOWN = -1; - - /** - * 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_UNKNOWN, COMMON_STATE_FLAT, COMMON_STATE_HALF_OPENED}) - @Retention(RetentionPolicy.SOURCE) - public @interface State { - } - +/** Wrapper for both Extension and Sidecar versions of DisplayFeature. */ +final class CommonDisplayFeature implements DisplayFeature { private static final Pattern FEATURE_PATTERN = Pattern.compile("([a-z]+)-\\[(\\d+),(\\d+),(\\d+),(\\d+)]-?(flat|half-opened)?"); @@ -94,49 +38,17 @@ public final class CommonFoldingFeature { private static final String PATTERN_STATE_FLAT = "flat"; private static final String PATTERN_STATE_HALF_OPENED = "half-opened"; - /** - * Parse a {@link List} of {@link CommonFoldingFeature} from a {@link String}. - * @param value a {@link String} representation of multiple {@link CommonFoldingFeature} - * separated by a ":". - * @param hingeState a global fallback value for a {@link CommonFoldingFeature} if one is not - * specified in the input. - * @throws IllegalArgumentException if the provided string is improperly formatted or could not - * otherwise be parsed. - * @see #FEATURE_PATTERN - * @return {@link List} of {@link CommonFoldingFeature}. - */ - static List<CommonFoldingFeature> parseListFromString(@NonNull String value, - @State int hingeState) { - List<CommonFoldingFeature> features = new ArrayList<>(); - String[] featureStrings = value.split(";"); - for (String featureString : featureStrings) { - CommonFoldingFeature feature; - try { - feature = CommonFoldingFeature.parseFromString(featureString, hingeState); - } catch (IllegalArgumentException e) { - if (DEBUG) { - Log.w(TAG, "Failed to parse display feature: " + featureString, e); - } - continue; - } - features.add(feature); - } - return features; - } + // TODO(b/183049815): Support feature strings that include the state of the feature. /** * Parses a display feature from a string. * - * @param string A {@link String} representation of a {@link CommonFoldingFeature}. - * @param hingeState A fallback value for the {@link State} if it is not specified in the input. * @throws IllegalArgumentException if the provided string is improperly formatted or could not * otherwise be parsed. - * @return {@link CommonFoldingFeature} represented by the {@link String} value. * @see #FEATURE_PATTERN */ @NonNull - private static CommonFoldingFeature parseFromString(@NonNull String string, - @State int hingeState) { + static CommonDisplayFeature parseFromString(@NonNull String string) { Matcher featureMatcher = FEATURE_PATTERN.matcher(string); if (!featureMatcher.matches()) { throw new IllegalArgumentException("Malformed feature description format: " + string); @@ -147,10 +59,10 @@ public final class CommonFoldingFeature { int type; switch (featureType) { case FEATURE_TYPE_FOLD: - type = COMMON_TYPE_FOLD; + type = 1 /* TYPE_FOLD */; break; case FEATURE_TYPE_HINGE: - type = COMMON_TYPE_HINGE; + type = 2 /* TYPE_HINGE */; break; default: { throw new IllegalArgumentException("Malformed feature type: " + featureType); @@ -167,7 +79,7 @@ public final class CommonFoldingFeature { } String stateString = featureMatcher.group(6); stateString = stateString == null ? "" : stateString; - final int state; + Integer state; switch (stateString) { case PATTERN_STATE_FLAT: state = COMMON_STATE_FLAT; @@ -176,10 +88,10 @@ public final class CommonFoldingFeature { state = COMMON_STATE_HALF_OPENED; break; default: - state = hingeState; + state = null; break; } - return new CommonFoldingFeature(type, state, featureRect); + return new CommonDisplayFeature(type, state, featureRect); } catch (NumberFormatException e) { throw new IllegalArgumentException("Malformed feature description: " + string, e); } @@ -187,11 +99,11 @@ public final class CommonFoldingFeature { private final int mType; @Nullable - private final int mState; + private final Integer mState; @NonNull private final Rect mRect; - CommonFoldingFeature(int type, int state, @NonNull Rect rect) { + CommonDisplayFeature(int type, @Nullable Integer state, @NonNull Rect rect) { assertValidState(state); this.mType = type; this.mState = state; @@ -202,19 +114,16 @@ public final class CommonFoldingFeature { 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. */ - @State - public int getState() { + @Nullable + public Integer getState() { return mState; } - /** Returns the bounds of the feature. */ @NonNull public Rect getRect() { return mRect; @@ -224,7 +133,7 @@ public final class CommonFoldingFeature { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - CommonFoldingFeature that = (CommonFoldingFeature) o; + CommonDisplayFeature that = (CommonDisplayFeature) o; return mType == that.mType && Objects.equals(mState, that.mState) && mRect.equals(that.mRect); @@ -236,8 +145,7 @@ public final class CommonFoldingFeature { } private static void assertValidState(@Nullable Integer state) { - if (state != null && state != COMMON_STATE_FLAT - && state != COMMON_STATE_HALF_OPENED && state != COMMON_STATE_UNKNOWN) { + if (state != null && state != COMMON_STATE_FLAT && state != COMMON_STATE_HALF_OPENED) { throw new IllegalArgumentException("Invalid state: " + state + "must be either COMMON_STATE_FLAT or COMMON_STATE_HALF_OPENED"); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerPostureProducer.java index 6987401525b4..fa9a5a8b7a1b 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerPostureProducer.java @@ -18,15 +18,11 @@ package androidx.window.common; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE; -import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN; -import static androidx.window.common.CommonFoldingFeature.parseListFromString; - import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback; -import android.text.TextUtils; import android.util.Log; import android.util.SparseIntArray; @@ -34,7 +30,6 @@ import androidx.window.util.BaseDataProducer; import com.android.internal.R; -import java.util.List; import java.util.Optional; /** @@ -42,13 +37,10 @@ import java.util.Optional; * by mapping the state returned from {@link DeviceStateManager} to values provided in the resources * config at {@link R.array#config_device_state_postures}. */ -public final class DeviceStateManagerFoldingFeatureProducer extends - BaseDataProducer<List<CommonFoldingFeature>> { - private static final String TAG = - DeviceStateManagerFoldingFeatureProducer.class.getSimpleName(); +public final class DeviceStateManagerPostureProducer extends BaseDataProducer<Integer> { + private static final String TAG = "ConfigDevicePostureProducer"; private static final boolean DEBUG = false; - private final Context mContext; private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray(); private int mCurrentDeviceState = INVALID_DEVICE_STATE; @@ -58,8 +50,7 @@ public final class DeviceStateManagerFoldingFeatureProducer extends notifyDataChanged(); }; - public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context) { - mContext = context; + public DeviceStateManagerPostureProducer(@NonNull Context context) { String[] deviceStatePosturePairs = context.getResources() .getStringArray(R.array.config_device_state_postures); for (String deviceStatePosturePair : deviceStatePosturePairs) { @@ -95,17 +86,8 @@ public final class DeviceStateManagerFoldingFeatureProducer extends @Override @Nullable - public Optional<List<CommonFoldingFeature>> getData() { - final int globalHingeState = globalHingeState(); - String displayFeaturesString = mContext.getResources().getString( - R.string.config_display_features); - if (TextUtils.isEmpty(displayFeaturesString)) { - return Optional.empty(); - } - return Optional.of(parseListFromString(displayFeaturesString, globalHingeState)); - } - - private int globalHingeState() { - return mDeviceStateToPostureMap.get(mCurrentDeviceState, COMMON_STATE_UNKNOWN); + public Optional<Integer> getData() { + final int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState, -1); + return posture != -1 ? Optional.of(posture) : Optional.empty(); } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java new file mode 100644 index 000000000000..573641857b99 --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java @@ -0,0 +1,60 @@ +/* + * 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/EmptyLifecycleCallbacksAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/common/EmptyLifecycleCallbacksAdapter.java deleted file mode 100644 index f2e403b4f792..000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/EmptyLifecycleCallbacksAdapter.java +++ /dev/null @@ -1,55 +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.app.Activity; -import android.app.Application; -import android.os.Bundle; - -/** - * An empty implementation of {@link Application.ActivityLifecycleCallbacks} derived classes can - * implement the methods necessary. - */ -public class EmptyLifecycleCallbacksAdapter implements Application.ActivityLifecycleCallbacks { - @Override - public void onActivityCreated(Activity activity, Bundle savedInstanceState) { - } - - @Override - public void onActivityStarted(Activity activity) { - } - - @Override - public void onActivityResumed(Activity activity) { - } - - @Override - public void onActivityPaused(Activity activity) { - } - - @Override - public void onActivityStopped(Activity activity) { - } - - @Override - public void onActivitySaveInstanceState(Activity activity, Bundle outState) { - } - - @Override - public void onActivityDestroyed(Activity activity) { - } -} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java new file mode 100644 index 000000000000..cd2cadc082e1 --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java @@ -0,0 +1,74 @@ +/* + * 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.annotation.Nullable; +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import androidx.window.util.BaseDataProducer; + +import com.android.internal.R; + +import java.util.ArrayList; +import java.util.List; +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 R.string#config_display_features}. + */ +public final class ResourceConfigDisplayFeatureProducer extends + BaseDataProducer<List<DisplayFeature>> { + private static final boolean DEBUG = false; + private static final String TAG = "ResourceConfigDisplayFeatureProducer"; + + private final Context mContext; + + public ResourceConfigDisplayFeatureProducer(@NonNull Context context) { + mContext = context; + } + + @Override + @Nullable + public Optional<List<DisplayFeature>> getData() { + String displayFeaturesString = mContext.getResources().getString( + R.string.config_display_features); + if (TextUtils.isEmpty(displayFeaturesString)) { + return Optional.empty(); + } + + List<DisplayFeature> features = new ArrayList<>(); + String[] featureStrings = displayFeaturesString.split(";"); + for (String featureString : featureStrings) { + CommonDisplayFeature feature; + try { + feature = CommonDisplayFeature.parseFromString(featureString); + } catch (IllegalArgumentException e) { + if (DEBUG) { + Log.w(TAG, "Failed to parse display feature: " + featureString, e); + } + continue; + } + features.add(feature); + } + return Optional.of(features); + } +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java new file mode 100644 index 000000000000..2026df3fa979 --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java @@ -0,0 +1,96 @@ +/* + * 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.annotation.Nullable; +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 androidx.window.util.BaseDataProducer; + +import java.util.Optional; + +/** + * Implementation of {@link androidx.window.util.DataProducer} that provides the device posture + * as an {@link Integer} from a value stored in {@link Settings}. + */ +public final class SettingsDevicePostureProducer extends BaseDataProducer<Integer> { + private static final String DEVICE_POSTURE = "device_posture"; + + private final Uri mDevicePostureUri = + Settings.Global.getUriFor(DEVICE_POSTURE); + + private final ContentResolver mResolver; + private final ContentObserver mObserver; + private boolean mRegisteredObservers; + + public SettingsDevicePostureProducer(@NonNull Context context) { + mResolver = context.getContentResolver(); + mObserver = new SettingsObserver(); + } + + @Override + @Nullable + public Optional<Integer> getData() { + int posture = Settings.Global.getInt(mResolver, DEVICE_POSTURE, -1); + return posture == -1 ? Optional.empty() : Optional.of(posture); + } + + /** + * 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(mDevicePostureUri, 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. + */ + 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 (mDevicePostureUri.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 index 0e696eb8efb7..040662657a74 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java @@ -16,12 +16,8 @@ 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.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; @@ -30,24 +26,24 @@ import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.text.TextUtils; +import android.util.Log; import androidx.window.util.BaseDataProducer; -import java.util.Collections; +import java.util.ArrayList; 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}. + * {@link CommonDisplayFeature} parsed from a string stored in {@link Settings}. */ public final class SettingsDisplayFeatureProducer - extends BaseDataProducer<List<CommonFoldingFeature>> { + extends BaseDataProducer<List<DisplayFeature>> { + private static final boolean DEBUG = false; + private static final String TAG = "SettingsDisplayFeatureProducer"; 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); @@ -60,27 +56,33 @@ public final class SettingsDisplayFeatureProducer 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() { + @Nullable + public Optional<List<DisplayFeature>> getData() { String displayFeaturesString = Settings.Global.getString(mResolver, DISPLAY_FEATURES); if (displayFeaturesString == null) { return Optional.empty(); } + List<DisplayFeature> features = new ArrayList<>(); if (TextUtils.isEmpty(displayFeaturesString)) { - return Optional.of(Collections.emptyList()); + return Optional.of(features); + } + String[] featureStrings = displayFeaturesString.split(";"); + + for (String featureString : featureStrings) { + CommonDisplayFeature feature; + try { + feature = CommonDisplayFeature.parseFromString(featureString); + } catch (IllegalArgumentException e) { + if (DEBUG) { + Log.w(TAG, "Failed to parse display feature: " + featureString, e); + } + continue; + } + features.add(feature); } - return Optional.of(parseListFromString(displayFeaturesString, getPosture())); + return Optional.of(features); } /** @@ -94,7 +96,6 @@ public final class SettingsDisplayFeatureProducer mRegisteredObservers = true; mResolver.registerContentObserver(mDisplayFeaturesUri, false /* notifyForDescendants */, mObserver /* ContentObserver */); - mResolver.registerContentObserver(mDevicePostureUri, false, mObserver); } /** @@ -116,7 +117,7 @@ public final class SettingsDisplayFeatureProducer @Override public void onChange(boolean selfChange, Uri uri) { - if (mDisplayFeaturesUri.equals(uri) || mDevicePostureUri.equals(uri)) { + if (mDisplayFeaturesUri.equals(uri)) { notifyDataChanged(); } } 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 fc955927f3ed..8f368c2bee22 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -28,6 +28,7 @@ import android.app.Activity; import android.app.ActivityClient; import android.app.ActivityOptions; import android.app.ActivityThread; +import android.app.Application.ActivityLifecycleCallbacks; import android.app.Instrumentation; import android.content.Context; import android.content.Intent; @@ -40,8 +41,6 @@ import android.os.Looper; import android.window.TaskFragmentInfo; import android.window.WindowContainerTransaction; -import androidx.window.common.EmptyLifecycleCallbacksAdapter; - import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -760,7 +759,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return shouldRetainAssociatedContainer(finishingContainer, associatedContainer); } - private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter { + private final class LifecycleCallbacks implements ActivityLifecycleCallbacks { + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + } @Override public void onActivityPostCreated(Activity activity, Bundle savedInstanceState) { @@ -772,6 +775,30 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } @Override + public void onActivityStarted(Activity activity) { + } + + @Override + public void onActivityResumed(Activity activity) { + } + + @Override + public void onActivityPaused(Activity activity) { + } + + @Override + public void onActivityStopped(Activity activity) { + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + } + + @Override + public void onActivityDestroyed(Activity activity) { + } + + @Override public void onActivityConfigurationChanged(Activity activity) { SplitController.this.onActivityConfigurationChanged(activity); } @@ -806,8 +833,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen if (shouldExpand(null, intent, getSplitRules())) { setLaunchingInExpandedContainer(launchingActivity, options); - } else if (!splitWithLaunchingActivity(launchingActivity, intent, options)) { - setLaunchingInSameSideContainer(launchingActivity, intent, options); + } else if (!setLaunchingToSideContainer(launchingActivity, intent, options)) { + setLaunchingInSameContainer(launchingActivity, intent, options); } return super.onStartActivity(who, intent, options); @@ -826,9 +853,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen /** * 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 - * launched in the side container. + * launched in an empty side container. */ - private boolean splitWithLaunchingActivity(Activity launchingActivity, Intent intent, + private boolean setLaunchingToSideContainer(Activity launchingActivity, Intent intent, Bundle options) { final SplitPairRule splitPairRule = getSplitRule(launchingActivity, intent, getSplitRules()); @@ -836,14 +863,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return false; } - // Check if there is any existing side container to launch into. - TaskFragmentContainer secondaryContainer = findSideContainerForNewLaunch( - launchingActivity, splitPairRule); - if (secondaryContainer == null) { - // Create a new split with an empty side container. - secondaryContainer = mPresenter - .createNewSplitWithEmptySideContainer(launchingActivity, splitPairRule); - } + // Create a new split with an empty side container + final TaskFragmentContainer secondaryContainer = mPresenter + .createNewSplitWithEmptySideContainer(launchingActivity, splitPairRule); // Amend the request to let the WM know that the activity should be placed in the // dedicated container. @@ -853,39 +875,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } /** - * Finds if there is an existing split side {@link TaskFragmentContainer} that can be used - * for the new rule. - */ - @Nullable - private TaskFragmentContainer findSideContainerForNewLaunch(Activity launchingActivity, - SplitPairRule splitPairRule) { - final TaskFragmentContainer launchingContainer = getContainerWithActivity( - launchingActivity.getActivityToken()); - if (launchingContainer == null) { - return null; - } - - // We only check if the launching activity is the primary of the split. We will check - // if the launching activity is the secondary in #setLaunchingInSameSideContainer. - final SplitContainer splitContainer = getActiveSplitForContainer(launchingContainer); - if (splitContainer == null - || splitContainer.getPrimaryContainer() != launchingContainer) { - return null; - } - - if (canReuseContainer(splitPairRule, splitContainer.getSplitRule())) { - return splitContainer.getSecondaryContainer(); - } - return null; - } - - /** * Checks if the activity that is going to be started via the {@code intent} should be * paired with the existing top activity which is currently paired with the - * {@code launchingActivity}. If so, set the activity to be launched in the same side + * {@code launchingActivity}. If so, set the activity to be launched in the same * container of the {@code launchingActivity}. */ - private void setLaunchingInSameSideContainer(Activity launchingActivity, Intent intent, + private void setLaunchingInSameContainer(Activity launchingActivity, Intent intent, Bundle options) { final TaskFragmentContainer launchingContainer = getContainerWithActivity( launchingActivity.getActivityToken()); @@ -916,11 +911,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } - // Can only launch in the same container if the rules share the same presentation. - if (!canReuseContainer(splitPairRule, splitContainer.getSplitRule())) { - return; - } - // Amend the request to let the WM know that the activity should be placed in the // dedicated container. This is necessary for the case that the activity is started // into a new Task, or new Task will be escaped from the current host Task and be @@ -937,31 +927,4 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen public boolean isActivityEmbedded(@NonNull Activity activity) { return mPresenter.isActivityEmbedded(activity.getActivityToken()); } - - /** - * If the two rules have the same presentation, we can reuse the same {@link SplitContainer} if - * there is any. - */ - private static boolean canReuseContainer(SplitRule rule1, SplitRule rule2) { - if (!isContainerReusableRule(rule1) || !isContainerReusableRule(rule2)) { - return false; - } - return rule1.getSplitRatio() == rule2.getSplitRatio() - && rule1.getLayoutDirection() == rule2.getLayoutDirection(); - } - - /** - * Whether it is ok for other rule to reuse the {@link TaskFragmentContainer} of the given - * rule. - */ - private static boolean isContainerReusableRule(SplitRule rule) { - // We don't expect to reuse the placeholder rule. - if (!(rule instanceof SplitPairRule)) { - return false; - } - final SplitPairRule pairRule = (SplitPairRule) rule; - - // Not reuse if it needs to destroy the existing. - return !pairRule.shouldClearTop(); - } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java index b3becad3dc5a..89d7a407e459 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java @@ -33,12 +33,6 @@ import androidx.annotation.NonNull; * The base adapter can be used for {@link RemoteAnimationTarget} that is simple open/close. */ class TaskFragmentAnimationAdapter { - - /** - * If {@link #mOverrideLayer} is set to this value, we don't want to override the surface layer. - */ - private static final int LAYER_NO_OVERRIDE = -1; - final Animation mAnimation; final RemoteAnimationTarget mTarget; final SurfaceControl mLeash; @@ -48,7 +42,6 @@ class TaskFragmentAnimationAdapter { final float[] mVecs = new float[4]; final Rect mRect = new Rect(); private boolean mIsFirstFrame = true; - private int mOverrideLayer = LAYER_NO_OVERRIDE; TaskFragmentAnimationAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) { @@ -65,21 +58,10 @@ class TaskFragmentAnimationAdapter { mLeash = leash; } - /** - * Surface layer to be set at the first frame of the animation. We will not set the layer if it - * is set to {@link #LAYER_NO_OVERRIDE}. - */ - final void overrideLayer(int layer) { - mOverrideLayer = layer; - } - /** Called on frame update. */ final void onAnimationUpdate(@NonNull SurfaceControl.Transaction t, long currentPlayTime) { if (mIsFirstFrame) { t.show(mLeash); - if (mOverrideLayer != LAYER_NO_OVERRIDE) { - t.setLayer(mLeash, mOverrideLayer); - } mIsFirstFrame = false; } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java index 1ac33173668b..46bdf6d0e689 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java @@ -25,7 +25,6 @@ import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN; import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; -import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; import android.animation.Animator; import android.animation.ValueAnimator; @@ -182,22 +181,18 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { private List<TaskFragmentAnimationAdapter> createOpenAnimationAdapters( @NonNull RemoteAnimationTarget[] targets) { - return createOpenCloseAnimationAdapters(targets, true /* isOpening */, + return createOpenCloseAnimationAdapters(targets, mAnimationSpec::loadOpenAnimation); } private List<TaskFragmentAnimationAdapter> createCloseAnimationAdapters( @NonNull RemoteAnimationTarget[] targets) { - return createOpenCloseAnimationAdapters(targets, false /* isOpening */, + return createOpenCloseAnimationAdapters(targets, mAnimationSpec::loadCloseAnimation); } - /** - * Creates {@link TaskFragmentAnimationAdapter} for OPEN and CLOSE types of transition. - * @param isOpening {@code true} for OPEN type, {@code false} for CLOSE type. - */ private List<TaskFragmentAnimationAdapter> createOpenCloseAnimationAdapters( - @NonNull RemoteAnimationTarget[] targets, boolean isOpening, + @NonNull RemoteAnimationTarget[] targets, @NonNull BiFunction<RemoteAnimationTarget, Rect, Animation> animationProvider) { // We need to know if the target window is only a partial of the whole animation screen. // If so, we will need to adjust it to make the whole animation screen looks like one. @@ -215,25 +210,14 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { } } - // For OPEN transition, open windows should be above close windows. - // For CLOSE transition, open windows should be below close windows. - int offsetLayer = TYPE_LAYER_OFFSET; final List<TaskFragmentAnimationAdapter> adapters = new ArrayList<>(); for (RemoteAnimationTarget target : openingTargets) { - final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target, - animationProvider, openingWholeScreenBounds); - if (isOpening) { - adapter.overrideLayer(offsetLayer++); - } - adapters.add(adapter); + adapters.add(createOpenCloseAnimationAdapter(target, animationProvider, + openingWholeScreenBounds)); } for (RemoteAnimationTarget target : closingTargets) { - final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target, - animationProvider, closingWholeScreenBounds); - if (!isOpening) { - adapter.overrideLayer(offsetLayer++); - } - adapters.add(adapter); + adapters.add(createOpenCloseAnimationAdapter(target, animationProvider, + closingWholeScreenBounds)); } return adapters; } 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 ee8cb48e3c4c..fe9ce971d4d9 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -18,24 +18,22 @@ package androidx.window.extensions.layout; import static android.view.Display.DEFAULT_DISPLAY; -import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT; -import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED; +import static androidx.window.common.DisplayFeature.COMMON_STATE_FLAT; +import static androidx.window.common.DisplayFeature.COMMON_STATE_HALF_OPENED; import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation; 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.DeviceStateManagerPostureProducer; +import androidx.window.common.DisplayFeature; +import androidx.window.common.ResourceConfigDisplayFeatureProducer; +import androidx.window.common.SettingsDevicePostureProducer; import androidx.window.common.SettingsDisplayFeatureProducer; import androidx.window.util.DataProducer; import androidx.window.util.PriorityDataProducer; @@ -58,27 +56,36 @@ import java.util.function.Consumer; */ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private static final String TAG = "SampleExtension"; + private static WindowLayoutComponent sInstance; private final Map<Activity, Consumer<WindowLayoutInfo>> mWindowLayoutChangeListeners = new HashMap<>(); + private final SettingsDevicePostureProducer mSettingsDevicePostureProducer; + private final DataProducer<Integer> mDevicePostureProducer; + private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; - private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer; + private final DataProducer<List<DisplayFeature>> mDisplayFeatureProducer; public WindowLayoutComponentImpl(Context context) { - ((Application) context.getApplicationContext()) - .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); + mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); + mDevicePostureProducer = new PriorityDataProducer<>(List.of( + mSettingsDevicePostureProducer, + new DeviceStateManagerPostureProducer(context) + )); + mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context); - mFoldingFeatureProducer = new PriorityDataProducer<>(List.of( + mDisplayFeatureProducer = new PriorityDataProducer<>(List.of( mSettingsDisplayFeatureProducer, - new DeviceStateManagerFoldingFeatureProducer(context) + new ResourceConfigDisplayFeatureProducer(context) )); - mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); + + mDevicePostureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); + mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } /** * 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} */ @@ -90,7 +97,6 @@ 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( @@ -112,34 +118,43 @@ 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(); } /** + * 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}. + * + * @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. + */ + @Nullable + private Integer getFeatureState(DisplayFeature feature) { + Integer featureState = feature.getState(); + Optional<Integer> posture = mDevicePostureProducer.getData(); + Integer state = featureState == null ? posture.orElse(null) : featureState; + return convertToExtensionState(state); + } + + /** * A convenience method to translate from the common feature state to the extensions feature - * state. More specifically, translates from {@link CommonFoldingFeature.State} to + * state. More specifically, translates from {@link DisplayFeature.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 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. + * @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. */ @Nullable - private Integer convertToExtensionState(int state) { - if (state == COMMON_STATE_FLAT) { + private Integer convertToExtensionState(@Nullable Integer state) { + if (state == null) { // The null check avoids a NullPointerException. + return null; + } else if (state == COMMON_STATE_FLAT) { return FoldingFeature.STATE_FLAT; } else if (state == COMMON_STATE_HALF_OPENED) { return FoldingFeature.STATE_HALF_OPENED; @@ -157,30 +172,33 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { @NonNull private WindowLayoutInfo getWindowLayoutInfo(@NonNull Activity activity) { - List<DisplayFeature> displayFeatures = getDisplayFeatures(activity); + List<androidx.window.extensions.layout.DisplayFeature> displayFeatures = + getDisplayFeatures(activity); return new WindowLayoutInfo(displayFeatures); } /** - * 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. + * 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. * * For a {@link FoldingFeature} the bounds are localized into the {@link Activity} window - * coordinate space and the state is calculated from {@link CommonFoldingFeature#getState()}. - * The state from {@link #mFoldingFeatureProducer} may not be valid since - * {@link #mFoldingFeatureProducer} 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. + * 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. * * @param activity a proxy for the {@link android.view.Window} that contains the - * {@link DisplayFeature}. - * @return a {@link List} of valid {@link DisplayFeature} that + * {@link androidx.window.extensions.layout.DisplayFeature}. + * @return a {@link List} of valid {@link androidx.window.extensions.layout.DisplayFeature} that * are within the {@link android.view.Window} of the {@link Activity} */ - private List<DisplayFeature> getDisplayFeatures(@NonNull Activity activity) { - List<DisplayFeature> features = new ArrayList<>(); + private List<androidx.window.extensions.layout.DisplayFeature> getDisplayFeatures( + @NonNull Activity activity) { + List<androidx.window.extensions.layout.DisplayFeature> 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"); @@ -193,10 +211,11 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { return features; } - Optional<List<CommonFoldingFeature>> storedFeatures = mFoldingFeatureProducer.getData(); + Optional<List<DisplayFeature>> storedFeatures = mDisplayFeatureProducer.getData(); if (storedFeatures.isPresent()) { - for (CommonFoldingFeature baseFeature : storedFeatures.get()) { - Integer state = convertToExtensionState(baseFeature.getState()); + + for (DisplayFeature baseFeature : storedFeatures.get()) { + Integer state = getFeatureState(baseFeature); if (state == null) { continue; } @@ -204,7 +223,8 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { rotateRectToDisplayRotation(displayId, featureRect); transformToWindowSpaceRect(activity, featureRect); - features.add(new FoldingFeature(featureRect, baseFeature.getType(), state)); + features.add(new FoldingFeature(featureRect, baseFeature.getType(), + getFeatureState(baseFeature))); } } return features; @@ -212,31 +232,13 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private void updateRegistrations() { if (hasListeners()) { + mSettingsDevicePostureProducer.registerObserversIfNeeded(); mSettingsDisplayFeatureProducer.registerObserversIfNeeded(); } else { + mSettingsDevicePostureProducer.unregisterObserversIfNeeded(); 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(); - } - } + onDisplayFeaturesChanged(); } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java index c7b709347060..aa949f126154 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java @@ -23,17 +23,16 @@ 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.DeviceStateManagerPostureProducer; +import androidx.window.common.DisplayFeature; +import androidx.window.common.ResourceConfigDisplayFeatureProducer; +import androidx.window.common.SettingsDevicePostureProducer; import androidx.window.common.SettingsDisplayFeatureProducer; import androidx.window.util.DataProducer; import androidx.window.util.PriorityDataProducer; @@ -49,25 +48,36 @@ import java.util.Optional; */ class SampleSidecarImpl extends StubSidecar { private static final String TAG = "SampleSidecar"; + private static final boolean DEBUG = false; - private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer; + private final SettingsDevicePostureProducer mSettingsDevicePostureProducer; + private final DataProducer<Integer> mDevicePostureProducer; - private final SettingsDisplayFeatureProducer mSettingsFoldingFeatureProducer; + private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; + private final DataProducer<List<DisplayFeature>> mDisplayFeatureProducer; SampleSidecarImpl(Context context) { - ((Application) context.getApplicationContext()) - .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); - mSettingsFoldingFeatureProducer = new SettingsDisplayFeatureProducer(context); - mFoldingFeatureProducer = new PriorityDataProducer<>(List.of( - mSettingsFoldingFeatureProducer, - new DeviceStateManagerFoldingFeatureProducer(context) + mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); + mDevicePostureProducer = new PriorityDataProducer<>(List.of( + mSettingsDevicePostureProducer, + new DeviceStateManagerPostureProducer(context) )); - mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); + mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context); + mDisplayFeatureProducer = new PriorityDataProducer<>(List.of( + mSettingsDisplayFeatureProducer, + new ResourceConfigDisplayFeatureProducer(context) + )); + + mDevicePostureProducer.addDataChangedCallback(this::onDevicePostureChanged); + mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } - private void onDisplayFeaturesChanged() { + private void onDevicePostureChanged() { updateDeviceState(getDeviceState()); + } + + private void onDisplayFeaturesChanged() { for (IBinder windowToken : getWindowsListeningForLayoutChanges()) { SidecarWindowLayoutInfo newLayout = getWindowLayoutInfo(windowToken); updateWindowLayout(windowToken, newLayout); @@ -77,21 +87,27 @@ class SampleSidecarImpl extends StubSidecar { @NonNull @Override public SidecarDeviceState getDeviceState() { + Optional<Integer> posture = mDevicePostureProducer.getData(); + SidecarDeviceState deviceState = new SidecarDeviceState(); - deviceState.posture = deviceStateFromFeature(); + deviceState.posture = posture.orElse(deviceStateFromFeature()); return deviceState; } private int deviceStateFromFeature() { - List<CommonFoldingFeature> storedFeatures = mFoldingFeatureProducer.getData() + List<DisplayFeature> storedFeatures = mDisplayFeatureProducer.getData() .orElse(Collections.emptyList()); for (int i = 0; i < storedFeatures.size(); i++) { - CommonFoldingFeature feature = storedFeatures.get(i); - final int state = feature.getState(); + DisplayFeature 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 CommonFoldingFeature.COMMON_STATE_FLAT: + case DisplayFeature.COMMON_STATE_FLAT: return SidecarDeviceState.POSTURE_OPENED; - case CommonFoldingFeature.COMMON_STATE_HALF_OPENED: + case DisplayFeature.COMMON_STATE_HALF_OPENED: return SidecarDeviceState.POSTURE_HALF_OPENED; } } @@ -111,22 +127,22 @@ class SampleSidecarImpl extends StubSidecar { } private List<SidecarDisplayFeature> getDisplayFeatures(@NonNull Activity activity) { + List<SidecarDisplayFeature> features = new ArrayList<SidecarDisplayFeature>(); int displayId = activity.getDisplay().getDisplayId(); if (displayId != DEFAULT_DISPLAY) { Log.w(TAG, "This sample doesn't support display features on secondary displays"); - return Collections.emptyList(); + return features; } if (activity.isInMultiWindowMode()) { // It is recommended not to report any display features in multi-window mode, since it // won't be possible to synchronize the display feature positions with window movement. - return Collections.emptyList(); + return features; } - Optional<List<CommonFoldingFeature>> storedFeatures = mFoldingFeatureProducer.getData(); - List<SidecarDisplayFeature> features = new ArrayList<>(); + Optional<List<DisplayFeature>> storedFeatures = mDisplayFeatureProducer.getData(); if (storedFeatures.isPresent()) { - for (CommonFoldingFeature baseFeature : storedFeatures.get()) { + for (DisplayFeature baseFeature : storedFeatures.get()) { SidecarDisplayFeature feature = new SidecarDisplayFeature(); Rect featureRect = baseFeature.getRect(); rotateRectToDisplayRotation(displayId, featureRect); @@ -136,37 +152,17 @@ class SampleSidecarImpl extends StubSidecar { features.add(feature); } } - return Collections.unmodifiableList(features); + return features; } @Override protected void onListenersChanged() { if (hasListeners()) { - mSettingsFoldingFeatureProducer.registerObserversIfNeeded(); - onDisplayFeaturesChanged(); + mSettingsDevicePostureProducer.registerObserversIfNeeded(); + mSettingsDisplayFeatureProducer.registerObserversIfNeeded(); } 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(); - } + mSettingsDevicePostureProducer.unregisterObserversIfNeeded(); + mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded(); } } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java index b9c808a6569b..199c37315c07 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; - final Set<IBinder> mWindowLayoutChangeListenerTokens = new HashSet<>(); + private final Set<IBinder> mWindowLayoutChangeListenerTokens = new HashSet<>(); private boolean mDeviceStateChangeListenerRegistered; StubSidecar() { diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index f3bab494c076..6434e315503d 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -27,7 +27,7 @@ <string name="pip_play" msgid="3496151081459417097">"Reprodueix"</string> <string name="pip_pause" msgid="690688849510295232">"Posa en pausa"</string> <string name="pip_skip_to_next" msgid="8403429188794867653">"Ves al següent"</string> - <string name="pip_skip_to_prev" msgid="7172158111196394092">"Ves a l\'anterior"</string> + <string name="pip_skip_to_prev" msgid="7172158111196394092">"Torna a l\'anterior"</string> <string name="accessibility_action_pip_resize" msgid="4623966104749543182">"Canvia la mida"</string> <string name="accessibility_action_pip_stash" msgid="4060775037619702641">"Amaga"</string> <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Deixa d\'amagar"</string> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index c3cd04655178..8fef67b69747 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -36,16 +36,16 @@ <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ప్రత్యామ్నాయ డిస్ప్లేలో యాప్ పని చేయకపోవచ్చు."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ప్రత్యామ్నాయ డిస్ప్లేల్లో ప్రారంభానికి యాప్ మద్దతు లేదు."</string> <string name="accessibility_divider" msgid="703810061635792791">"విభజన స్క్రీన్ విభాగిని"</string> - <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ఎడమవైపు ఫుల్-స్క్రీన్"</string> + <string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"ఎడమవైపు పూర్తి స్క్రీన్"</string> <string name="accessibility_action_divider_left_70" msgid="8859845045360659250">"ఎడమవైపు 70%"</string> <string name="accessibility_action_divider_left_50" msgid="3488317024557521561">"ఎడమవైపు 50%"</string> <string name="accessibility_action_divider_left_30" msgid="6023611335723838727">"ఎడమవైపు 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"కుడివైపు ఫుల్-స్క్రీన్"</string> - <string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"ఎగువ ఫుల్-స్క్రీన్"</string> + <string name="accessibility_action_divider_right_full" msgid="3408505054325944903">"కుడివైపు పూర్తి స్క్రీన్"</string> + <string name="accessibility_action_divider_top_full" msgid="3495871951082107594">"ఎగువ పూర్తి స్క్రీన్"</string> <string name="accessibility_action_divider_top_70" msgid="1779164068887875474">"ఎగువ 70%"</string> <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ఎగువ 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ఎగువ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"దిగువ ఫుల్-స్క్రీన్"</string> + <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"దిగువ పూర్తి స్క్రీన్"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"వన్-హ్యాండెడ్ మోడ్ను ఉపయోగించడం"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"నిష్క్రమించడానికి, స్క్రీన్ కింది భాగం నుండి పైకి స్వైప్ చేయండి లేదా యాప్ పైన ఎక్కడైనా ట్యాప్ చేయండి"</string> <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"వన్-హ్యాండెడ్ మోడ్ను ప్రారంభిస్తుంది"</string> diff --git a/libs/WindowManager/Shell/res/values-te/strings_tv.xml b/libs/WindowManager/Shell/res/values-te/strings_tv.xml index b9e8d762eda9..47489efbc4c2 100644 --- a/libs/WindowManager/Shell/res/values-te/strings_tv.xml +++ b/libs/WindowManager/Shell/res/values-te/strings_tv.xml @@ -20,5 +20,5 @@ <string name="notification_channel_tv_pip" msgid="2576686079160402435">"పిక్చర్-ఇన్-పిక్చర్"</string> <string name="pip_notification_unknown_title" msgid="2729870284350772311">"(శీర్షిక లేని ప్రోగ్రామ్)"</string> <string name="pip_close" msgid="9135220303720555525">"PIPని మూసివేయి"</string> - <string name="pip_fullscreen" msgid="7278047353591302554">"ఫుల్-స్క్రీన్"</string> + <string name="pip_fullscreen" msgid="7278047353591302554">"పూర్తి స్క్రీన్"</string> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java index f98849260511..fd3be2b11c15 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java @@ -103,7 +103,7 @@ public class DragLayout extends LinearLayout { MATCH_PARENT)); ((LayoutParams) mDropZoneView1.getLayoutParams()).weight = 1; ((LayoutParams) mDropZoneView2.getLayoutParams()).weight = 1; - updateContainerMargins(getResources().getConfiguration().orientation); + updateContainerMargins(); } @Override @@ -128,18 +128,20 @@ public class DragLayout extends LinearLayout { } public void onConfigChanged(Configuration newConfig) { - if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE + final int orientation = getResources().getConfiguration().orientation; + if (orientation == Configuration.ORIENTATION_LANDSCAPE && getOrientation() != HORIZONTAL) { setOrientation(LinearLayout.HORIZONTAL); - updateContainerMargins(newConfig.orientation); - } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT + updateContainerMargins(); + } else if (orientation == Configuration.ORIENTATION_PORTRAIT && getOrientation() != VERTICAL) { setOrientation(LinearLayout.VERTICAL); - updateContainerMargins(newConfig.orientation); + updateContainerMargins(); } } - private void updateContainerMargins(int orientation) { + private void updateContainerMargins() { + final int orientation = getResources().getConfiguration().orientation; final float halfMargin = mDisplayMargin / 2f; if (orientation == Configuration.ORIENTATION_LANDSCAPE) { mDropZoneView1.setContainerMargin( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 4c77f6a7e00d..8b87df44c52c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -134,9 +134,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, private final Provider<Optional<StageTaskUnfoldController>> mUnfoldControllerProvider; private StageCoordinator mStageCoordinator; - // Only used for the legacy recents animation from splitscreen to allow the tasks to be animated - // outside the bounds of the roots by being reparented into a higher level fullscreen container - private SurfaceControl mSplitTasksContainerLayer; public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, Context context, @@ -367,24 +364,20 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, RemoteAnimationTarget[] apps) { if (apps.length < 2) return null; - SurfaceControl.Transaction transaction = new SurfaceControl.Transaction(); - if (mSplitTasksContainerLayer != null) { - // Remove the previous layer before recreating - transaction.remove(mSplitTasksContainerLayer); - } final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession()) .setContainerLayer() .setName("RecentsAnimationSplitTasks") .setHidden(false) .setCallsite("SplitScreenController#onGoingtoRecentsLegacy"); mRootTDAOrganizer.attachToDisplayArea(DEFAULT_DISPLAY, builder); - mSplitTasksContainerLayer = builder.build(); + SurfaceControl sc = builder.build(); + SurfaceControl.Transaction transaction = new SurfaceControl.Transaction(); // Ensure that we order these in the parent in the right z-order as their previous order Arrays.sort(apps, (a1, a2) -> a1.prefixOrderIndex - a2.prefixOrderIndex); int layer = 1; for (RemoteAnimationTarget appTarget : apps) { - transaction.reparent(appTarget.leash, mSplitTasksContainerLayer); + transaction.reparent(appTarget.leash, sc); transaction.setPosition(appTarget.leash, appTarget.screenSpaceBounds.left, appTarget.screenSpaceBounds.top); transaction.setLayer(appTarget.leash, layer++); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 38c1aff0a62c..5d1d159e63e6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -365,10 +365,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { - // Ensure divider is invisible before transition. - setDividerVisibility(false /* visible */); // Init divider first to make divider leash for remote animation target. - mSplitLayout.init(); + setDividerVisibility(true /* visible */); // Set false to avoid record new bounds with old task still on top; mShouldUpdateRecents = false; final WindowContainerTransaction wct = new WindowContainerTransaction(); @@ -398,7 +396,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, public void onAnimationFinished() throws RemoteException { mIsDividerRemoteAnimating = false; mShouldUpdateRecents = true; - setDividerVisibility(true /* visible */); mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> applyDividerVisibility(t)); finishedCallback.onAnimationFinished(); @@ -423,7 +420,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, public void onAnimationCancelled() { mIsDividerRemoteAnimating = false; mShouldUpdateRecents = true; - setDividerVisibility(true /* visible */); mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> applyDividerVisibility(t)); try { diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index 99fd463b0660..0e4a1f945b85 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -74,15 +74,7 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con if (backBuffer.get() == nullptr) { return false; } - - // update the coordinates of the global light position based on surface rotation - SkPoint lightCenter = mVkSurface->getCurrentPreTransform().mapXY(lightGeometry.center.x, - lightGeometry.center.y); - LightGeometry localGeometry = lightGeometry; - localGeometry.center.x = lightCenter.fX; - localGeometry.center.y = lightCenter.fY; - - LightingInfo::updateLighting(localGeometry, lightInfo); + LightingInfo::updateLighting(lightGeometry, lightInfo); renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer, mVkSurface->getCurrentPreTransform()); |