Snap for 9444344 from c3f30502f8 to tm-qpr2-release
Change-Id: Id55b5226f75c4fb6ed28fe803a8e70f6396a8bd6
This commit is contained in:
@@ -16,11 +16,14 @@
|
||||
|
||||
package com.android.internal.app;
|
||||
|
||||
import static android.util.PollingCheck.waitFor;
|
||||
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.action.ViewActions.swipeUp;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isSelected;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
|
||||
@@ -49,6 +52,8 @@ import com.android.internal.R;
|
||||
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
|
||||
import com.android.internal.app.ChooserActivityWorkProfileTest.TestCase.Tab;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -331,8 +336,17 @@ public class ChooserActivityWorkProfileTest {
|
||||
final int stringId = tab == Tab.WORK ? R.string.resolver_work_tab
|
||||
: R.string.resolver_personal_tab;
|
||||
|
||||
onView(withText(stringId)).perform(click());
|
||||
waitForIdle();
|
||||
waitFor(() -> {
|
||||
onView(withText(stringId)).perform(click());
|
||||
waitForIdle();
|
||||
|
||||
try {
|
||||
onView(withText(stringId)).check(matches(isSelected()));
|
||||
return true;
|
||||
} catch (AssertionFailedError e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
onView(withId(R.id.contentPanel))
|
||||
.perform(swipeUp());
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
package com.android.internal.app;
|
||||
|
||||
import static android.util.PollingCheck.waitFor;
|
||||
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.action.ViewActions.swipeUp;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isSelected;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
|
||||
@@ -48,6 +51,8 @@ import com.android.internal.R;
|
||||
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
|
||||
import com.android.internal.app.ResolverActivityWorkProfileTest.TestCase.Tab;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -309,8 +314,17 @@ public class ResolverActivityWorkProfileTest {
|
||||
final int stringId = tab == Tab.WORK ? R.string.resolver_work_tab
|
||||
: R.string.resolver_personal_tab;
|
||||
|
||||
onView(withText(stringId)).perform(click());
|
||||
waitForIdle();
|
||||
waitFor(() -> {
|
||||
onView(withText(stringId)).perform(click());
|
||||
waitForIdle();
|
||||
|
||||
try {
|
||||
onView(withText(stringId)).check(matches(isSelected()));
|
||||
return true;
|
||||
} catch (AssertionFailedError e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
onView(withId(R.id.contentPanel))
|
||||
.perform(swipeUp());
|
||||
|
||||
@@ -63,6 +63,12 @@ android_library_import {
|
||||
sdk_version: "current",
|
||||
}
|
||||
|
||||
android_library_import {
|
||||
name: "window-extensions-core",
|
||||
aars: ["window-extensions-core-release.aar"],
|
||||
sdk_version: "current",
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "androidx.window.extensions",
|
||||
srcs: [
|
||||
@@ -70,7 +76,10 @@ java_library {
|
||||
"src/androidx/window/util/**/*.java",
|
||||
"src/androidx/window/common/**/*.java",
|
||||
],
|
||||
static_libs: ["window-extensions"],
|
||||
static_libs: [
|
||||
"window-extensions",
|
||||
"window-extensions-core",
|
||||
],
|
||||
installable: true,
|
||||
sdk_version: "core_platform",
|
||||
system_ext_specific: true,
|
||||
|
||||
@@ -75,7 +75,10 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.window.common.CommonFoldingFeature;
|
||||
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
|
||||
import androidx.window.extensions.WindowExtensionsImpl;
|
||||
import androidx.window.extensions.WindowExtensionsProvider;
|
||||
import androidx.window.extensions.core.util.function.Consumer;
|
||||
import androidx.window.extensions.core.util.function.Function;
|
||||
import androidx.window.extensions.embedding.TransactionManager.TransactionRecord;
|
||||
import androidx.window.extensions.layout.WindowLayoutComponentImpl;
|
||||
|
||||
@@ -86,7 +89,6 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Main controller class that manages split states and presentation.
|
||||
@@ -112,7 +114,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
/**
|
||||
* A developer-defined {@link SplitAttributes} calculator to compute the current
|
||||
* {@link SplitAttributes} with the current device and window states.
|
||||
* It is registered via {@link #setSplitAttributesCalculator(SplitAttributesCalculator)}
|
||||
* It is registered via {@link #setSplitAttributesCalculator(Function)}
|
||||
* and unregistered via {@link #clearSplitAttributesCalculator()}.
|
||||
* This is called when:
|
||||
* <ul>
|
||||
@@ -125,7 +127,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
private SplitAttributesCalculator mSplitAttributesCalculator;
|
||||
private Function<SplitAttributesCalculatorParams, SplitAttributes> mSplitAttributesCalculator;
|
||||
|
||||
/**
|
||||
* Map from Task id to {@link TaskContainer} which contains all TaskFragment and split pair info
|
||||
@@ -138,6 +140,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
final SparseArray<TaskContainer> mTaskContainers = new SparseArray<>();
|
||||
|
||||
/** Callback to Jetpack to notify about changes to split states. */
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
private Consumer<List<SplitInfo>> mEmbeddingCallback;
|
||||
private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
|
||||
@@ -171,7 +174,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
mWindowLayoutComponent.addFoldingStateChangedCallback(new FoldingFeatureListener());
|
||||
}
|
||||
|
||||
private class FoldingFeatureListener implements Consumer<List<CommonFoldingFeature>> {
|
||||
private class FoldingFeatureListener
|
||||
implements java.util.function.Consumer<List<CommonFoldingFeature>> {
|
||||
@Override
|
||||
public void accept(List<CommonFoldingFeature> foldingFeatures) {
|
||||
synchronized (mLock) {
|
||||
@@ -212,7 +216,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSplitAttributesCalculator(@NonNull SplitAttributesCalculator calculator) {
|
||||
public void setSplitAttributesCalculator(
|
||||
@NonNull Function<SplitAttributesCalculatorParams, SplitAttributes> calculator) {
|
||||
synchronized (mLock) {
|
||||
mSplitAttributesCalculator = calculator;
|
||||
}
|
||||
@@ -227,7 +232,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
SplitAttributesCalculator getSplitAttributesCalculator() {
|
||||
Function<SplitAttributesCalculatorParams, SplitAttributes> getSplitAttributesCalculator() {
|
||||
return mSplitAttributesCalculator;
|
||||
}
|
||||
|
||||
@@ -240,9 +245,22 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
|
||||
/**
|
||||
* Registers the split organizer callback to notify about changes to active splits.
|
||||
* @deprecated Use {@link #setSplitInfoCallback(Consumer)} starting with
|
||||
* {@link WindowExtensionsImpl#getVendorApiLevel()} 2.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setSplitInfoCallback(@NonNull Consumer<List<SplitInfo>> callback) {
|
||||
public void setSplitInfoCallback(
|
||||
@NonNull java.util.function.Consumer<List<SplitInfo>> callback) {
|
||||
Consumer<List<SplitInfo>> oemConsumer = callback::accept;
|
||||
setSplitInfoCallback(oemConsumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the split organizer callback to notify about changes to active splits.
|
||||
* @since {@link WindowExtensionsImpl#getVendorApiLevel()} 2
|
||||
*/
|
||||
public void setSplitInfoCallback(Consumer<List<SplitInfo>> callback) {
|
||||
synchronized (mLock) {
|
||||
mEmbeddingCallback = callback;
|
||||
updateCallbackIfNecessary();
|
||||
|
||||
@@ -42,11 +42,11 @@ import android.window.WindowContainerTransaction;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.window.extensions.core.util.function.Function;
|
||||
import androidx.window.extensions.embedding.SplitAttributes.SplitType;
|
||||
import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
|
||||
import androidx.window.extensions.embedding.SplitAttributes.SplitType.HingeSplitType;
|
||||
import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
|
||||
import androidx.window.extensions.embedding.SplitAttributesCalculator.SplitAttributesCalculatorParams;
|
||||
import androidx.window.extensions.embedding.TaskContainer.TaskProperties;
|
||||
import androidx.window.extensions.layout.DisplayFeature;
|
||||
import androidx.window.extensions.layout.FoldingFeature;
|
||||
@@ -522,7 +522,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
@NonNull SplitRule rule, @Nullable Pair<Size, Size> minDimensionsPair) {
|
||||
final Configuration taskConfiguration = taskProperties.getConfiguration();
|
||||
final WindowMetrics taskWindowMetrics = getTaskWindowMetrics(taskConfiguration);
|
||||
final SplitAttributesCalculator calculator = mController.getSplitAttributesCalculator();
|
||||
final Function<SplitAttributesCalculatorParams, SplitAttributes> calculator =
|
||||
mController.getSplitAttributesCalculator();
|
||||
final SplitAttributes defaultSplitAttributes = rule.getDefaultSplitAttributes();
|
||||
final boolean isDefaultMinSizeSatisfied = rule.checkParentMetrics(taskWindowMetrics);
|
||||
if (calculator == null) {
|
||||
@@ -538,7 +539,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
final SplitAttributesCalculatorParams params = new SplitAttributesCalculatorParams(
|
||||
taskWindowMetrics, taskConfiguration, defaultSplitAttributes,
|
||||
isDefaultMinSizeSatisfied, windowLayoutInfo, rule.getTag());
|
||||
final SplitAttributes splitAttributes = calculator.computeSplitAttributesForParams(params);
|
||||
final SplitAttributes splitAttributes = calculator.apply(params);
|
||||
return sanitizeSplitAttributes(taskProperties, splitAttributes, minDimensionsPair);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ import androidx.window.common.CommonFoldingFeature;
|
||||
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
|
||||
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
|
||||
import androidx.window.common.RawFoldingFeatureProducer;
|
||||
import androidx.window.extensions.core.util.function.Consumer;
|
||||
import androidx.window.util.DataProducer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -51,7 +52,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Reference implementation of androidx.window.extensions.layout OEM interface for use with
|
||||
@@ -80,6 +80,10 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
|
||||
private final Map<IBinder, ConfigurationChangeListener> mConfigurationChangeListeners =
|
||||
new ArrayMap<>();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private final Map<java.util.function.Consumer<WindowLayoutInfo>, Consumer<WindowLayoutInfo>>
|
||||
mJavaToExtConsumers = new ArrayMap<>();
|
||||
|
||||
public WindowLayoutComponentImpl(@NonNull Context context) {
|
||||
((Application) context.getApplicationContext())
|
||||
.registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
|
||||
@@ -90,7 +94,8 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
|
||||
}
|
||||
|
||||
/** Registers to listen to {@link CommonFoldingFeature} changes */
|
||||
public void addFoldingStateChangedCallback(Consumer<List<CommonFoldingFeature>> consumer) {
|
||||
public void addFoldingStateChangedCallback(
|
||||
java.util.function.Consumer<List<CommonFoldingFeature>> consumer) {
|
||||
synchronized (mLock) {
|
||||
mFoldingFeatureProducer.addDataChangedCallback(consumer);
|
||||
}
|
||||
@@ -104,13 +109,17 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
|
||||
*/
|
||||
@Override
|
||||
public void addWindowLayoutInfoListener(@NonNull Activity activity,
|
||||
@NonNull Consumer<WindowLayoutInfo> consumer) {
|
||||
addWindowLayoutInfoListener((Context) activity, consumer);
|
||||
@NonNull java.util.function.Consumer<WindowLayoutInfo> consumer) {
|
||||
final Consumer<WindowLayoutInfo> extConsumer = consumer::accept;
|
||||
synchronized (mLock) {
|
||||
mJavaToExtConsumers.put(consumer, extConsumer);
|
||||
}
|
||||
addWindowLayoutInfoListener(activity, extConsumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #addWindowLayoutInfoListener(Activity, Consumer)}, but takes a UI Context
|
||||
* as a parameter.
|
||||
* Similar to {@link #addWindowLayoutInfoListener(Activity, java.util.function.Consumer)}, but
|
||||
* takes a UI Context as a parameter.
|
||||
*
|
||||
* Jetpack {@link androidx.window.layout.ExtensionWindowLayoutInfoBackend} makes sure all
|
||||
* consumers related to the same {@link Context} gets updated {@link WindowLayoutInfo}
|
||||
@@ -151,6 +160,18 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeWindowLayoutInfoListener(
|
||||
@NonNull java.util.function.Consumer<WindowLayoutInfo> consumer) {
|
||||
final Consumer<WindowLayoutInfo> extConsumer;
|
||||
synchronized (mLock) {
|
||||
extConsumer = mJavaToExtConsumers.remove(consumer);
|
||||
}
|
||||
if (extConsumer != null) {
|
||||
removeWindowLayoutInfoListener(extConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener no longer interested in receiving updates.
|
||||
*
|
||||
|
||||
@@ -34,9 +34,11 @@ import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Pair;
|
||||
import android.view.WindowMetrics;
|
||||
import android.window.TaskFragmentInfo;
|
||||
import android.window.WindowContainerToken;
|
||||
|
||||
import androidx.window.extensions.core.util.function.Predicate;
|
||||
import androidx.window.extensions.embedding.SplitAttributes.SplitType;
|
||||
import androidx.window.extensions.layout.DisplayFeature;
|
||||
import androidx.window.extensions.layout.FoldingFeature;
|
||||
@@ -107,7 +109,7 @@ public class EmbeddingTestUtils {
|
||||
static SplitRule createSplitRule(@NonNull Activity primaryActivity,
|
||||
@NonNull Intent secondaryIntent, boolean clearTop) {
|
||||
final Pair<Activity, Intent> targetPair = new Pair<>(primaryActivity, secondaryIntent);
|
||||
return new SplitPairRule.Builder(
|
||||
return createSplitPairRuleBuilder(
|
||||
activityPair -> false,
|
||||
targetPair::equals,
|
||||
w -> true)
|
||||
@@ -144,7 +146,7 @@ public class EmbeddingTestUtils {
|
||||
@NonNull Activity secondaryActivity, int finishPrimaryWithSecondary,
|
||||
int finishSecondaryWithPrimary, boolean clearTop) {
|
||||
final Pair<Activity, Activity> targetPair = new Pair<>(primaryActivity, secondaryActivity);
|
||||
return new SplitPairRule.Builder(
|
||||
return createSplitPairRuleBuilder(
|
||||
targetPair::equals,
|
||||
activityIntentPair -> false,
|
||||
w -> true)
|
||||
@@ -223,4 +225,26 @@ public class EmbeddingTestUtils {
|
||||
displayFeatures.add(foldingFeature);
|
||||
return new WindowLayoutInfo(displayFeatures);
|
||||
}
|
||||
|
||||
static ActivityRule.Builder createActivityBuilder(
|
||||
@NonNull Predicate<Activity> activityPredicate,
|
||||
@NonNull Predicate<Intent> intentPredicate) {
|
||||
return new ActivityRule.Builder(activityPredicate, intentPredicate);
|
||||
}
|
||||
|
||||
static SplitPairRule.Builder createSplitPairRuleBuilder(
|
||||
@NonNull Predicate<Pair<Activity, Activity>> activitiesPairPredicate,
|
||||
@NonNull Predicate<Pair<Activity, Intent>> activityIntentPairPredicate,
|
||||
@NonNull Predicate<WindowMetrics> windowMetricsPredicate) {
|
||||
return new SplitPairRule.Builder(activitiesPairPredicate, activityIntentPairPredicate,
|
||||
windowMetricsPredicate);
|
||||
}
|
||||
|
||||
static SplitPlaceholderRule.Builder createSplitPlaceholderRuleBuilder(
|
||||
@NonNull Intent placeholderIntent, @NonNull Predicate<Activity> activityPredicate,
|
||||
@NonNull Predicate<Intent> intentPredicate,
|
||||
@NonNull Predicate<WindowMetrics> windowMetricsPredicate) {
|
||||
return new SplitPlaceholderRule.Builder(placeholderIntent, activityPredicate,
|
||||
intentPredicate, windowMetricsPredicate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,11 @@ import static androidx.window.extensions.embedding.EmbeddingTestUtils.SPLIT_ATTR
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TEST_TAG;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityBuilder;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityInfoWithMinDimensions;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPairRuleBuilder;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPlaceholderRuleBuilder;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTestTaskContainer;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.getSplitBounds;
|
||||
@@ -429,7 +432,7 @@ public class SplitControllerTest {
|
||||
@Test
|
||||
public void testResolveStartActivityIntent_withoutLaunchingActivity() {
|
||||
final Intent intent = new Intent();
|
||||
final ActivityRule expandRule = new ActivityRule.Builder(r -> false, i -> i == intent)
|
||||
final ActivityRule expandRule = createActivityBuilder(r -> false, i -> i == intent)
|
||||
.setShouldAlwaysExpand(true)
|
||||
.build();
|
||||
mSplitController.setEmbeddingRules(Collections.singleton(expandRule));
|
||||
@@ -1167,7 +1170,7 @@ public class SplitControllerTest {
|
||||
|
||||
@Test
|
||||
public void testHasSamePresentation() {
|
||||
SplitPairRule splitRule1 = new SplitPairRule.Builder(
|
||||
SplitPairRule splitRule1 = createSplitPairRuleBuilder(
|
||||
activityPair -> true,
|
||||
activityIntentPair -> true,
|
||||
windowMetrics -> true)
|
||||
@@ -1175,7 +1178,7 @@ public class SplitControllerTest {
|
||||
.setFinishPrimaryWithSecondary(DEFAULT_FINISH_PRIMARY_WITH_SECONDARY)
|
||||
.setDefaultSplitAttributes(SPLIT_ATTRIBUTES)
|
||||
.build();
|
||||
SplitPairRule splitRule2 = new SplitPairRule.Builder(
|
||||
SplitPairRule splitRule2 = createSplitPairRuleBuilder(
|
||||
activityPair -> true,
|
||||
activityIntentPair -> true,
|
||||
windowMetrics -> true)
|
||||
@@ -1188,7 +1191,7 @@ public class SplitControllerTest {
|
||||
SplitController.haveSamePresentation(splitRule1, splitRule2,
|
||||
new WindowMetrics(TASK_BOUNDS, WindowInsets.CONSUMED)));
|
||||
|
||||
splitRule2 = new SplitPairRule.Builder(
|
||||
splitRule2 = createSplitPairRuleBuilder(
|
||||
activityPair -> true,
|
||||
activityIntentPair -> true,
|
||||
windowMetrics -> true)
|
||||
@@ -1352,7 +1355,7 @@ public class SplitControllerTest {
|
||||
|
||||
/** Setups a rule to always expand the given intent. */
|
||||
private void setupExpandRule(@NonNull Intent expandIntent) {
|
||||
final ActivityRule expandRule = new ActivityRule.Builder(r -> false, expandIntent::equals)
|
||||
final ActivityRule expandRule = createActivityBuilder(r -> false, expandIntent::equals)
|
||||
.setShouldAlwaysExpand(true)
|
||||
.build();
|
||||
mSplitController.setEmbeddingRules(Collections.singleton(expandRule));
|
||||
@@ -1360,7 +1363,7 @@ public class SplitControllerTest {
|
||||
|
||||
/** Setups a rule to always expand the given activity. */
|
||||
private void setupExpandRule(@NonNull Activity expandActivity) {
|
||||
final ActivityRule expandRule = new ActivityRule.Builder(expandActivity::equals, i -> false)
|
||||
final ActivityRule expandRule = createActivityBuilder(expandActivity::equals, i -> false)
|
||||
.setShouldAlwaysExpand(true)
|
||||
.build();
|
||||
mSplitController.setEmbeddingRules(Collections.singleton(expandRule));
|
||||
@@ -1368,7 +1371,7 @@ public class SplitControllerTest {
|
||||
|
||||
/** Setups a rule to launch placeholder for the given activity. */
|
||||
private void setupPlaceholderRule(@NonNull Activity primaryActivity) {
|
||||
final SplitRule placeholderRule = new SplitPlaceholderRule.Builder(PLACEHOLDER_INTENT,
|
||||
final SplitRule placeholderRule = createSplitPlaceholderRuleBuilder(PLACEHOLDER_INTENT,
|
||||
primaryActivity::equals, i -> false, w -> true)
|
||||
.setDefaultSplitAttributes(SPLIT_ATTRIBUTES)
|
||||
.build();
|
||||
|
||||
@@ -27,6 +27,7 @@ import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUND
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityInfoWithMinDimensions;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPairRuleBuilder;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createWindowLayoutInfo;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.getSplitBounds;
|
||||
@@ -473,7 +474,7 @@ public class SplitPresenterTest {
|
||||
final Activity secondaryActivity = createMockActivity();
|
||||
final TaskFragmentContainer bottomTf = mController.newContainer(secondaryActivity, TASK_ID);
|
||||
final TaskFragmentContainer primaryTf = mController.newContainer(mActivity, TASK_ID);
|
||||
final SplitPairRule rule = new SplitPairRule.Builder(pair ->
|
||||
final SplitPairRule rule = createSplitPairRuleBuilder(pair ->
|
||||
pair.first == mActivity && pair.second == secondaryActivity, pair -> false,
|
||||
metrics -> true)
|
||||
.setDefaultSplitAttributes(SPLIT_ATTRIBUTES)
|
||||
@@ -491,7 +492,7 @@ public class SplitPresenterTest {
|
||||
|
||||
@Test
|
||||
public void testComputeSplitAttributes() {
|
||||
final SplitPairRule splitPairRule = new SplitPairRule.Builder(
|
||||
final SplitPairRule splitPairRule = createSplitPairRuleBuilder(
|
||||
activityPair -> true,
|
||||
activityIntentPair -> true,
|
||||
windowMetrics -> windowMetrics.getBounds().equals(TASK_BOUNDS))
|
||||
|
||||
BIN
libs/WindowManager/Jetpack/window-extensions-core-release.aar
Normal file
BIN
libs/WindowManager/Jetpack/window-extensions-core-release.aar
Normal file
Binary file not shown.
Binary file not shown.
@@ -20,6 +20,7 @@ import com.android.keyguard.KeyguardUnfoldTransition
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.shade.NotificationPanelUnfoldAnimationController
|
||||
import com.android.systemui.statusbar.phone.StatusBarMoveFromCenterAnimationController
|
||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
|
||||
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
|
||||
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
|
||||
import com.android.systemui.util.kotlin.getOrNull
|
||||
@@ -95,4 +96,6 @@ interface SysUIUnfoldComponent {
|
||||
fun getUnfoldHapticsPlayer(): UnfoldHapticsPlayer
|
||||
|
||||
fun getUnfoldLightRevealOverlayAnimation(): UnfoldLightRevealOverlayAnimation
|
||||
|
||||
fun getUnfoldKeyguardVisibilityManager(): UnfoldKeyguardVisibilityManager
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.android.systemui.unfold
|
||||
|
||||
import android.util.Log
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
|
||||
import com.android.systemui.util.kotlin.getOrNull
|
||||
import java.util.Optional
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Used to set the keyguard visibility state to [UnfoldKeyguardVisibilityManager].
|
||||
*
|
||||
* It is not possible to directly inject a sysui class (e.g. [KeyguardStateController]) into
|
||||
* [DeviceStateProvider], as it can't depend on google sysui directly. So,
|
||||
* [UnfoldKeyguardVisibilityManager] is provided to clients, that can set the keyguard visibility
|
||||
* accordingly.
|
||||
*/
|
||||
@SysUISingleton
|
||||
class UnfoldKeyguardVisibilityListener
|
||||
@Inject
|
||||
constructor(
|
||||
keyguardStateController: KeyguardStateController,
|
||||
unfoldComponent: Optional<SysUIUnfoldComponent>,
|
||||
) {
|
||||
|
||||
private val unfoldKeyguardVisibilityManager =
|
||||
unfoldComponent.getOrNull()?.getUnfoldKeyguardVisibilityManager()
|
||||
|
||||
private val delegate = { keyguardStateController.isVisible }
|
||||
|
||||
fun init() {
|
||||
unfoldKeyguardVisibilityManager?.setKeyguardVisibleDelegate(delegate).also {
|
||||
Log.d(TAG, "setKeyguardVisibleDelegate set")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val TAG = "UnfoldKeyguardVisibilityListener"
|
||||
@@ -29,6 +29,7 @@ import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListen
|
||||
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
|
||||
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
|
||||
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
|
||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.capture
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
@@ -56,6 +57,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var rotationChangeProvider: RotationChangeProvider
|
||||
|
||||
@Mock
|
||||
private lateinit var unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider
|
||||
|
||||
@Captor
|
||||
private lateinit var rotationListener: ArgumentCaptor<RotationListener>
|
||||
|
||||
@@ -87,6 +91,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||
screenOnStatusProvider,
|
||||
foldProvider,
|
||||
activityTypeProvider,
|
||||
unfoldKeyguardVisibilityProvider,
|
||||
rotationChangeProvider,
|
||||
context.mainExecutor,
|
||||
handler
|
||||
@@ -379,6 +384,47 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun startClosingEvent_whileNotOnKeyguardAndNotOnLauncher_doesNotTriggerBeforeThreshold() {
|
||||
setKeyguardVisibility(visible = false)
|
||||
setupForegroundActivityType(isHomeActivity = false)
|
||||
sendHingeAngleEvent(180)
|
||||
|
||||
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
|
||||
|
||||
assertThat(foldUpdates).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun startClosingEvent_whileKeyguardStateNotAvailable_triggerBeforeThreshold() {
|
||||
setKeyguardVisibility(visible = null)
|
||||
sendHingeAngleEvent(180)
|
||||
|
||||
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
|
||||
|
||||
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun startClosingEvent_whileonKeyguard_doesTriggerBeforeThreshold() {
|
||||
setKeyguardVisibility(visible = true)
|
||||
sendHingeAngleEvent(180)
|
||||
|
||||
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
|
||||
|
||||
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun startClosingEvent_whileNotOnKeyguard_triggersAfterThreshold() {
|
||||
setKeyguardVisibility(visible = false)
|
||||
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
|
||||
|
||||
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
|
||||
|
||||
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun screenOff_whileFolded_hingeAngleProviderRemainsOff() {
|
||||
setFoldState(folded = true)
|
||||
@@ -445,6 +491,10 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
|
||||
whenever(activityTypeProvider.isHomeActivity).thenReturn(isHomeActivity)
|
||||
}
|
||||
|
||||
private fun setKeyguardVisibility(visible: Boolean?) {
|
||||
whenever(unfoldKeyguardVisibilityProvider.isKeyguardVisible).thenReturn(visible)
|
||||
}
|
||||
|
||||
private fun simulateTimeout(waitTime: Long = HALF_OPENED_TIMEOUT_MILLIS) {
|
||||
val runnableDelay = scheduledRunnableDelay ?: throw Exception("No runnable scheduled.")
|
||||
if (waitTime >= runnableDelay) {
|
||||
|
||||
@@ -28,6 +28,9 @@ import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
|
||||
import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider
|
||||
import com.android.systemui.unfold.util.ATraceLoggerTransitionProgressListener
|
||||
import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider
|
||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
|
||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManagerImpl
|
||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import java.util.Optional
|
||||
@@ -57,7 +60,8 @@ class UnfoldSharedModule {
|
||||
scaleAwareProviderFactory.wrap(baseProgressProvider).apply {
|
||||
// Always present callback that logs animation beginning and end.
|
||||
addCallback(tracingListener)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -77,4 +81,16 @@ class UnfoldSharedModule {
|
||||
} else {
|
||||
EmptyHingeAngleProvider
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun unfoldKeyguardVisibilityProvider(
|
||||
impl: UnfoldKeyguardVisibilityManagerImpl
|
||||
): UnfoldKeyguardVisibilityProvider = impl
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun unfoldKeyguardVisibilityManager(
|
||||
impl: UnfoldKeyguardVisibilityManagerImpl
|
||||
): UnfoldKeyguardVisibilityManager = impl
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
|
||||
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
|
||||
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
|
||||
import com.android.systemui.unfold.util.CurrentActivityTypeProvider
|
||||
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
|
||||
import java.util.concurrent.Executor
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -42,6 +43,7 @@ constructor(
|
||||
private val screenStatusProvider: ScreenStatusProvider,
|
||||
private val foldProvider: FoldProvider,
|
||||
private val activityTypeProvider: CurrentActivityTypeProvider,
|
||||
private val unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider,
|
||||
private val rotationChangeProvider: RotationChangeProvider,
|
||||
@UnfoldMain private val mainExecutor: Executor,
|
||||
@UnfoldMain private val handler: Handler
|
||||
@@ -152,12 +154,13 @@ constructor(
|
||||
*/
|
||||
private fun getClosingThreshold(): Int? {
|
||||
val isHomeActivity = activityTypeProvider.isHomeActivity ?: return null
|
||||
val isKeyguardVisible = unfoldKeyguardVisibilityProvider.isKeyguardVisible == true
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "isHomeActivity=$isHomeActivity")
|
||||
Log.d(TAG, "isHomeActivity=$isHomeActivity, isOnKeyguard=$isKeyguardVisible")
|
||||
}
|
||||
|
||||
return if (isHomeActivity) {
|
||||
return if (isHomeActivity || isKeyguardVisible) {
|
||||
null
|
||||
} else {
|
||||
START_CLOSING_ON_APPS_THRESHOLD_DEGREES
|
||||
@@ -257,7 +260,7 @@ fun @receiver:FoldUpdate Int.name() =
|
||||
}
|
||||
|
||||
private const val TAG = "DeviceFoldProvider"
|
||||
private const val DEBUG = false
|
||||
private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
|
||||
|
||||
/** Threshold after which we consider the device fully unfolded. */
|
||||
@VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 com.android.systemui.unfold.util
|
||||
|
||||
import java.lang.ref.WeakReference
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
interface UnfoldKeyguardVisibilityProvider {
|
||||
/**
|
||||
* True when the keyguard is visible.
|
||||
*
|
||||
* Might be [null] when it is not known.
|
||||
*/
|
||||
val isKeyguardVisible: Boolean?
|
||||
}
|
||||
|
||||
/** Used to notify keyguard visibility. */
|
||||
interface UnfoldKeyguardVisibilityManager {
|
||||
/** Sets the delegate. [delegate] should return true when the keyguard is visible. */
|
||||
fun setKeyguardVisibleDelegate(delegate: () -> Boolean)
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps a [WeakReference] for the keyguard visibility provider.
|
||||
*
|
||||
* It is a weak reference because this is in the global scope, while the delegate might be set from
|
||||
* another subcomponent (that might have shorter lifespan).
|
||||
*/
|
||||
@Singleton
|
||||
class UnfoldKeyguardVisibilityManagerImpl @Inject constructor() :
|
||||
UnfoldKeyguardVisibilityProvider, UnfoldKeyguardVisibilityManager {
|
||||
|
||||
private var delegatedProvider: WeakReference<() -> Boolean?>? = null
|
||||
|
||||
override fun setKeyguardVisibleDelegate(delegate: () -> Boolean) {
|
||||
delegatedProvider = WeakReference(delegate)
|
||||
}
|
||||
|
||||
override val isKeyguardVisible: Boolean?
|
||||
get() = delegatedProvider?.get()?.invoke()
|
||||
}
|
||||
@@ -668,8 +668,8 @@ public class AttentionManagerService extends SystemService {
|
||||
mIProximityUpdateCallback = new IProximityUpdateCallback.Stub() {
|
||||
@Override
|
||||
public void onProximityUpdate(double distance) {
|
||||
mCallbackInternal.onProximityUpdate(distance);
|
||||
synchronized (mLock) {
|
||||
mCallbackInternal.onProximityUpdate(distance);
|
||||
freeIfInactiveLocked();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user