diff options
81 files changed, 2223 insertions, 1607 deletions
diff --git a/Android.bp b/Android.bp index d170913150c5..dc92586a8d14 100644 --- a/Android.bp +++ b/Android.bp @@ -632,6 +632,7 @@ java_defaults { ], sdk_version: "core_platform", static_libs: [ + "bouncycastle-repackaged-unbundled", "framework-internal-utils", // If MimeMap ever becomes its own APEX, then this dependency would need to be removed // in favor of an API stubs dependency in java_library "framework" below. diff --git a/core/api/current.txt b/core/api/current.txt index d1b9716b4cd3..3efb78943bd7 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -722,6 +722,7 @@ package android { field public static final int gwpAsanMode = 16844310; // 0x1010616 field public static final int hand_hour = 16843011; // 0x1010103 field public static final int hand_minute = 16843012; // 0x1010104 + field public static final int hand_second = 16844323; // 0x1010623 field public static final int handle = 16843354; // 0x101025a field public static final int handleProfiling = 16842786; // 0x1010022 field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e @@ -12471,6 +12472,7 @@ package android.content.pm { field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L field public static final int PERMISSION_DENIED = -1; // 0xffffffff field public static final int PERMISSION_GRANTED = 0; // 0x0 + field public static final String PROPERTY_MEDIA_CAPABILITIES = "android.media.PROPERTY_MEDIA_CAPABILITIES"; field public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; // 0xffffffff field public static final int SIGNATURE_MATCH = 0; // 0x0 field public static final int SIGNATURE_NEITHER_SIGNED = 1; // 0x1 @@ -31862,6 +31864,10 @@ package android.os.strictmode { public final class ImplicitDirectBootViolation extends android.os.strictmode.Violation { } + public final class IncorrectContextUseViolation extends android.os.strictmode.Violation { + ctor public IncorrectContextUseViolation(@NonNull String, @NonNull Throwable); + } + public class InstanceCountViolation extends android.os.strictmode.Violation { method public long getNumberOfInstances(); } @@ -53072,6 +53078,10 @@ package android.widget { ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet); ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet, int); ctor @Deprecated public AnalogClock(android.content.Context, android.util.AttributeSet, int, int); + method @Deprecated public void setDial(@NonNull android.graphics.drawable.Icon); + method @Deprecated public void setHourHand(@NonNull android.graphics.drawable.Icon); + method @Deprecated public void setMinuteHand(@NonNull android.graphics.drawable.Icon); + method @Deprecated public void setSecondHand(@Nullable android.graphics.drawable.Icon); } public class ArrayAdapter<T> extends android.widget.BaseAdapter implements android.widget.Filterable android.widget.ThemedSpinnerAdapter { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 1d13b73b7020..b748b918d1c6 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -7281,6 +7281,7 @@ package android.net { method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); + field public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; // 0x1c field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 diff --git a/core/api/test-current.txt b/core/api/test-current.txt index bc1858b63783..b0ee3f01f210 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2324,6 +2324,8 @@ package android.view { } public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable { + method @Nullable public final android.os.IBinder getWindowContextToken(); + method public final void setWindowContextToken(@NonNull android.os.IBinder); field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000 field public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 64; // 0x40 field public CharSequence accessibilityTitle; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 9085ed2be8b1..72fb1cae3871 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -125,6 +125,19 @@ public abstract class PackageManager { } /** + * <application> level {@link android.content.pm.PackageManager.Property} tag specifying + * the XML resource ID containing an application's media capabilities XML file + * + * For example: + * <application> + * <property android:name="android.media.PROPERTY_MEDIA_CAPABILITIES" + * android:resource="@xml/media_capabilities"> + * <application> + */ + public static final String PROPERTY_MEDIA_CAPABILITIES = + "android.media.PROPERTY_MEDIA_CAPABILITIES"; + + /** * A property value set within the manifest. * <p> * The value of a property will only have a single type, as defined by diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index f6edb2edc5ff..abf694f9742e 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -89,6 +89,11 @@ public class CompatibilityInfo implements Parcelable { private static final int NEEDS_COMPAT_RES = 16; /** + * Set if the application needs to be forcibly downscaled + */ + private static final int HAS_OVERRIDE_SCALING = 32; + + /** * The effective screen density we have selected for this application. */ public final int applicationDensity; @@ -107,6 +112,11 @@ public class CompatibilityInfo implements Parcelable { @UnsupportedAppUsage public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw, boolean forceCompat) { + this(appInfo, screenLayout, sw, forceCompat, 1f); + } + + public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw, + boolean forceCompat, float overrideScale) { int compatFlags = 0; if (appInfo.targetSdkVersion < VERSION_CODES.O) { @@ -241,7 +251,12 @@ public class CompatibilityInfo implements Parcelable { compatFlags |= NEVER_NEEDS_COMPAT; } - if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { + if (overrideScale != 1.0f) { + applicationDensity = DisplayMetrics.DENSITY_DEFAULT; + applicationScale = overrideScale; + applicationInvertedScale = 1.0f / overrideScale; + compatFlags |= HAS_OVERRIDE_SCALING; + } else if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { applicationDensity = DisplayMetrics.DENSITY_DEVICE; applicationScale = 1.0f; applicationInvertedScale = 1.0f; @@ -277,7 +292,7 @@ public class CompatibilityInfo implements Parcelable { */ @UnsupportedAppUsage public boolean isScalingRequired() { - return (mCompatibilityFlags&SCALING_REQUIRED) != 0; + return (mCompatibilityFlags & (SCALING_REQUIRED | HAS_OVERRIDE_SCALING)) != 0; } @UnsupportedAppUsage @@ -303,7 +318,7 @@ public class CompatibilityInfo implements Parcelable { */ @UnsupportedAppUsage public Translator getTranslator() { - return isScalingRequired() ? new Translator() : null; + return (mCompatibilityFlags & SCALING_REQUIRED) != 0 ? new Translator() : null; } /** @@ -504,6 +519,16 @@ public class CompatibilityInfo implements Parcelable { if (isScalingRequired()) { float invertedRatio = applicationInvertedScale; inoutConfig.densityDpi = (int)((inoutConfig.densityDpi * invertedRatio) + .5f); + inoutConfig.screenWidthDp = (int) ((inoutConfig.screenWidthDp * invertedRatio) + .5f); + inoutConfig.screenHeightDp = (int) ((inoutConfig.screenHeightDp * invertedRatio) + .5f); + inoutConfig.smallestScreenWidthDp = + (int) ((inoutConfig.smallestScreenWidthDp * invertedRatio) + .5f); + inoutConfig.windowConfiguration.getMaxBounds().scale(invertedRatio); + inoutConfig.windowConfiguration.getBounds().scale(invertedRatio); + final Rect appBounds = inoutConfig.windowConfiguration.getAppBounds(); + if (appBounds != null) { + appBounds.scale(invertedRatio); + } } } diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java index 250cff29944a..a22d41a5ef86 100644 --- a/core/java/android/net/http/SslCertificate.java +++ b/core/java/android/net/http/SslCertificate.java @@ -26,7 +26,7 @@ import android.view.View; import android.widget.TextView; import com.android.internal.util.HexDump; -import com.android.org.bouncycastle.asn1.x509.X509Name; +import com.android.internal.org.bouncycastle.asn1.x509.X509Name; import java.io.ByteArrayInputStream; import java.math.BigInteger; diff --git a/core/java/android/os/strictmode/IncorrectContextUseViolation.java b/core/java/android/os/strictmode/IncorrectContextUseViolation.java index 647db171e080..11d26cab14b3 100644 --- a/core/java/android/os/strictmode/IncorrectContextUseViolation.java +++ b/core/java/android/os/strictmode/IncorrectContextUseViolation.java @@ -16,19 +16,20 @@ package android.os.strictmode; +import android.annotation.NonNull; import android.content.Context; /** - * Incorrect usage of {@link Context}, such as obtaining a visual service from non-visual - * {@link Context} instance. + * Incorrect usage of {@link Context}, such as obtaining a UI service from non-UI {@link Context} + * instance. + * * @see Context#getSystemService(String) - * @see Context#getDisplayNoVerify() - * @hide + * @see Context#isUiContext(Context) + * @see android.os.StrictMode.VmPolicy.Builder#detectIncorrectContextUse() */ public final class IncorrectContextUseViolation extends Violation { - /** @hide */ - public IncorrectContextUseViolation(String message, Throwable originStack) { + public IncorrectContextUseViolation(@NonNull String message, @NonNull Throwable originStack) { super(message); initCause(originStack); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 11be792ece42..9a412fcd436a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -21370,6 +21370,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int height = mBottom - mTop; int layerType = getLayerType(); + // Hacky hack: Reset any stretch effects as those are applied during the draw pass + // instead of being "stateful" like other RenderNode properties + renderNode.clearStretch(); + final RecordingCanvas canvas = renderNode.beginRecording(width, height); try { @@ -22796,6 +22800,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final Rect bounds = drawable.getBounds(); final int width = bounds.width(); final int height = bounds.height(); + + // Hacky hack: Reset any stretch effects as those are applied during the draw pass + // instead of being "stateful" like other RenderNode properties + renderNode.clearStretch(); + final RecordingCanvas canvas = renderNode.beginRecording(width, height); // Reverse left/top translation done by drawable canvas, which will diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index fa471fa28c7f..8319b74d9cdf 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -83,6 +83,7 @@ import static android.view.WindowLayoutParamsProto.Y; import android.Manifest.permission; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -99,6 +100,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.os.Build; +import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; @@ -2855,12 +2857,14 @@ public interface WindowManager extends ViewManager { /** * The token of {@link android.app.WindowContext}. It is usually a - * {@link android.app.WindowTokenClient} and is used for updating - * {@link android.content.res.Resources} from {@link Configuration} propagated from the - * server side. + * {@link android.app.WindowTokenClient} and is used for associating the params with an + * existing node in the WindowManager hierarchy and getting the corresponding + * {@link Configuration} and {@link android.content.res.Resources} values with updates + * propagated from the server side. * * @hide */ + @Nullable public IBinder mWindowContextToken = null; /** @@ -3547,6 +3551,37 @@ public interface WindowManager extends ViewManager { return userActivityTimeout; } + /** + * Sets the {@link android.app.WindowContext} token. + * + * @see #getWindowContextToken() + * + * @hide + */ + @TestApi + public final void setWindowContextToken(@NonNull IBinder token) { + mWindowContextToken = token; + } + + /** + * Gets the {@link android.app.WindowContext} token. + * + * The token is usually a {@link android.app.WindowTokenClient} and is used for associating + * the params with an existing node in the WindowManager hierarchy and getting the + * corresponding {@link Configuration} and {@link android.content.res.Resources} values with + * updates propagated from the server side. + * + * @see android.app.WindowTokenClient + * @see Context#createWindowContext(Display, int, Bundle) + * + * @hide + */ + @TestApi + @Nullable + public final IBinder getWindowContextToken() { + return mWindowContextToken; + } + public int describeContents() { return 0; } diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java index ffdb89de5f59..98738eff83c3 100644 --- a/core/java/android/widget/AnalogClock.java +++ b/core/java/android/widget/AnalogClock.java @@ -16,6 +16,8 @@ package android.widget; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.content.BroadcastReceiver; import android.content.Context; @@ -25,8 +27,10 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.text.format.DateUtils; import android.util.AttributeSet; +import android.view.RemotableViewMethod; import android.view.View; import android.widget.RemoteViews.RemoteView; @@ -42,25 +46,32 @@ import java.time.ZoneId; * @attr ref android.R.styleable#AnalogClock_dial * @attr ref android.R.styleable#AnalogClock_hand_hour * @attr ref android.R.styleable#AnalogClock_hand_minute + * @attr ref android.R.styleable#AnalogClock_hand_second * @deprecated This widget is no longer supported. */ @RemoteView @Deprecated public class AnalogClock extends View { + /** How often the clock should refresh to make the seconds hand advance at ~15 FPS. */ + private static final long SECONDS_TICK_FREQUENCY_MS = 1000 / 15; + private Clock mClock; @UnsupportedAppUsage private Drawable mHourHand; @UnsupportedAppUsage private Drawable mMinuteHand; + @Nullable + private Drawable mSecondHand; @UnsupportedAppUsage private Drawable mDial; private int mDialWidth; private int mDialHeight; - private boolean mAttached; + private boolean mVisible; + private float mSeconds; private float mMinutes; private float mHour; private boolean mChanged; @@ -101,18 +112,70 @@ public class AnalogClock extends View { mMinuteHand = context.getDrawable(com.android.internal.R.drawable.clock_hand_minute); } + mSecondHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_second); + mClock = Clock.systemDefaultZone(); mDialWidth = mDial.getIntrinsicWidth(); mDialHeight = mDial.getIntrinsicHeight(); } + /** Sets the dial of the clock to the specified Icon. */ + @RemotableViewMethod + public void setDial(@NonNull Icon icon) { + mDial = icon.loadDrawable(getContext()); + mDialWidth = mDial.getIntrinsicWidth(); + mDialHeight = mDial.getIntrinsicHeight(); + + mChanged = true; + invalidate(); + } + + /** Sets the hour hand of the clock to the specified Icon. */ + @RemotableViewMethod + public void setHourHand(@NonNull Icon icon) { + mHourHand = icon.loadDrawable(getContext()); + + mChanged = true; + invalidate(); + } + + /** Sets the minute hand of the clock to the specified Icon. */ + @RemotableViewMethod + public void setMinuteHand(@NonNull Icon icon) { + mMinuteHand = icon.loadDrawable(getContext()); + + mChanged = true; + invalidate(); + } + + /** + * Sets the second hand of the clock to the specified Icon, or hides the second hand if it is + * null. + */ + @RemotableViewMethod + public void setSecondHand(@Nullable Icon icon) { + mSecondHand = icon == null ? null : icon.loadDrawable(getContext()); + mSecondsTick.run(); + + mChanged = true; + invalidate(); + } + @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); + public void onVisibilityAggregated(boolean isVisible) { + super.onVisibilityAggregated(isVisible); - if (!mAttached) { - mAttached = true; + if (isVisible) { + onVisible(); + } else { + onInvisible(); + } + } + + private void onVisible() { + if (!mVisible) { + mVisible = true; IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); @@ -128,6 +191,8 @@ public class AnalogClock extends View { // user not the one the context is for. getContext().registerReceiverAsUser(mIntentReceiver, android.os.Process.myUserHandle(), filter, null, getHandler()); + + mSecondsTick.run(); } // NOTE: It's safe to do these after registering the receiver since the receiver always runs @@ -140,12 +205,11 @@ public class AnalogClock extends View { onTimeChanged(); } - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mAttached) { + private void onInvisible() { + if (mVisible) { getContext().unregisterReceiver(mIntentReceiver); - mAttached = false; + removeCallbacks(mSecondsTick); + mVisible = false; } } @@ -237,6 +301,20 @@ public class AnalogClock extends View { minuteHand.draw(canvas); canvas.restore(); + final Drawable secondHand = mSecondHand; + if (secondHand != null) { + canvas.save(); + canvas.rotate(mSeconds / 60.0f * 360.0f, x, y); + + if (changed) { + w = secondHand.getIntrinsicWidth(); + h = secondHand.getIntrinsicHeight(); + secondHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2)); + } + secondHand.draw(canvas); + canvas.restore(); + } + if (scaled) { canvas.restore(); } @@ -250,6 +328,7 @@ public class AnalogClock extends View { int minute = localDateTime.getMinute(); int second = localDateTime.getSecond(); + mSeconds = second + localDateTime.getNano() / 1_000_000_000f; mMinutes = minute + second / 60.0f; mHour = hour + mMinutes / 60.0f; mChanged = true; @@ -271,6 +350,21 @@ public class AnalogClock extends View { } }; + private final Runnable mSecondsTick = new Runnable() { + @Override + public void run() { + if (!mVisible || mSecondHand == null) { + return; + } + + onTimeChanged(); + + invalidate(); + + postDelayed(this, SECONDS_TICK_FREQUENCY_MS); + } + }; + private void updateContentDescription(long timeMillis) { final int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_24HOUR; String contentDescription = DateUtils.formatDateTime(mContext, timeMillis, flags); diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 14f1e0e20ef6..07c3adfb4c69 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4069,6 +4069,7 @@ <attr name="dial" format="reference"/> <attr name="hand_hour" format="reference"/> <attr name="hand_minute" format="reference"/> + <attr name="hand_second" format="reference"/> </declare-styleable> <declare-styleable name="Button"> </declare-styleable> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 9c1c51cdd48e..b76ab3a22a20 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3059,6 +3059,7 @@ <public name="pathAdvancedPattern" /> <public name="sspAdvancedPattern" /> <public name="fontProviderSystemFontFamily" /> + <public name="hand_second" /> </public-group> <public-group type="drawable" first-id="0x010800b5"> diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index c1310a9214e0..4a92cf11fa5c 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -693,6 +693,32 @@ public final class RenderNode { throw new IllegalArgumentException("Unrecognized outline?"); } + /** @hide */ + public boolean clearStretch() { + return nClearStretch(mNativeRenderNode); + } + + /** @hide */ + public boolean stretch(float left, float top, float right, float bottom, + float vecX, float vecY, float maxStretchAmount) { + if (1.0 < vecX || vecX < -1.0) { + throw new IllegalArgumentException("vecX must be in the range [-1, 1], was " + vecX); + } + if (1.0 < vecY || vecY < -1.0) { + throw new IllegalArgumentException("vecY must be in the range [-1, 1], was " + vecY); + } + if (top <= bottom || right <= left) { + throw new IllegalArgumentException( + "Stretch region must not be empty, got " + + new RectF(left, top, right, bottom).toString()); + } + if (maxStretchAmount <= 0.0f) { + throw new IllegalArgumentException( + "The max stretch amount must be >0, got " + maxStretchAmount); + } + return nStretch(mNativeRenderNode, left, top, right, bottom, vecX, vecY, maxStretchAmount); + } + /** * Checks if the RenderNode has a shadow. That is, if the combination of {@link #getElevation()} * and {@link #getTranslationZ()} is greater than zero, there is an {@link Outline} set with @@ -1638,6 +1664,13 @@ public final class RenderNode { private static native boolean nSetOutlineNone(long renderNode); @CriticalNative + private static native boolean nClearStretch(long renderNode); + + @CriticalNative + private static native boolean nStretch(long renderNode, float left, float top, float right, + float bottom, float vecX, float vecY, float maxStretch); + + @CriticalNative private static native boolean nHasShadow(long renderNode); @CriticalNative diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java index f41b6081e38c..ae9f866459d6 100644 --- a/keystore/java/android/security/Credentials.java +++ b/keystore/java/android/security/Credentials.java @@ -19,9 +19,9 @@ package android.security; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; -import com.android.org.bouncycastle.util.io.pem.PemObject; -import com.android.org.bouncycastle.util.io.pem.PemReader; -import com.android.org.bouncycastle.util.io.pem.PemWriter; +import com.android.internal.org.bouncycastle.util.io.pem.PemObject; +import com.android.internal.org.bouncycastle.util.io.pem.PemReader; +import com.android.internal.org.bouncycastle.util.io.pem.PemWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 4a67135227dd..e19d88c182ff 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -45,8 +45,8 @@ import android.security.keystore.KeystoreResponse; import android.security.keystore.UserNotAuthenticatedException; import android.util.Log; -import com.android.org.bouncycastle.asn1.ASN1InputStream; -import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import com.android.internal.org.bouncycastle.asn1.ASN1InputStream; +import com.android.internal.org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java index 6ad8d2c0aca3..334b1110d651 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -26,24 +26,24 @@ import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterCertificateChain; import android.security.keymaster.KeymasterDefs; -import com.android.org.bouncycastle.asn1.ASN1EncodableVector; -import com.android.org.bouncycastle.asn1.ASN1InputStream; -import com.android.org.bouncycastle.asn1.ASN1Integer; -import com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier; -import com.android.org.bouncycastle.asn1.DERBitString; -import com.android.org.bouncycastle.asn1.DERNull; -import com.android.org.bouncycastle.asn1.DERSequence; -import com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; -import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import com.android.org.bouncycastle.asn1.x509.Certificate; -import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import com.android.org.bouncycastle.asn1.x509.TBSCertificate; -import com.android.org.bouncycastle.asn1.x509.Time; -import com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; -import com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers; -import com.android.org.bouncycastle.jce.X509Principal; -import com.android.org.bouncycastle.jce.provider.X509CertificateObject; -import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; +import com.android.internal.org.bouncycastle.asn1.ASN1EncodableVector; +import com.android.internal.org.bouncycastle.asn1.ASN1InputStream; +import com.android.internal.org.bouncycastle.asn1.ASN1Integer; +import com.android.internal.org.bouncycastle.asn1.ASN1ObjectIdentifier; +import com.android.internal.org.bouncycastle.asn1.DERBitString; +import com.android.internal.org.bouncycastle.asn1.DERNull; +import com.android.internal.org.bouncycastle.asn1.DERSequence; +import com.android.internal.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import com.android.internal.org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import com.android.internal.org.bouncycastle.asn1.x509.Certificate; +import com.android.internal.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import com.android.internal.org.bouncycastle.asn1.x509.TBSCertificate; +import com.android.internal.org.bouncycastle.asn1.x509.Time; +import com.android.internal.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; +import com.android.internal.org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import com.android.internal.org.bouncycastle.jce.X509Principal; +import com.android.internal.org.bouncycastle.jce.provider.X509CertificateObject; +import com.android.internal.org.bouncycastle.x509.X509V3CertificateGenerator; import libcore.util.EmptyArray; diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt index ccfdce65f7b2..24b0f3043319 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt @@ -18,10 +18,11 @@ package com.android.wm.shell.flicker import android.graphics.Region import android.view.Surface +import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER +import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER import com.android.server.wm.flicker.dsl.LayersAssertionBuilder import com.android.server.wm.flicker.helpers.WindowUtils import com.android.server.wm.flicker.traces.layers.getVisibleBounds -import com.android.wm.shell.flicker.FlickerTestBase.Companion.DOCKED_STACK_DIVIDER @JvmOverloads fun LayersAssertionBuilder.appPairsDividerIsVisible( @@ -29,7 +30,7 @@ fun LayersAssertionBuilder.appPairsDividerIsVisible( enabled: Boolean = bugId == 0 ) { end("appPairsDividerIsVisible", bugId, enabled) { - this.isVisible(FlickerTestBase.APP_PAIR_SPLIT_DIVIDER) + this.isVisible(APP_PAIR_SPLIT_DIVIDER) } } @@ -39,7 +40,7 @@ fun LayersAssertionBuilder.appPairsDividerIsInvisible( enabled: Boolean = bugId == 0 ) { end("appPairsDividerIsInVisible", bugId, enabled) { - this.notExists(FlickerTestBase.APP_PAIR_SPLIT_DIVIDER) + this.notExists(APP_PAIR_SPLIT_DIVIDER) } } @@ -107,7 +108,7 @@ fun LayersAssertionBuilder.appPairsPrimaryBoundsIsVisible( enabled: Boolean = bugId == 0 ) { end("PrimaryAppBounds", bugId, enabled) { - val dividerRegion = entry.getVisibleBounds(FlickerTestBase.APP_PAIR_SPLIT_DIVIDER) + val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER) this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation)) } } @@ -120,7 +121,7 @@ fun LayersAssertionBuilder.appPairsSecondaryBoundsIsVisible( enabled: Boolean = bugId == 0 ) { end("SecondaryAppBounds", bugId, enabled) { - val dividerRegion = entry.getVisibleBounds(FlickerTestBase.APP_PAIR_SPLIT_DIVIDER) + val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER) this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation)) } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt index 3953c1c5a0f4..89bbdb0a2f99 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt @@ -135,12 +135,4 @@ abstract class FlickerTestBase { throw RuntimeException(e) } } - - companion object { - const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar" - const val STATUS_BAR_WINDOW_TITLE = "StatusBar" - const val DOCKED_STACK_DIVIDER = "DockedStackDivider" - const val APP_PAIR_SPLIT_DIVIDER = "AppPairSplitDivider" - const val IMAGE_WALLPAPER = "ImageWallpaper" - } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt index 5cbfec638da5..257350b6950b 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt @@ -21,12 +21,12 @@ import android.os.SystemClock import android.platform.test.annotations.Presubmit import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.buildTestTag import com.android.server.wm.flicker.traces.layers.getVisibleBounds -import com.android.wm.shell.flicker.FlickerTestBase.Companion.APP_PAIR_SPLIT_DIVIDER import com.android.wm.shell.flicker.appPairsDividerIsVisible import com.android.wm.shell.flicker.helpers.AppPairsHelper import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt index f57a000a0ccb..0b001f5ac1b6 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt @@ -21,12 +21,12 @@ import android.os.SystemClock import android.platform.test.annotations.Presubmit import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER import com.android.server.wm.flicker.FlickerTestRunner import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.buildTestTag import com.android.server.wm.flicker.traces.layers.getVisibleBounds -import com.android.wm.shell.flicker.FlickerTestBase.Companion.APP_PAIR_SPLIT_DIVIDER import com.android.wm.shell.flicker.appPairsDividerIsInvisible import com.android.wm.shell.flicker.helpers.AppPairsHelper import org.junit.FixMethodOrder diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt deleted file mode 100644 index dea5c300f590..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen - -import android.platform.test.annotations.Presubmit -import android.view.Surface -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.dsl.runWithFlicker -import com.android.server.wm.flicker.helpers.canSplitScreen -import com.android.server.wm.flicker.helpers.exitSplitScreen -import com.android.server.wm.flicker.helpers.isInSplitScreen -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.helpers.openQuickstep -import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview -import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.wm.shell.flicker.dockedStackDividerIsInvisible -import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS -import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible -import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible -import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible -import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible -import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible -import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible -import org.junit.Assert -import com.android.wm.shell.flicker.dockedStackDividerBecomesVisible -import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry -import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test SplitScreen launch. - * To run this test: `atest WMShellFlickerTests:EnterLegacySplitScreenTest` - */ -@Presubmit -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class EnterLegacySplitScreenTest( - rotationName: String, - rotation: Int -) : SplitScreenTestBase(rotationName, rotation) { - private val splitScreenSetup: FlickerBuilder - get() = FlickerBuilder(instrumentation).apply { - val testLaunchActivity = "launch_splitScreen_test_activity" - withTestName { - testLaunchActivity - } - setup { - eachRun { - uiDevice.wakeUpAndGoToHomeScreen() - uiDevice.openQuickStepAndClearRecentAppsFromOverview() - } - } - teardown { - eachRun { - if (uiDevice.isInSplitScreen()) { - uiDevice.exitSplitScreen() - } - splitScreenApp.exit() - secondaryApp.exit() - nonResizeableApp.exit() - } - } - assertions { - layersTrace { - navBarLayerIsAlwaysVisible() - statusBarLayerIsAlwaysVisible() - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - } - } - } - - @Test - fun testEnterSplitScreen_dockActivity() { - val testTag = "testEnterSplitScreen_dockActivity" - runWithFlicker(splitScreenSetup) { - withTestName { testTag } - repeat { - TEST_REPETITIONS - } - transitions { - splitScreenApp.launchViaIntent() - uiDevice.launchSplitScreen() - } - assertions { - layersTrace { - dockedStackPrimaryBoundsIsVisible( - rotation, splitScreenApp.defaultWindowName, 169271943) - dockedStackDividerBecomesVisible() - visibleLayersShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, - LIVE_WALLPAPER_PACKAGE_NAME) - ) - } - windowManagerTrace { - end("appWindowIsVisible") { - isVisible(splitScreenApp.defaultWindowName) - } - } - } - } - } - - @Test - fun testEnterSplitScreen_launchToSide() { - val testTag = "testEnterSplitScreen_launchToSide" - runWithFlicker(splitScreenSetup) { - withTestName { testTag } - repeat { - TEST_REPETITIONS - } - transitions { - secondaryApp.launchViaIntent() - splitScreenApp.launchViaIntent() - uiDevice.launchSplitScreen() - splitScreenApp.reopenAppFromOverview() - } - assertions { - layersTrace { - dockedStackPrimaryBoundsIsVisible( - rotation, splitScreenApp.defaultWindowName, 169271943) - dockedStackSecondaryBoundsIsVisible( - rotation, secondaryApp.defaultWindowName, 169271943) - dockedStackDividerBecomesVisible() - visibleLayersShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, - secondaryApp.defaultWindowName) - ) - } - windowManagerTrace { - end("appWindowIsVisible") { - isVisible(splitScreenApp.defaultWindowName) - .isVisible(secondaryApp.defaultWindowName) - } - visibleWindowsShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, - secondaryApp.defaultWindowName)) - } - } - } - } - - @FlakyTest(bugId = 173875043) - @Test - fun testNonResizeableNotDocked() { - val testTag = "testNonResizeableNotDocked" - runWithFlicker(splitScreenSetup) { - withTestName { testTag } - repeat { - TEST_REPETITIONS - } - transitions { - nonResizeableApp.launchViaIntent() - uiDevice.openQuickstep() - if (uiDevice.canSplitScreen()) { - Assert.fail("Non-resizeable app should not enter split screen") - } - } - assertions { - layersTrace { - dockedStackDividerIsInvisible() - visibleLayersShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, nonResizeableApp.defaultWindowName) - ) - } - windowManagerTrace { - end("appWindowIsVisible") { - isInvisible(nonResizeableApp.defaultWindowName) - } - visibleWindowsShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, nonResizeableApp.defaultWindowName)) - } - } - } - } - - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val supportedRotations = intArrayOf(Surface.ROTATION_0) - return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } - } - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt new file mode 100644 index 000000000000..5374bd9f40de --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt @@ -0,0 +1,98 @@ +/* + * 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 com.android.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.WALLPAPER_TITLE +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.startRotation +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.wm.shell.flicker.dockedStackDividerBecomesVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test open activity and dock to primary split screen + * To run this test: `atest WMShellFlickerTests:EnterSplitScreenDockActivity` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class EnterSplitScreenDockActivity( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testLegacySplitScreenDockActivity", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + device.launchSplitScreen() + } + assertions { + layersTrace { + dockedStackPrimaryBoundsIsVisible( + configuration.startRotation, + splitScreenApp.defaultWindowName, bugId = 169271943) + dockedStackDividerBecomesVisible() + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, + WALLPAPER_TITLE, LIVE_WALLPAPER_PACKAGE_NAME, + splitScreenApp.defaultWindowName), + bugId = 178531736 + ) + } + windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, + WALLPAPER_TITLE, LIVE_WALLPAPER_PACKAGE_NAME, + splitScreenApp.defaultWindowName), + bugId = 178531736 + ) + end("appWindowIsVisible") { + isVisible(splitScreenApp.defaultWindowName) + } + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, defaultTransitionSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt new file mode 100644 index 000000000000..d750403d66c6 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt @@ -0,0 +1,102 @@ +/* + * 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 com.android.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.startRotation +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.wm.shell.flicker.dockedStackDividerBecomesVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test open activity to primary split screen and dock secondary activity to side + * To run this test: `atest WMShellFlickerTests:EnterSplitScreenLaunchToSide` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class EnterSplitScreenLaunchToSide( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testLegacySplitScreenLaunchToSide", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + device.launchSplitScreen() + secondaryApp.reopenAppFromOverview() + } + assertions { + layersTrace { + dockedStackPrimaryBoundsIsVisible( + configuration.startRotation, + splitScreenApp.defaultWindowName, bugId = 169271943) + dockedStackSecondaryBoundsIsVisible( + configuration.startRotation, + secondaryApp.defaultWindowName, bugId = 169271943) + dockedStackDividerBecomesVisible() + // TODO(b/178447631) Remove Splash Screen from white list when flicker lib + // add a wait for splash screen be gone + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, SPLASH_SCREEN_NAME, + splitScreenApp.defaultWindowName, + secondaryApp.defaultWindowName), + bugId = 178447631 + ) + } + windowManagerTrace { + appWindowBecomesVisible(secondaryApp.defaultWindowName) + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, SPLASH_SCREEN_NAME, + splitScreenApp.defaultWindowName, + secondaryApp.defaultWindowName) + ) + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, defaultTransitionSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt new file mode 100644 index 000000000000..e3619235ee77 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt @@ -0,0 +1,101 @@ +/* + * 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 com.android.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.FlakyTest +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.WALLPAPER_TITLE +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.canSplitScreen +import com.android.server.wm.flicker.helpers.openQuickstep +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.wm.shell.flicker.dockedStackDividerIsInvisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.Assert +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test open non-resizable activity will auto exit split screen mode + * To run this test: `atest WMShellFlickerTests:EnterSplitScreenNonResizableNotDock` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@FlakyTest(bugId = 173875043) +class EnterSplitScreenNonResizableNotDock( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testLegacySplitScreenNonResizeableActivityNotDock", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + nonResizeableApp.launchViaIntent(wmHelper) + device.openQuickstep() + if (device.canSplitScreen()) { + Assert.fail("Non-resizeable app should not enter split screen") + } + } + assertions { + layersTrace { + dockedStackDividerIsInvisible() + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, + SPLASH_SCREEN_NAME, + nonResizeableApp.defaultWindowName, + splitScreenApp.defaultWindowName), + bugId = 178447631 + ) + } + windowManagerTrace { + visibleWindowsShownMoreThanOneConsecutiveEntry( + listOf(WALLPAPER_TITLE, + LAUNCHER_PACKAGE_NAME, + SPLASH_SCREEN_NAME, + nonResizeableApp.defaultWindowName, + splitScreenApp.defaultWindowName) + ) + end("appWindowIsVisible") { + isInvisible(nonResizeableApp.defaultWindowName) + } + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, defaultTransitionSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS, + supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */)) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt new file mode 100644 index 000000000000..6aed83f35327 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesInVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.exitSplitScreenFromBottom +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.layerBecomesInvisible +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test open resizeable activity split in primary, and drag divider to bottom exit split screen + * To run this test: `atest WMShellFlickerTests:ExitLegacySplitScreenFromBottom` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class ExitLegacySplitScreenFromBottom( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testExitLegacySplitScreenFromBottom", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + device.launchSplitScreen() + device.exitSplitScreenFromBottom() + } + assertions { + layersTrace { + layerBecomesInvisible(DOCKED_STACK_DIVIDER) + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, + secondaryApp.defaultWindowName), + bugId = 178447631 + ) + } + windowManagerTrace { + appWindowBecomesInVisible(secondaryApp.defaultWindowName) + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, + secondaryApp.defaultWindowName) + ) + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, defaultTransitionSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt deleted file mode 100644 index a3b8673d93ed..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen - -import android.platform.test.annotations.Presubmit -import android.view.Surface -import androidx.test.filters.RequiresDevice -import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.FlickerTestRunner -import com.android.server.wm.flicker.FlickerTestRunnerFactory -import com.android.server.wm.flicker.endRotation -import com.android.server.wm.flicker.helpers.buildTestTag -import com.android.server.wm.flicker.helpers.exitSplitScreen -import com.android.server.wm.flicker.helpers.exitSplitScreenFromBottom -import com.android.server.wm.flicker.helpers.isInSplitScreen -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview -import com.android.server.wm.flicker.helpers.setRotation -import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.server.wm.flicker.repetitions -import com.android.wm.shell.flicker.helpers.SplitScreenHelper -import org.junit.FixMethodOrder -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:ExitLegacySplitScreenFromBottomTest` - */ -@Presubmit -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class ExitLegacySplitScreenFromBottomTest( - testSpec: FlickerTestRunnerFactory.TestSpec -) : FlickerTestRunner(testSpec) { - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val instrumentation = InstrumentationRegistry.getInstrumentation() - val splitScreenApp = SplitScreenHelper.getPrimary(instrumentation) - // TODO(b/162923992) Use of multiple segments of flicker spec for testing - return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, - supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)) { - configuration -> - withTestName { - buildTestTag("exitSplitScreenFromBottom", configuration) - } - repeat { configuration.repetitions } - setup { - eachRun { - device.wakeUpAndGoToHomeScreen() - device.openQuickStepAndClearRecentAppsFromOverview() - splitScreenApp.launchViaIntent(wmHelper) - device.launchSplitScreen() - device.waitForIdle() - this.setRotation(configuration.endRotation) - } - } - teardown { - eachRun { - if (device.isInSplitScreen()) { - device.exitSplitScreen() - } - splitScreenApp.exit() - } - } - transitions { - device.exitSplitScreenFromBottom() - } - assertions { - windowManagerTrace { - all("isNotEmpty") { isNotEmpty() } - } - } - } - } - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt deleted file mode 100644 index 701b0d05e65c..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen - -import android.platform.test.annotations.Presubmit -import android.util.Rational -import android.view.Surface -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry -import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry -import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible -import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible -import com.android.server.wm.flicker.layerBecomesInvisible -import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.dsl.runWithFlicker -import com.android.server.wm.flicker.helpers.exitSplitScreen -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview -import com.android.server.wm.flicker.helpers.resizeSplitScreen -import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.wm.shell.flicker.dockedStackDividerIsInvisible -import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test exit SplitScreen mode. - * To run this test: `atest WMShellFlickerTests:ExitLegacySplitScreenTest` - */ -@Presubmit -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class ExitLegacySplitScreenTest( - rotationName: String, - rotation: Int -) : SplitScreenTestBase(rotationName, rotation) { - private val splitScreenSetup: FlickerBuilder - get() = FlickerBuilder(instrumentation).apply { - val testLaunchActivity = "launch_splitScreen_test_activity" - withTestName { - testLaunchActivity - } - setup { - eachRun { - uiDevice.wakeUpAndGoToHomeScreen() - uiDevice.openQuickStepAndClearRecentAppsFromOverview() - secondaryApp.launchViaIntent() - splitScreenApp.launchViaIntent() - uiDevice.launchSplitScreen() - } - } - teardown { - eachRun { - splitScreenApp.exit() - secondaryApp.exit() - } - } - assertions { - windowManagerTrace { - visibleWindowsShownMoreThanOneConsecutiveEntry() - } - layersTrace { - visibleLayersShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME)) - } - } - } - - @Test - fun testEnterSplitScreen_exitPrimarySplitScreenMode() { - val testTag = "testEnterSplitScreen_exitPrimarySplitScreenMode" - runWithFlicker(splitScreenSetup) { - withTestName { testTag } - repeat { - TEST_REPETITIONS - } - transitions { - uiDevice.exitSplitScreen() - } - assertions { - layersTrace { - dockedStackDividerIsInvisible() - layerBecomesInvisible(splitScreenApp.defaultWindowName) - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - end("appWindowIsInvisible") { - isInvisible(splitScreenApp.defaultWindowName) - } - } - } - } - } - - @Test - @FlakyTest(bugId = 172811376) - fun testEnterSplitScreen_exitPrimary_showSecondaryAppFullScreen() { - val testTag = "testEnterSplitScreen_exitPrimary_showSecondaryAppFullScreen" - runWithFlicker(splitScreenSetup) { - withTestName { testTag } - repeat { - TEST_REPETITIONS - } - transitions { - splitScreenApp.reopenAppFromOverview() - uiDevice.resizeSplitScreen(startRatio) - } - assertions { - layersTrace { - dockedStackDividerIsInvisible() - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - end("appWindowIsVisible") { - isVisible(splitScreenApp.defaultWindowName) - } - } - } - } - } - - companion object { - private val startRatio = Rational(1, 3) - - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val supportedRotations = intArrayOf(Surface.ROTATION_0) - return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } - } - } -} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt new file mode 100644 index 000000000000..59f6aaf7dd6a --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt @@ -0,0 +1,93 @@ +/* + * 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 com.android.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesInVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.layerBecomesInvisible +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.wm.shell.flicker.dockedStackDividerIsInvisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test dock activity to primary split screen, and open secondary to side, exit primary split + * and test secondary activity become full screen. + * To run this test: `atest WMShellFlickerTests:ExitPrimarySplitScreenShowSecondaryFullscreen` + */ +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class ExitPrimarySplitScreenShowSecondaryFullscreen( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testExitPrimarySplitScreenShowSecondaryFullscreen", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + device.launchSplitScreen() + secondaryApp.reopenAppFromOverview() + // TODO(b/175687842) Can not find Split screen divider, use exit() instead + splitScreenApp.exit() + } + assertions { + layersTrace { + dockedStackDividerIsInvisible(bugId = 175687842) + layerBecomesInvisible(splitScreenApp.defaultWindowName) + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, + secondaryApp.defaultWindowName), + bugId = 178447631 + ) + } + windowManagerTrace { + appWindowBecomesInVisible(splitScreenApp.defaultWindowName) + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, + secondaryApp.defaultWindowName), + bugId = 178447631 + ) + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, defaultTransitionSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS) + } + } +} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt index 4dcbdfff8cd5..03b6edf0ff2a 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt @@ -52,13 +52,13 @@ import org.junit.runners.Parameterized /** * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:LegacySplitScreenToLauncherTest` + * To run this test: `atest WMShellFlickerTests:LegacySplitScreenToLauncher` */ @Presubmit @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -class LegacySplitScreenToLauncherTest( +class LegacySplitScreenToLauncher( testSpec: FlickerTestRunnerFactory.TestSpec ) : FlickerTestRunner(testSpec) { companion object { @@ -67,68 +67,68 @@ class LegacySplitScreenToLauncherTest( fun getParams(): Collection<Array<Any>> { val instrumentation = InstrumentationRegistry.getInstrumentation() val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation) - .launcherStrategy.supportedLauncherPackage + .launcherStrategy.supportedLauncherPackage val testApp = SimpleAppHelper(instrumentation) // b/161435597 causes the test not to work on 90 degrees return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, supportedRotations = listOf(Surface.ROTATION_0)) { configuration -> - withTestName { - buildTestTag("splitScreenToLauncher", configuration) + withTestName { + buildTestTag("splitScreenToLauncher", configuration) + } + repeat { configuration.repetitions } + setup { + test { + device.wakeUpAndGoToHomeScreen() + device.openQuickStepAndClearRecentAppsFromOverview() } - repeat { configuration.repetitions } - setup { - test { - device.wakeUpAndGoToHomeScreen() - device.openQuickStepAndClearRecentAppsFromOverview() - } - eachRun { - testApp.launchViaIntent(wmHelper) - this.setRotation(configuration.endRotation) - device.launchSplitScreen() - device.waitForIdle() - } + eachRun { + testApp.launchViaIntent(wmHelper) + this.setRotation(configuration.endRotation) + device.launchSplitScreen() + device.waitForIdle() } - teardown { - eachRun { - testApp.exit() - } - test { - if (device.isInSplitScreen()) { - device.exitSplitScreen() - } + } + teardown { + eachRun { + testApp.exit() + } + test { + if (device.isInSplitScreen()) { + device.exitSplitScreen() } } - transitions { - device.exitSplitScreen() + } + transitions { + device.exitSplitScreen() + } + assertions { + windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry() } - assertions { - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - visibleWindowsShownMoreThanOneConsecutiveEntry() - } - layersTrace { - navBarLayerIsAlwaysVisible() - statusBarLayerIsAlwaysVisible() - noUncoveredRegions(configuration.endRotation) - navBarLayerRotatesAndScales(configuration.endRotation) - statusBarLayerRotatesScales(configuration.endRotation) - visibleLayersShownMoreThanOneConsecutiveEntry( - listOf(launcherPackageName)) + layersTrace { + navBarLayerIsAlwaysVisible() + statusBarLayerIsAlwaysVisible() + noUncoveredRegions(configuration.endRotation) + navBarLayerRotatesAndScales(configuration.endRotation) + statusBarLayerRotatesScales(configuration.endRotation) + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(launcherPackageName)) - // b/161435597 causes the test not to work on 90 degrees - dockedStackDividerBecomesInvisible() + // b/161435597 causes the test not to work on 90 degrees + dockedStackDividerBecomesInvisible() - layerBecomesInvisible(testApp.getPackage()) - } + layerBecomesInvisible(testApp.getPackage()) + } - eventLog { - focusDoesNotChange(bugId = 151179149) - } + eventLog { + focusDoesNotChange(bugId = 151179149) } } + } } } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt new file mode 100644 index 000000000000..328ff88cd41b --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2020 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/LICENSE2.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.wm.shell.flicker.legacysplitscreen + +import android.app.Instrumentation +import android.os.Bundle +import android.support.test.launcherhelper.LauncherStrategyFactory +import android.view.Surface +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview +import com.android.server.wm.flicker.helpers.setRotation +import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen +import com.android.server.wm.flicker.startRotation +import com.android.wm.shell.flicker.helpers.SplitScreenHelper + +abstract class LegacySplitScreenTransition( + protected val instrumentation: Instrumentation +) { + internal val splitScreenApp = SplitScreenHelper.getPrimary(instrumentation) + internal val secondaryApp = SplitScreenHelper.getSecondary(instrumentation) + internal val nonResizeableApp = SplitScreenHelper.getNonResizeable(instrumentation) + internal val LAUNCHER_PACKAGE_NAME = LauncherStrategyFactory.getInstance(instrumentation) + .launcherStrategy.supportedLauncherPackage + internal val LIVE_WALLPAPER_PACKAGE_NAME = + "com.breel.wallpapers18.soundviz.wallpaper.variations.SoundVizWallpaperV2" + internal val LETTERBOX_NAME = "Letterbox" + internal val TOAST_NAME = "Toast" + internal val SPLASH_SCREEN_NAME = "Splash Screen" + + internal open val defaultTransitionSetup: FlickerBuilder.(Bundle) -> Unit + get() = { configuration -> + setup { + eachRun { + device.wakeUpAndGoToHomeScreen() + device.openQuickStepAndClearRecentAppsFromOverview() + secondaryApp.launchViaIntent(wmHelper) + splitScreenApp.launchViaIntent(wmHelper) + this.setRotation(configuration.startRotation) + } + } + teardown { + eachRun { + splitScreenApp.exit() + secondaryApp.exit() + this.setRotation(Surface.ROTATION_0) + } + } + } + + internal open val cleanSetup: FlickerBuilder.(Bundle) -> Unit + get() = { configuration -> + setup { + eachRun { + device.wakeUpAndGoToHomeScreen() + device.openQuickStepAndClearRecentAppsFromOverview() + this.setRotation(configuration.startRotation) + } + } + teardown { + eachRun { + nonResizeableApp.exit() + this.setRotation(Surface.ROTATION_0) + } + } + } + + internal open val customRotateSetup: FlickerBuilder.(Bundle) -> Unit + get() = { configuration -> + setup { + eachRun { + device.wakeUpAndGoToHomeScreen() + device.openQuickStepAndClearRecentAppsFromOverview() + secondaryApp.launchViaIntent(wmHelper) + splitScreenApp.launchViaIntent(wmHelper) + } + } + teardown { + eachRun { + splitScreenApp.exit() + secondaryApp.exit() + this.setRotation(Surface.ROTATION_0) + } + } + } +} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt new file mode 100644 index 000000000000..42c7b7c032cd --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt @@ -0,0 +1,100 @@ +/* + * 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 com.android.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesInVisible +import com.android.server.wm.flicker.appWindowBecomesVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.layerBecomesInvisible +import com.android.server.wm.flicker.layerBecomesVisible +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test launch non resizable activity in split screen mode will trigger exit split screen mode + * (Non resizable activity launch via recent overview) + * To run this test: `atest WMShellFlickerTests:NonResizableDismissInLegacySplitScreen` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class NonResizableDismissInLegacySplitScreen( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testNonResizableDismissInLegacySplitScreen", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + nonResizeableApp.launchViaIntent(wmHelper) + splitScreenApp.launchViaIntent(wmHelper) + device.launchSplitScreen() + nonResizeableApp.reopenAppFromOverview() + wmHelper.waitForAppTransitionIdle() + } + assertions { + layersTrace { + layerBecomesVisible(nonResizeableApp.defaultWindowName) + layerBecomesInvisible(splitScreenApp.defaultWindowName) + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(DOCKED_STACK_DIVIDER, LAUNCHER_PACKAGE_NAME, + LETTERBOX_NAME, TOAST_NAME, + splitScreenApp.defaultWindowName, + nonResizeableApp.defaultWindowName), + bugId = 178447631 + ) + } + windowManagerTrace { + appWindowBecomesVisible(nonResizeableApp.defaultWindowName) + appWindowBecomesInVisible(splitScreenApp.defaultWindowName) + visibleWindowsShownMoreThanOneConsecutiveEntry( + listOf(DOCKED_STACK_DIVIDER, LAUNCHER_PACKAGE_NAME, + LETTERBOX_NAME, TOAST_NAME, + splitScreenApp.defaultWindowName, + nonResizeableApp.defaultWindowName) + ) + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, cleanSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS, + supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */)) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreenTest.kt deleted file mode 100644 index 6fca5809b4fa..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreenTest.kt +++ /dev/null @@ -1,92 +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 com.android.wm.shell.flicker.legacysplitscreen - -import android.platform.test.annotations.Presubmit -import android.view.Surface -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.dsl.runWithFlicker -import com.android.server.wm.flicker.helpers.WindowUtils -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry -import com.android.wm.shell.flicker.dockedStackDividerIsInvisible -import com.android.wm.shell.flicker.helpers.SplitScreenHelper -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:NonResizableDismissInLegacySplitScreenTest` - */ -@Presubmit -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class NonResizableDismissInLegacySplitScreenTest( - rotationName: String, - rotation: Int -) : SplitScreenTestBase(rotationName, rotation) { - - @Test - fun testNonResizableDismissInLegacySplitScreenTest() { - val testTag = "testNonResizableDismissInLegacySplitScreenTest" - - runWithFlicker(transitionSetup) { - withTestName { testTag } - repeat { SplitScreenHelper.TEST_REPETITIONS } - transitions { - nonResizeableApp.launchViaIntent(wmHelper) - splitScreenApp.launchViaIntent(wmHelper) - device.launchSplitScreen() - nonResizeableApp.reopenAppFromOverview() - } - assertions { - layersTrace { - dockedStackDividerIsInvisible() - end("appsEndingBounds", enabled = false) { - val displayBounds = WindowUtils.getDisplayBounds(rotation) - this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds) - } - visibleLayersShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, - nonResizeableApp.defaultWindowName, LETTER_BOX_NAME, - TOAST_NAME, LIVE_WALLPAPER_PACKAGE_NAME), - bugId = 178447631 - ) - } - windowManagerTrace { - end("nonResizeableAppWindowIsVisible") { - isVisible(nonResizeableApp.defaultWindowName) - .isInvisible(splitScreenApp.defaultWindowName) - } - } - } - } - } - - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90) - return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } - } - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt new file mode 100644 index 000000000000..5b8ec1e9c61e --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt @@ -0,0 +1,100 @@ +/* + * 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 com.android.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesInVisible +import com.android.server.wm.flicker.appWindowBecomesVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.layerBecomesInvisible +import com.android.server.wm.flicker.layerBecomesVisible +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test launch non resizable activity in split screen mode will trigger exit split screen mode + * (Non resizable activity launch via intent) + * To run this test: `atest WMShellFlickerTests:NonResizableLaunchInLegacySplitScreen` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class NonResizableLaunchInLegacySplitScreen( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testNonResizableLaunchInLegacySplitScreen", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + splitScreenApp.launchViaIntent(wmHelper) + device.launchSplitScreen() + nonResizeableApp.launchViaIntent(wmHelper) + wmHelper.waitForAppTransitionIdle() + } + assertions { + layersTrace { + layerBecomesVisible(nonResizeableApp.defaultWindowName) + layerBecomesInvisible(splitScreenApp.defaultWindowName) + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(DOCKED_STACK_DIVIDER, + LAUNCHER_PACKAGE_NAME, + LETTERBOX_NAME, + nonResizeableApp.defaultWindowName, + splitScreenApp.defaultWindowName) + ) + } + windowManagerTrace { + appWindowBecomesVisible(nonResizeableApp.defaultWindowName) + appWindowBecomesInVisible(splitScreenApp.defaultWindowName) + visibleWindowsShownMoreThanOneConsecutiveEntry( + listOf(DOCKED_STACK_DIVIDER, + LAUNCHER_PACKAGE_NAME, + LETTERBOX_NAME, + nonResizeableApp.defaultWindowName, + splitScreenApp.defaultWindowName) + ) + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, cleanSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS, + supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */)) + } + } +} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreenTest.kt deleted file mode 100644 index deae41fae0ca..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreenTest.kt +++ /dev/null @@ -1,92 +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 com.android.wm.shell.flicker.legacysplitscreen - -import android.platform.test.annotations.Presubmit -import android.view.Surface -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.dsl.runWithFlicker -import com.android.server.wm.flicker.helpers.WindowUtils -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry -import com.android.wm.shell.flicker.dockedStackDividerIsInvisible -import com.android.wm.shell.flicker.helpers.SplitScreenHelper -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:NonResizableLaunchInLegacySplitScreenTest` - */ -@Presubmit -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class NonResizableLaunchInLegacySplitScreenTest( - rotationName: String, - rotation: Int -) : SplitScreenTestBase(rotationName, rotation) { - - @Test - fun testNonResizableLaunchInLegacySplitScreenTest() { - val testTag = "testNonResizableLaunchInLegacySplitScreenTest" - - runWithFlicker(transitionSetup) { - withTestName { testTag } - repeat { SplitScreenHelper.TEST_REPETITIONS } - transitions { - nonResizeableApp.launchViaIntent(wmHelper) - splitScreenApp.launchViaIntent(wmHelper) - device.launchSplitScreen() - nonResizeableApp.reopenAppFromOverview() - } - assertions { - layersTrace { - dockedStackDividerIsInvisible() - end("appsEndingBounds", enabled = false) { - val displayBounds = WindowUtils.getDisplayBounds(rotation) - this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds) - } - visibleLayersShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, - nonResizeableApp.defaultWindowName, LETTER_BOX_NAME, - TOAST_NAME, LIVE_WALLPAPER_PACKAGE_NAME), - bugId = 178447631 - ) - } - windowManagerTrace { - end("nonResizeableAppWindowIsVisible") { - isVisible(nonResizeableApp.defaultWindowName) - .isInvisible(splitScreenApp.defaultWindowName) - } - } - } - } - } - - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90) - return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } - } - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt index 6200a69b795e..c802ffef204f 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt @@ -16,94 +16,84 @@ package com.android.wm.shell.flicker.legacysplitscreen +import android.os.Bundle import android.platform.test.annotations.Presubmit -import android.view.Surface import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory import com.android.server.wm.flicker.appWindowBecomesVisible -import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible -import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry -import com.android.server.wm.flicker.layerBecomesVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.focusChanges +import com.android.server.wm.flicker.helpers.buildTestTag import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.dsl.runWithFlicker -import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible +import com.android.server.wm.flicker.layerBecomesVisible import com.android.server.wm.flicker.noUncoveredRegions +import com.android.server.wm.flicker.startRotation +import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper import com.android.wm.shell.flicker.appPairsDividerBecomesVisible import com.android.wm.shell.flicker.helpers.SplitScreenHelper import org.junit.FixMethodOrder -import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:OpenAppToLegacySplitScreenTest` + * To run this test: `atest WMShellFlickerTests:OpenAppToLegacySplitScreen` */ @Presubmit @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -class OpenAppToLegacySplitScreenTest( - rotationName: String, - rotation: Int -) : SplitScreenTestBase(rotationName, rotation) { - @Test - fun OpenAppToLegacySplitScreenTest() { - val testTag = "OpenAppToLegacySplitScreenTest" - val helper = WindowManagerStateHelper() - runWithFlicker(transitionSetup) { - withTestName { testTag } - repeat { SplitScreenHelper.TEST_REPETITIONS } - setup { - eachRun { - splitScreenApp.launchViaIntent(wmHelper) - device.pressHome() - this.setRotation(rotation) +class OpenAppToLegacySplitScreen( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val wmHelper = WindowManagerStateHelper() + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testOpenAppToLegacySplitScreen", configuration) } - } - transitions { - device.launchSplitScreen() - helper.waitForAppTransitionIdle() - } - assertions { - windowManagerTrace { - visibleWindowsShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, - LETTER_BOX_NAME) - ) - appWindowBecomesVisible(splitScreenApp.getPackage()) + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + device.launchSplitScreen() + wmHelper.waitForAppTransitionIdle() } + assertions { + windowManagerTrace { + visibleWindowsShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName), + bugId = 178447631) + appWindowBecomesVisible(splitScreenApp.getPackage()) + } - layersTrace { - navBarLayerIsAlwaysVisible() - noUncoveredRegions(rotation, enabled = false) - statusBarLayerIsAlwaysVisible() - visibleLayersShownMoreThanOneConsecutiveEntry( - listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName, - LETTER_BOX_NAME)) - appPairsDividerBecomesVisible() - layerBecomesVisible(splitScreenApp.getPackage()) - } + layersTrace { + noUncoveredRegions(configuration.startRotation, enabled = false) + statusBarLayerIsAlwaysVisible() + appPairsDividerBecomesVisible() + layerBecomesVisible(splitScreenApp.getPackage()) + visibleLayersShownMoreThanOneConsecutiveEntry( + listOf(LAUNCHER_PACKAGE_NAME, splitScreenApp.defaultWindowName), + bugId = 178447631) + } - eventLog { - focusChanges(splitScreenApp.`package`, + eventLog { + focusChanges(splitScreenApp.`package`, "recents_animation_input_consumer", "NexusLauncherActivity", bugId = 151179149) + } } } - } - } - - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - // TODO(b/161435597) causes the test not to work on 90 degrees - val supportedRotations = intArrayOf(Surface.ROTATION_0) - return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, defaultTransitionSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS) } } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt index 95c1c16385c4..54a37d71868d 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt @@ -58,7 +58,7 @@ import org.junit.runners.Parameterized /** * Test split screen resizing window transitions. - * To run this test: `atest WMShellFlickerTests:ResizeLegacySplitScreenTest` + * To run this test: `atest WMShellFlickerTests:ResizeLegacySplitScreen` * * Currently it runs only in 0 degrees because of b/156100803 */ @@ -67,7 +67,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 159096424) -class ResizeLegacySplitScreenTest( +class ResizeLegacySplitScreen( testSpec: FlickerTestRunnerFactory.TestSpec ) : FlickerTestRunner(testSpec) { companion object { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt new file mode 100644 index 000000000000..214269e13203 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.endRotation +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.helpers.setRotation +import com.android.server.wm.flicker.navBarLayerRotatesAndScales +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.startRotation +import com.android.server.wm.flicker.statusBarLayerRotatesScales +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.dockedStackDividerIsVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test dock activity to primary split screen and rotate + * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppAndEnterSplitScreen` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class RotateOneLaunchedAppAndEnterSplitScreen( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testRotateOneLaunchedAppAndEnterSplitScreen", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + device.launchSplitScreen() + this.setRotation(configuration.startRotation) + } + assertions { + layersTrace { + dockedStackDividerIsVisible(bugId = 175687842) + dockedStackPrimaryBoundsIsVisible( + configuration.startRotation, + splitScreenApp.defaultWindowName, bugId = 175687842) + navBarLayerRotatesAndScales( + configuration.startRotation, + configuration.endRotation, bugId = 169271943) + statusBarLayerRotatesScales( + configuration.startRotation, + configuration.endRotation, bugId = 169271943) + } + windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + appWindowBecomesVisible(splitScreenApp.defaultWindowName) + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, customRotateSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS, + supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */)) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt new file mode 100644 index 000000000000..4290c923b38d --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.endRotation +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.helpers.setRotation +import com.android.server.wm.flicker.navBarLayerRotatesAndScales +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.startRotation +import com.android.server.wm.flicker.statusBarLayerRotatesScales +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.dockedStackDividerIsVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Rotate + * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppInSplitScreenMode` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class RotateOneLaunchedAppInSplitScreenMode( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testRotateOneLaunchedAppInSplitScreenMode", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + this.setRotation(configuration.startRotation) + device.launchSplitScreen() + } + assertions { + layersTrace { + dockedStackDividerIsVisible(bugId = 175687842) + dockedStackPrimaryBoundsIsVisible( + configuration.startRotation, + splitScreenApp.defaultWindowName, bugId = 175687842) + navBarLayerRotatesAndScales( + configuration.startRotation, + configuration.endRotation, bugId = 169271943) + statusBarLayerRotatesScales( + configuration.startRotation, + configuration.endRotation, bugId = 169271943) + } + windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + appWindowBecomesVisible(splitScreenApp.defaultWindowName) + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, customRotateSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS, + supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */)) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt deleted file mode 100644 index 07571c3218a8..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen - -import android.platform.test.annotations.Presubmit -import android.view.Surface -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.dsl.runWithFlicker -import com.android.server.wm.flicker.helpers.exitSplitScreen -import com.android.server.wm.flicker.helpers.isInSplitScreen -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview -import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.server.wm.flicker.navBarLayerRotatesAndScales -import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible -import com.android.server.wm.flicker.statusBarLayerRotatesScales -import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible -import com.android.wm.shell.flicker.dockedStackDividerIsVisible -import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible -import com.android.wm.shell.flicker.helpers.SplitScreenHelper -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppTest` - */ -@Presubmit -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class RotateOneLaunchedAppTest( - rotationName: String, - rotation: Int -) : SplitScreenTestBase(rotationName, rotation) { - private val splitScreenRotationSetup: FlickerBuilder - get() = FlickerBuilder(instrumentation).apply { - val testSetupRotation = "testSetupRotation" - withTestName { - testSetupRotation - } - setup { - test { - uiDevice.wakeUpAndGoToHomeScreen() - uiDevice.openQuickStepAndClearRecentAppsFromOverview() - } - } - teardown { - eachRun { - if (uiDevice.isInSplitScreen()) { - uiDevice.exitSplitScreen() - } - setRotation(Surface.ROTATION_0) - splitScreenApp.exit() - secondaryApp.exit() - } - } - } - - @Test - fun testRotateInSplitScreenMode() { - val testTag = "testEnterSplitScreen_launchToSide" - runWithFlicker(splitScreenRotationSetup) { - withTestName { testTag } - repeat { - SplitScreenHelper.TEST_REPETITIONS - } - transitions { - splitScreenApp.launchViaIntent() - uiDevice.launchSplitScreen() - setRotation(rotation) - } - assertions { - layersTrace { - navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943) - statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943) - dockedStackDividerIsVisible() - dockedStackPrimaryBoundsIsVisible( - rotation, splitScreenApp.defaultWindowName, 169271943) - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - end("appWindowIsVisible") { - isVisible(splitScreenApp.defaultWindowName) - } - } - } - } - } - - @Test - fun testRotateAndEnterSplitScreenMode() { - val testTag = "testRotateAndEnterSplitScreenMode" - runWithFlicker(splitScreenRotationSetup) { - withTestName { testTag } - repeat { - SplitScreenHelper.TEST_REPETITIONS - } - transitions { - splitScreenApp.launchViaIntent() - setRotation(rotation) - uiDevice.launchSplitScreen() - } - assertions { - layersTrace { - navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943) - statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943) - dockedStackDividerIsVisible() - dockedStackPrimaryBoundsIsVisible( - rotation, splitScreenApp.defaultWindowName, 169271943) - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - end("appWindowIsVisible") { - isVisible(splitScreenApp.defaultWindowName) - } - } - } - } - } - - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270) - return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } - } - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt new file mode 100644 index 000000000000..4095b9a2e61e --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.endRotation +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.helpers.setRotation +import com.android.server.wm.flicker.navBarLayerRotatesAndScales +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.startRotation +import com.android.server.wm.flicker.statusBarLayerRotatesScales +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.dockedStackDividerIsVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test open app to split screen. + * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppAndEnterSplitScreen` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class RotateTwoLaunchedAppAndEnterSplitScreen( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testRotateTwoLaunchedAppAndEnterSplitScreen", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + transitions { + this.setRotation(configuration.startRotation) + device.launchSplitScreen() + secondaryApp.reopenAppFromOverview() + } + assertions { + layersTrace { + dockedStackDividerIsVisible(bugId = 175687842) + dockedStackPrimaryBoundsIsVisible( + configuration.startRotation, + splitScreenApp.defaultWindowName, 175687842) + dockedStackSecondaryBoundsIsVisible( + configuration.startRotation, + secondaryApp.defaultWindowName, bugId = 175687842) + navBarLayerRotatesAndScales( + configuration.startRotation, + configuration.endRotation, bugId = 169271943) + statusBarLayerRotatesScales( + configuration.startRotation, + configuration.endRotation, bugId = 169271943) + } + windowManagerTrace { + appWindowBecomesVisible(secondaryApp.defaultWindowName) + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, customRotateSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS, + supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */)) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt new file mode 100644 index 000000000000..aebf6067615e --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen + +import android.os.Bundle +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.appWindowBecomesVisible +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.endRotation +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.helpers.setRotation +import com.android.server.wm.flicker.navBarLayerRotatesAndScales +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.startRotation +import com.android.server.wm.flicker.statusBarLayerRotatesScales +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.dockedStackDividerIsVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test open app to split screen. + * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppInSplitScreenMode` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class RotateTwoLaunchedAppInSplitScreenMode( + testSpec: FlickerTestRunnerFactory.TestSpec +) : FlickerTestRunner(testSpec) { + companion object : LegacySplitScreenTransition(InstrumentationRegistry.getInstrumentation()) { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration -> + withTestName { + buildTestTag("testRotateTwoLaunchedAppInSplitScreenMode", configuration) + } + repeat { SplitScreenHelper.TEST_REPETITIONS } + setup { + eachRun { + device.launchSplitScreen() + splitScreenApp.reopenAppFromOverview() + this.setRotation(configuration.startRotation) + } + } + transitions { + this.setRotation(configuration.startRotation) + } + assertions { + layersTrace { + dockedStackDividerIsVisible(bugId = 175687842) + dockedStackPrimaryBoundsIsVisible( + configuration.startRotation, + splitScreenApp.defaultWindowName, bugId = 175687842) + dockedStackSecondaryBoundsIsVisible( + configuration.startRotation, + secondaryApp.defaultWindowName, bugId = 175687842) + navBarLayerRotatesAndScales( + configuration.startRotation, + configuration.endRotation, bugId = 169271943) + statusBarLayerRotatesScales( + configuration.startRotation, + configuration.endRotation, bugId = 169271943) + } + windowManagerTrace { + appWindowBecomesVisible(secondaryApp.defaultWindowName) + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + } + } + } + return FlickerTestRunnerFactory.getInstance().buildTest( + instrumentation, customRotateSetup, testSpec, + repetitions = SplitScreenHelper.TEST_REPETITIONS, + supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */)) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt deleted file mode 100644 index d8014d37dfad..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen - -import android.platform.test.annotations.Presubmit -import android.view.Surface -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.dsl.runWithFlicker -import com.android.server.wm.flicker.helpers.exitSplitScreen -import com.android.server.wm.flicker.helpers.isInSplitScreen -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview -import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.server.wm.flicker.navBarLayerRotatesAndScales -import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible -import com.android.server.wm.flicker.statusBarLayerRotatesScales -import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible -import com.android.wm.shell.flicker.dockedStackDividerIsVisible -import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible -import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible -import com.android.wm.shell.flicker.helpers.SplitScreenHelper -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppTest` - */ -@Presubmit -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class RotateTwoLaunchedAppTest( - rotationName: String, - rotation: Int -) : SplitScreenTestBase(rotationName, rotation) { - private val splitScreenRotationSetup: FlickerBuilder - get() = FlickerBuilder(instrumentation).apply { - val testSetupRotation = "testSetupRotation" - withTestName { - testSetupRotation - } - setup { - test { - uiDevice.wakeUpAndGoToHomeScreen() - uiDevice.openQuickStepAndClearRecentAppsFromOverview() - } - } - teardown { - eachRun { - if (uiDevice.isInSplitScreen()) { - uiDevice.exitSplitScreen() - } - setRotation(Surface.ROTATION_0) - splitScreenApp.exit() - secondaryApp.exit() - } - } - } - - @Test - fun testRotateInSplitScreenMode() { - val testTag = "testRotateInSplitScreenMode" - runWithFlicker(splitScreenRotationSetup) { - withTestName { testTag } - repeat { - SplitScreenHelper.TEST_REPETITIONS - } - transitions { - secondaryApp.launchViaIntent() - splitScreenApp.launchViaIntent() - uiDevice.launchSplitScreen() - splitScreenApp.reopenAppFromOverview() - setRotation(rotation) - } - assertions { - layersTrace { - navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943) - statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943) - dockedStackDividerIsVisible() - dockedStackPrimaryBoundsIsVisible( - rotation, splitScreenApp.defaultWindowName, 169271943) - dockedStackSecondaryBoundsIsVisible( - rotation, secondaryApp.defaultWindowName, 169271943) - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - end("appWindowIsVisible") { - isVisible(splitScreenApp.defaultWindowName) - .isVisible(secondaryApp.defaultWindowName) - } - } - } - } - } - - @FlakyTest(bugId = 173875043) - @Test - fun testRotateAndEnterSplitScreenMode() { - val testTag = "testRotateAndEnterSplitScreenMode" - runWithFlicker(splitScreenRotationSetup) { - withTestName { testTag } - repeat { - SplitScreenHelper.TEST_REPETITIONS - } - transitions { - secondaryApp.launchViaIntent() - splitScreenApp.launchViaIntent() - setRotation(rotation) - uiDevice.launchSplitScreen() - splitScreenApp.reopenAppFromOverview() - } - assertions { - layersTrace { - navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943) - statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943) - dockedStackDividerIsVisible() - dockedStackPrimaryBoundsIsVisible( - rotation, splitScreenApp.defaultWindowName, 169271943) - dockedStackSecondaryBoundsIsVisible( - rotation, secondaryApp.defaultWindowName, 169271943) - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - end("appWindowIsVisible") { - isVisible(splitScreenApp.defaultWindowName) - .isVisible(secondaryApp.defaultWindowName) - } - } - } - } - } - - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270) - return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } - } - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt deleted file mode 100644 index 01db4ed6253e..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2020 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.wm.shell.flicker.legacysplitscreen - -import android.support.test.launcherhelper.LauncherStrategyFactory -import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.helpers.exitSplitScreen -import com.android.server.wm.flicker.helpers.isInSplitScreen -import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview -import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible -import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible -import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible -import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible -import com.android.wm.shell.flicker.NonRotationTestBase -import com.android.wm.shell.flicker.helpers.SplitScreenHelper - -abstract class SplitScreenTestBase( - rotationName: String, - rotation: Int -) : NonRotationTestBase(rotationName, rotation) { - protected val splitScreenApp = SplitScreenHelper.getPrimary(instrumentation) - protected val secondaryApp = SplitScreenHelper.getSecondary(instrumentation) - protected val nonResizeableApp = SplitScreenHelper.getNonResizeable(instrumentation) - protected val LAUNCHER_PACKAGE_NAME = LauncherStrategyFactory.getInstance(instrumentation) - .launcherStrategy.supportedLauncherPackage - protected val LIVE_WALLPAPER_PACKAGE_NAME = - "com.breel.wallpapers18.soundviz.wallpaper.variations.SoundVizWallpaperV2" - protected val LETTER_BOX_NAME = "Letterbox" - protected val TOAST_NAME = "Toast" - - protected val transitionSetup: FlickerBuilder - get() = FlickerBuilder(instrumentation).apply { - setup { - eachRun { - uiDevice.wakeUpAndGoToHomeScreen() - uiDevice.openQuickStepAndClearRecentAppsFromOverview() - } - } - teardown { - eachRun { - if (uiDevice.isInSplitScreen()) { - uiDevice.exitSplitScreen() - } - splitScreenApp.exit() - nonResizeableApp.exit() - } - } - assertions { - layersTrace { - navBarLayerIsAlwaysVisible() - statusBarLayerIsAlwaysVisible() - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - } - } - } -} diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 615bf4de9fcc..ce1d96c167d7 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -435,6 +435,7 @@ cc_defaults { "canvas/CanvasFrontend.cpp", "canvas/CanvasOpBuffer.cpp", "canvas/CanvasOpRasterizer.cpp", + "effects/StretchEffect.cpp", "pipeline/skia/SkiaDisplayList.cpp", "pipeline/skia/SkiaRecordingCanvas.cpp", "pipeline/skia/RenderNodeDrawable.cpp", diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 96118aaec29b..64b8b711f0a8 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -561,7 +561,7 @@ public: return; } c->concat(invertedMatrix); - mLayerSurface->draw(c, deviceBounds.fLeft, deviceBounds.fTop, nullptr); + mLayerSurface->draw(c, deviceBounds.fLeft, deviceBounds.fTop); } else { c->drawDrawable(drawable.get()); } diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index aeb60e6ce355..609706e2e49d 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -23,6 +23,7 @@ #include "Outline.h" #include "Rect.h" #include "RevealClip.h" +#include "effects/StretchEffect.h" #include "utils/MathUtils.h" #include "utils/PaintUtils.h" @@ -98,6 +99,10 @@ public: SkImageFilter* getImageFilter() const { return mImageFilter.get(); } + const StretchEffect& getStretchEffect() const { return mStretchEffect; } + + StretchEffect& mutableStretchEffect() { return mStretchEffect; } + // Sets alpha, xfermode, and colorfilter from an SkPaint // paint may be NULL, in which case defaults will be set bool setFromPaint(const SkPaint* paint); @@ -124,6 +129,7 @@ private: SkBlendMode mMode; sk_sp<SkColorFilter> mColorFilter; sk_sp<SkImageFilter> mImageFilter; + StretchEffect mStretchEffect; }; /* diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp new file mode 100644 index 000000000000..51cbc7592861 --- /dev/null +++ b/libs/hwui/effects/StretchEffect.cpp @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#include "StretchEffect.h" + +namespace android::uirenderer { + +sk_sp<SkImageFilter> StretchEffect::getImageFilter() const { + // TODO: Implement & Cache + // Probably need to use mutable to achieve caching + return nullptr; +} + +} // namespace android::uirenderer
\ No newline at end of file diff --git a/libs/hwui/effects/StretchEffect.h b/libs/hwui/effects/StretchEffect.h new file mode 100644 index 000000000000..7dfd6398765a --- /dev/null +++ b/libs/hwui/effects/StretchEffect.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#pragma once + +#include "utils/MathUtils.h" + +#include <SkPoint.h> +#include <SkRect.h> +#include <SkImageFilter.h> + +namespace android::uirenderer { + +// TODO: Inherit from base RenderEffect type? +class StretchEffect { +public: + enum class StretchInterpolator { + SmoothStep, + }; + + bool isEmpty() const { + return MathUtils::isZero(stretchDirection.x()) + && MathUtils::isZero(stretchDirection.y()); + } + + void setEmpty() { + *this = StretchEffect{}; + } + + void mergeWith(const StretchEffect& other) { + if (other.isEmpty()) { + return; + } + if (isEmpty()) { + *this = other; + return; + } + stretchDirection += other.stretchDirection; + if (isEmpty()) { + return setEmpty(); + } + stretchArea.join(other.stretchArea); + maxStretchAmount = std::max(maxStretchAmount, other.maxStretchAmount); + } + + sk_sp<SkImageFilter> getImageFilter() const; + + SkRect stretchArea {0, 0, 0, 0}; + SkVector stretchDirection {0, 0}; + float maxStretchAmount = 0; +}; + +} // namespace android::uirenderer diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp index 8b35d96aeac8..80239687a7fb 100644 --- a/libs/hwui/jni/android_graphics_RenderNode.cpp +++ b/libs/hwui/jni/android_graphics_RenderNode.cpp @@ -166,6 +166,31 @@ static jboolean android_view_RenderNode_setOutlineNone(CRITICAL_JNI_PARAMS_COMMA return true; } +static jboolean android_view_RenderNode_clearStretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + auto& stretch = renderNode->mutateStagingProperties() + .mutateLayerProperties().mutableStretchEffect(); + if (stretch.isEmpty()) { + return false; + } + stretch.setEmpty(); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); + return true; +} + +static jboolean android_view_RenderNode_stretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, + jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat vX, jfloat vY, jfloat max) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + renderNode->mutateStagingProperties().mutateLayerProperties().mutableStretchEffect().mergeWith( + StretchEffect{ + .stretchArea = SkRect::MakeLTRB(left, top, right, bottom), + .stretchDirection = {.fX = vX, .fY = vY}, + .maxStretchAmount = max + }); + renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); + return true; +} + static jboolean android_view_RenderNode_hasShadow(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); return renderNode->stagingProperties().hasShadow(); @@ -678,6 +703,8 @@ static const JNINativeMethod gMethods[] = { { "nSetOutlinePath", "(JJF)Z", (void*) android_view_RenderNode_setOutlinePath }, { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, + { "nClearStretch", "(J)Z", (void*) android_view_RenderNode_clearStretch }, + { "nStretch", "(JFFFFFFF)Z", (void*) android_view_RenderNode_stretch }, { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow }, { "nSetSpotShadowColor", "(JI)Z", (void*) android_view_RenderNode_setSpotShadowColor }, { "nGetSpotShadowColor", "(J)I", (void*) android_view_RenderNode_getSpotShadowColor }, diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp index c6c9e9dc869a..71f533c3fc4f 100644 --- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp @@ -194,7 +194,7 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) { canvas->concat(invertedMatrix); const SkIRect deviceBounds = canvas->getDeviceClipBounds(); - tmpSurface->draw(canvas, deviceBounds.fLeft, deviceBounds.fTop, nullptr); + tmpSurface->draw(canvas, deviceBounds.fLeft, deviceBounds.fTop); } } diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index 75815bb6e63d..c01021221f37 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -20,6 +20,8 @@ #include "SkiaDisplayList.h" #include "utils/TraceUtils.h" +#include <include/effects/SkImageFilters.h> + #include <optional> namespace android { @@ -171,11 +173,25 @@ static bool layerNeedsPaint(const LayerProperties& properties, float alphaMultip SkPaint* paint) { if (alphaMultiplier < 1.0f || properties.alpha() < 255 || properties.xferMode() != SkBlendMode::kSrcOver || properties.getColorFilter() != nullptr || - properties.getImageFilter() != nullptr) { + properties.getImageFilter() != nullptr || !properties.getStretchEffect().isEmpty()) { paint->setAlpha(properties.alpha() * alphaMultiplier); paint->setBlendMode(properties.xferMode()); paint->setColorFilter(sk_ref_sp(properties.getColorFilter())); - paint->setImageFilter(sk_ref_sp(properties.getImageFilter())); + + sk_sp<SkImageFilter> imageFilter = sk_ref_sp(properties.getImageFilter()); + sk_sp<SkImageFilter> stretchFilter = properties.getStretchEffect().getImageFilter(); + sk_sp<SkImageFilter> filter; + if (imageFilter && stretchFilter) { + filter = SkImageFilters::Compose( + std::move(stretchFilter), + std::move(imageFilter) + ); + } else if (stretchFilter) { + filter = std::move(stretchFilter); + } else { + filter = std::move(imageFilter); + } + paint->setImageFilter(std::move(filter)); return true; } return false; diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp index d464587cb6c8..3d633ea7089d 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -27,14 +27,13 @@ cc_library_shared { ], shared_libs: [ - "libandroid_runtime", "libhwui", "liblog", ], header_libs: [ - "libhwui_internal_headers", "jni_headers", + "libhwui_internal_headers", ], static_libs: ["libarect"], diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java index 0832152d6ab6..8bfa77acd36d 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java @@ -401,11 +401,18 @@ public final class NetworkCapabilities implements Parcelable { public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; /** - * Indicates that this network is not managed by a Virtual Carrier Network (VCN). - * - * TODO(b/177299683): Add additional clarifying javadoc. + * Indicates that this network is not subsumed by a Virtual Carrier Network (VCN). + * <p> + * To provide an experience on a VCN similar to a single traditional carrier network, in + * some cases the system sets this bit is set by default in application's network requests, + * and may choose to remove it at its own discretion when matching the request to a network. + * <p> + * Applications that want to know about a Virtual Carrier Network's underlying networks, + * for example to use them for multipath purposes, should remove this bit from their network + * requests ; the system will not add it back once removed. * @hide */ + @SystemApi public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml b/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml index cf6413642c63..5cb6f4626b36 100644 --- a/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml +++ b/packages/SystemUI/res/drawable/privacy_item_circle_camera.xml @@ -21,16 +21,16 @@ > <shape android:shape="oval"> <size - android:height="28dp" - android:width="28dp" + android:height="@dimen/ongoing_appops_dialog_circle_size" + android:width="@dimen/ongoing_appops_dialog_circle_size" /> <solid android:color="@color/privacy_circle_camera" /> </shape> </item> <item android:id="@id/icon" android:gravity="center" - android:width="20dp" - android:height="20dp" + android:width="@dimen/ongoing_appops_dialog_icon_size" + android:height="@dimen/ongoing_appops_dialog_icon_size" android:drawable="@*android:drawable/perm_group_camera" /> </layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_location.xml b/packages/SystemUI/res/drawable/privacy_item_circle_location.xml index 0a6a4a31d0a5..28466c8a29b3 100644 --- a/packages/SystemUI/res/drawable/privacy_item_circle_location.xml +++ b/packages/SystemUI/res/drawable/privacy_item_circle_location.xml @@ -21,16 +21,16 @@ > <shape android:shape="oval"> <size - android:height="28dp" - android:width="28dp" + android:height="@dimen/ongoing_appops_dialog_circle_size" + android:width="@dimen/ongoing_appops_dialog_circle_size" /> <solid android:color="@color/privacy_circle_microphone_location" /> </shape> </item> <item android:id="@id/icon" android:gravity="center" - android:width="20dp" - android:height="20dp" + android:width="@dimen/ongoing_appops_dialog_icon_size" + android:height="@dimen/ongoing_appops_dialog_icon_size" android:drawable="@*android:drawable/perm_group_microphone" /> </layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml b/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml index 0a6a4a31d0a5..28466c8a29b3 100644 --- a/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml +++ b/packages/SystemUI/res/drawable/privacy_item_circle_microphone.xml @@ -21,16 +21,16 @@ > <shape android:shape="oval"> <size - android:height="28dp" - android:width="28dp" + android:height="@dimen/ongoing_appops_dialog_circle_size" + android:width="@dimen/ongoing_appops_dialog_circle_size" /> <solid android:color="@color/privacy_circle_microphone_location" /> </shape> </item> <item android:id="@id/icon" android:gravity="center" - android:width="20dp" - android:height="20dp" + android:width="@dimen/ongoing_appops_dialog_icon_size" + android:height="@dimen/ongoing_appops_dialog_icon_size" android:drawable="@*android:drawable/perm_group_microphone" /> </layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/privacy_dialog.xml b/packages/SystemUI/res/layout/privacy_dialog.xml index 5db247e25d50..4d77a0d75689 100644 --- a/packages/SystemUI/res/layout/privacy_dialog.xml +++ b/packages/SystemUI/res/layout/privacy_dialog.xml @@ -22,7 +22,13 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/ongoing_appops_dialog_side_margins" android:layout_marginEnd="@dimen/ongoing_appops_dialog_side_margins" + android:layout_marginTop="8dp" android:orientation="vertical" - android:padding = "8dp" + android:paddingLeft="@dimen/ongoing_appops_dialog_side_padding" + android:paddingRight="@dimen/ongoing_appops_dialog_side_padding" + android:paddingBottom="12dp" + android:paddingTop="8dp" android:background="@drawable/privacy_dialog_bg" -/>
\ No newline at end of file +/> +<!-- 12dp padding bottom so there's 20dp total under the icon --> +<!-- 8dp padding top, as there's 4dp margin in each row -->
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/privacy_dialog_item.xml b/packages/SystemUI/res/layout/privacy_dialog_item.xml index 882e9680407e..91ffe225fac6 100644 --- a/packages/SystemUI/res/layout/privacy_dialog_item.xml +++ b/packages/SystemUI/res/layout/privacy_dialog_item.xml @@ -16,19 +16,22 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/privacy_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="48dp" android:orientation="horizontal" - android:layout_marginTop="8dp" + android:layout_marginTop="4dp" + android:importantForAccessibility="yes" + android:focusable="true" > + <!-- 4dp marginTop makes 20dp minimum between icons --> <ImageView android:id="@+id/icon" - android:layout_width="24dp" - android:layout_height="24dp" + android:layout_width="@dimen/ongoing_appops_dialog_circle_size" + android:layout_height="@dimen/ongoing_appops_dialog_circle_size" android:layout_gravity="center_vertical" - android:layout_marginStart="12dp" - android:layout_marginEnd="12dp" + android:importantForAccessibility="no" /> <TextView @@ -38,25 +41,21 @@ android:layout_width="0dp" android:layout_weight="1" android:layout_gravity="center_vertical" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:textDirection="locale" + android:textAlignment="viewStart" android:gravity="start | center_vertical" - android:textAppearance="@style/TextAppearance.QS.TileLabel" + android:textAppearance="@style/TextAppearance.PrivacyDialog" + android:lineHeight="20sp" /> - <FrameLayout - android:id="@+id/link" - android:layout_width="48dp" - android:layout_height="48dp" + <ImageView + android:layout_height="24dp" + android:layout_width="24dp" android:layout_gravity="center_vertical" - android:background="?android:attr/selectableItemBackground" - > - - <ImageView - android:layout_height="24dp" - android:layout_width="24dp" - android:layout_gravity="center" - android:src="@*android:drawable/ic_chevron_end" - android:tint="?android:attr/textColorPrimary" - /> - </FrameLayout> + android:src="@*android:drawable/ic_chevron_end" + android:tint="?android:attr/textColorPrimary" + /> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index e5109307c4f4..1fac96bb181d 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1181,6 +1181,12 @@ <dimen name="ongoing_appops_dialog_side_margins">@dimen/notification_shade_content_margin_horizontal</dimen> + <dimen name="ongoing_appops_dialog_circle_size">32dp</dimen> + + <dimen name="ongoing_appops_dialog_icon_size">20dp</dimen> + + <dimen name="ongoing_appops_dialog_side_padding">16dp</dimen> + <!-- Size of the RAT type for CellularTile --> <dimen name="celltile_rat_type_size">10sp</dimen> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index db260ce1b7b4..ad4e78e8e507 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -745,4 +745,9 @@ * Title: headline, medium 20sp * Message: body, 16 sp --> <style name="Theme.ControlsRequestDialog" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert"/> + + <style name="TextAppearance.PrivacyDialog"> + <item name="android:textSize">14sp</item> + <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> + </style> </resources> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 9908e672535f..d9a1eb6c0b28 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1909,12 +1909,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } /** - * Whether to show the lock icon on lock screen and bouncer. This depends on the enrolled - * biometrics to the device. + * Whether to show the lock icon on lock screen and bouncer. */ - public boolean shouldShowLockIcon() { - return isFaceAuthEnabledForUser(KeyguardUpdateMonitor.getCurrentUser()) - && !isUdfpsEnrolled(); + public boolean canShowLockIcon() { + if (mLockScreenMode == LOCK_SCREEN_MODE_LAYOUT_1) { + return isFaceAuthEnabledForUser(KeyguardUpdateMonitor.getCurrentUser()) + && !isUdfpsEnrolled(); + } + return true; } /** diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt index 66c535f869f0..c3d6a848202f 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt @@ -24,7 +24,6 @@ import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.WindowInsets import android.widget.ImageView @@ -66,9 +65,8 @@ class PrivacyDialog( super.onCreate(savedInstanceState) window?.apply { attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars() - setLayout(MATCH_PARENT, WRAP_CONTENT) + setLayout(context.resources.getDimensionPixelSize(R.dimen.qs_panel_width), WRAP_CONTENT) setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL) - setBackgroundDrawable(null) } setContentView(R.layout.privacy_dialog) @@ -130,7 +128,7 @@ class PrivacyDialog( ) } ?: firstLine newView.requireViewById<TextView>(R.id.text).text = finalText - newView.requireViewById<View>(R.id.link).apply { + newView.apply { tag = element.type.permGroupName setOnClickListener(clickListener) } @@ -154,9 +152,7 @@ class PrivacyDialog( } private val clickListener = View.OnClickListener { v -> - if (v.id == R.id.link) { - v.tag?.let { activityStarter(it as String) } - } + v.tag?.let { activityStarter(it as String) } } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java index 1ec043cb7670..e4ae560ba69b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java @@ -23,8 +23,6 @@ import android.view.ViewGroup; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; -import com.android.systemui.statusbar.phone.LockIcon; -import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.StatusBarWindowView; @@ -41,7 +39,6 @@ public class SuperStatusBarViewFactory { private final Context mContext; private final InjectionInflationController mInjectionInflationController; - private final LockscreenLockIconController mLockIconController; private final NotificationShelfComponent.Builder mNotificationShelfComponentBuilder; private NotificationShadeWindowView mNotificationShadeWindowView; @@ -51,11 +48,9 @@ public class SuperStatusBarViewFactory { @Inject public SuperStatusBarViewFactory(Context context, InjectionInflationController injectionInflationController, - NotificationShelfComponent.Builder notificationShelfComponentBuilder, - LockscreenLockIconController lockIconController) { + NotificationShelfComponent.Builder notificationShelfComponentBuilder) { mContext = context; mInjectionInflationController = injectionInflationController; - mLockIconController = lockIconController; mNotificationShelfComponentBuilder = notificationShelfComponentBuilder; } @@ -77,10 +72,6 @@ public class SuperStatusBarViewFactory { throw new IllegalStateException( "R.layout.super_notification_shade could not be properly inflated"); } - LockIcon lockIcon = mNotificationShadeWindowView.findViewById(R.id.lock_icon); - if (lockIcon != null) { - mLockIconController.attach(lockIcon); - } return mNotificationShadeWindowView; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index e1eaf3c17357..f289b9f20211 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -71,7 +71,7 @@ public final class DozeServiceHost implements DozeHost { "persist.sysui.wake_performs_auth", true); private boolean mDozingRequested; private boolean mPulsing; - private WakefulnessLifecycle mWakefulnessLifecycle; + private final WakefulnessLifecycle mWakefulnessLifecycle; private final SysuiStatusBarStateController mStatusBarStateController; private final DeviceProvisionedController mDeviceProvisionedController; private final HeadsUpManagerPhone mHeadsUpManagerPhone; @@ -86,9 +86,8 @@ public final class DozeServiceHost implements DozeHost { private final NotificationShadeWindowController mNotificationShadeWindowController; private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator; private NotificationShadeWindowViewController mNotificationShadeWindowViewController; - private final LockscreenLockIconController mLockscreenLockIconController; private final AuthController mAuthController; - private NotificationIconAreaController mNotificationIconAreaController; + private final NotificationIconAreaController mNotificationIconAreaController; private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private NotificationPanelViewController mNotificationPanel; private View mAmbientIndicationContainer; @@ -109,7 +108,6 @@ public final class DozeServiceHost implements DozeHost { PulseExpansionHandler pulseExpansionHandler, NotificationShadeWindowController notificationShadeWindowController, NotificationWakeUpCoordinator notificationWakeUpCoordinator, - LockscreenLockIconController lockscreenLockIconController, AuthController authController, NotificationIconAreaController notificationIconAreaController) { super(); @@ -129,7 +127,6 @@ public final class DozeServiceHost implements DozeHost { mPulseExpansionHandler = pulseExpansionHandler; mNotificationShadeWindowController = notificationShadeWindowController; mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; - mLockscreenLockIconController = lockscreenLockIconController; mAuthController = authController; mNotificationIconAreaController = notificationIconAreaController; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java index eceac3240ebc..4b70de997906 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java @@ -37,12 +37,10 @@ import androidx.annotation.Nullable; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.Utils; import com.android.systemui.R; -import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -52,18 +50,20 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator.WakeUpListener; import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent; +import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.util.ViewController; import java.util.Optional; import javax.inject.Inject; -/** Controls the {@link LockIcon} in the lockscreen. */ -@SysUISingleton -public class LockscreenLockIconController { +/** Controls the {@link LockIcon} on the lockscreen. */ +@StatusBarComponent.StatusBarScope +public class LockscreenLockIconController extends ViewController<LockIcon> { private final LockscreenGestureLogger mLockscreenGestureLogger; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @@ -79,7 +79,6 @@ public class LockscreenLockIconController { private final KeyguardStateController mKeyguardStateController; private final Resources mResources; private final HeadsUpManagerPhone mHeadsUpManagerPhone; - private final KeyguardSecurityModel mKeyguardSecurityModel; private boolean mKeyguardShowing; private boolean mKeyguardJustShown; private boolean mBlockUpdates; @@ -92,231 +91,13 @@ public class LockscreenLockIconController { private boolean mBouncerShowingScrimmed; private boolean mFingerprintUnlock; private int mStatusBarState = StatusBarState.SHADE; - private LockIcon mLockIcon; - - private View.OnAttachStateChangeListener mOnAttachStateChangeListener = - new View.OnAttachStateChangeListener() { - @Override - public void onViewAttachedToWindow(View v) { - mStatusBarStateController.addCallback(mSBStateListener); - mConfigurationController.addCallback(mConfigurationListener); - mNotificationWakeUpCoordinator.addListener(mWakeUpListener); - mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback); - mKeyguardStateController.addCallback(mKeyguardMonitorCallback); - - mDockManager.ifPresent(dockManager -> dockManager.addListener(mDockEventListener)); - - mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure(); - mConfigurationListener.onThemeChanged(); - - updateColor(); - update(); - } - - @Override - public void onViewDetachedFromWindow(View v) { - mStatusBarStateController.removeCallback(mSBStateListener); - mConfigurationController.removeCallback(mConfigurationListener); - mNotificationWakeUpCoordinator.removeListener(mWakeUpListener); - mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); - mKeyguardStateController.removeCallback(mKeyguardMonitorCallback); - - mDockManager.ifPresent(dockManager -> dockManager.removeListener(mDockEventListener)); - } - }; - - private final StatusBarStateController.StateListener mSBStateListener = - new StatusBarStateController.StateListener() { - @Override - public void onDozingChanged(boolean isDozing) { - setDozing(isDozing); - } - - @Override - public void onDozeAmountChanged(float linear, float eased) { - if (mLockIcon != null) { - mLockIcon.setDozeAmount(eased); - } - } - - @Override - public void onStateChanged(int newState) { - setStatusBarState(newState); - } - }; - - private final ConfigurationListener mConfigurationListener = new ConfigurationListener() { - private int mDensity; - - @Override - public void onUiModeChanged() { - updateColor(); - } - - @Override - public void onOverlayChanged() { - updateColor(); - } - - @Override - public void onDensityOrFontScaleChanged() { - if (mLockIcon == null) { - return; - } - - ViewGroup.LayoutParams lp = mLockIcon.getLayoutParams(); - if (lp == null) { - return; - } - lp.width = mLockIcon.getResources().getDimensionPixelSize(R.dimen.keyguard_lock_width); - lp.height = mLockIcon.getResources().getDimensionPixelSize( - R.dimen.keyguard_lock_height); - mLockIcon.setLayoutParams(lp); - update(true /* force */); - } - - @Override - public void onLocaleListChanged() { - if (mLockIcon == null) { - return; - } - - mLockIcon.setContentDescription( - mLockIcon.getResources().getText(R.string.accessibility_unlock_button)); - update(true /* force */); - } - - @Override - public void onConfigChanged(Configuration newConfig) { - final int density = newConfig.densityDpi; - if (density != mDensity) { - mDensity = density; - update(); - } - } - }; - - private final WakeUpListener mWakeUpListener = new WakeUpListener() { - @Override - public void onPulseExpansionChanged(boolean expandingChanged) { - } - - @Override - public void onFullyHiddenChanged(boolean isFullyHidden) { - if (mKeyguardBypassController.getBypassEnabled()) { - boolean changed = updateIconVisibility(); - if (changed) { - update(); - } - } - } - }; - - private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = - new KeyguardUpdateMonitorCallback() { - @Override - public void onSimStateChanged(int subId, int slotId, int simState) { - mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure(); - update(); - } - - @Override - public void onKeyguardVisibilityChanged(boolean showing) { - update(); - } - - @Override - public void onBiometricRunningStateChanged(boolean running, - BiometricSourceType biometricSourceType) { - update(); - } - - @Override - public void onStrongAuthStateChanged(int userId) { - update(); - } - }; - - private final DockManager.DockEventListener mDockEventListener = - event -> { - boolean docked = - event == DockManager.STATE_DOCKED || event == DockManager.STATE_DOCKED_HIDE; - if (docked != mDocked) { - mDocked = docked; - update(); - } - }; - - private final KeyguardStateController.Callback mKeyguardMonitorCallback = - new KeyguardStateController.Callback() { - @Override - public void onKeyguardShowingChanged() { - boolean force = false; - boolean wasShowing = mKeyguardShowing; - mKeyguardShowing = mKeyguardStateController.isShowing(); - if (!wasShowing && mKeyguardShowing && mBlockUpdates) { - mBlockUpdates = false; - force = true; - } - if (!wasShowing && mKeyguardShowing) { - setBouncerHideAmount(KeyguardBouncer.EXPANSION_HIDDEN); - mKeyguardJustShown = true; - } - update(force); - } - - @Override - public void onKeyguardFadingAwayChanged() { - if (!mKeyguardStateController.isKeyguardFadingAway()) { - if (mBlockUpdates) { - mBlockUpdates = false; - update(true /* force */); - } - } - } - - @Override - public void onUnlockedChanged() { - update(); - } - }; - - private final View.AccessibilityDelegate mAccessibilityDelegate = - new View.AccessibilityDelegate() { - @Override - public void onInitializeAccessibilityNodeInfo(View host, - AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(host, info); - boolean fingerprintRunning = - mKeyguardUpdateMonitor.isFingerprintDetectionRunning(); - // Only checking if unlocking with Biometric is allowed (no matter strong or - // non-strong as long as primary auth, i.e. PIN/pattern/password, is not - // required), so it's ok to pass true for isStrongBiometric to - // isUnlockingWithBiometricAllowed() to bypass the check of whether non-strong - // biometric is allowed - boolean unlockingAllowed = mKeyguardUpdateMonitor - .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */); - if (fingerprintRunning && unlockingAllowed) { - AccessibilityNodeInfo.AccessibilityAction unlock = - new AccessibilityNodeInfo.AccessibilityAction( - AccessibilityNodeInfo.ACTION_CLICK, - mResources.getString( - R.string.accessibility_unlock_without_fingerprint)); - info.addAction(unlock); - info.setHintText(mResources.getString( - R.string.accessibility_waiting_for_fingerprint)); - } else if (getState() == STATE_SCANNING_FACE) { - //Avoid 'button' to be spoken for scanning face - info.setClassName(LockIcon.class.getName()); - info.setContentDescription(mResources.getString( - R.string.accessibility_scanning_face)); - } - } - }; private int mLastState; + private boolean mDozing; @Inject - public LockscreenLockIconController(LockscreenGestureLogger lockscreenGestureLogger, + public LockscreenLockIconController( + @Nullable LockIcon view, + LockscreenGestureLogger lockscreenGestureLogger, KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils, ShadeController shadeController, @@ -329,8 +110,8 @@ public class LockscreenLockIconController { @Nullable DockManager dockManager, KeyguardStateController keyguardStateController, @Main Resources resources, - HeadsUpManagerPhone headsUpManagerPhone, - KeyguardSecurityModel keyguardSecurityModel) { + HeadsUpManagerPhone headsUpManagerPhone) { + super(view); mLockscreenGestureLogger = lockscreenGestureLogger; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; @@ -345,32 +126,52 @@ public class LockscreenLockIconController { mKeyguardStateController = keyguardStateController; mResources = resources; mHeadsUpManagerPhone = headsUpManagerPhone; - mKeyguardSecurityModel = keyguardSecurityModel; + + if (view == null) { + return; + } mKeyguardIndicationController.setLockIconController(this); } - /** - * Associate the controller with a {@link LockIcon} - * - * TODO: change to an init method and inject the view. - */ - public void attach(LockIcon lockIcon) { - mLockIcon = lockIcon; - - mLockIcon.setOnClickListener(this::handleClick); - mLockIcon.setOnLongClickListener(this::handleLongClick); - mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate); - - if (mLockIcon.isAttachedToWindow()) { - mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon); + @Override + protected void onInit() { + if (mView == null) { + return; } - mLockIcon.addOnAttachStateChangeListener(mOnAttachStateChangeListener); + mView.setOnClickListener(this::handleClick); + mView.setOnLongClickListener(this::handleLongClick); + mView.setAccessibilityDelegate(mAccessibilityDelegate); + } + + @Override + protected void onViewAttached() { setStatusBarState(mStatusBarStateController.getState()); + mDozing = mStatusBarStateController.isDozing(); + mStatusBarStateController.addCallback(mSBStateListener); + mConfigurationController.addCallback(mConfigurationListener); + mNotificationWakeUpCoordinator.addListener(mWakeUpListener); + mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback); + mKeyguardStateController.addCallback(mKeyguardMonitorCallback); + + mDockManager.ifPresent(dockManager -> dockManager.addListener(mDockEventListener)); + + mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure(); + mConfigurationListener.onThemeChanged(); + + updateColor(); + update(); } - public LockIcon getView() { - return mLockIcon; + @Override + protected void onViewDetached() { + mStatusBarStateController.removeCallback(mSBStateListener); + mConfigurationController.removeCallback(mConfigurationListener); + mNotificationWakeUpCoordinator.removeListener(mWakeUpListener); + mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); + mKeyguardStateController.removeCallback(mKeyguardMonitorCallback); + + mDockManager.ifPresent(dockManager -> dockManager.removeListener(mDockEventListener)); } /** @@ -430,31 +231,30 @@ public class LockscreenLockIconController { } private void updateColor() { - if (mLockIcon == null) { + if (mView == null) { return; } - int iconColor = -1; if (mBouncerHiddenAmount == KeyguardBouncer.EXPANSION_VISIBLE) { - TypedArray typedArray = mLockIcon.getContext().getTheme().obtainStyledAttributes( + TypedArray typedArray = mView.getContext().getTheme().obtainStyledAttributes( null, new int[]{ android.R.attr.textColorPrimary }, 0, 0); iconColor = typedArray.getColor(0, Color.WHITE); typedArray.recycle(); } else if (mBouncerHiddenAmount == KeyguardBouncer.EXPANSION_HIDDEN) { iconColor = Utils.getColorAttrDefaultColor( - mLockIcon.getContext(), com.android.systemui.R.attr.wallpaperTextColor); + mView.getContext(), com.android.systemui.R.attr.wallpaperTextColor); } else { // bouncer is transitioning - TypedArray typedArray = mLockIcon.getContext().getTheme().obtainStyledAttributes( + TypedArray typedArray = mView.getContext().getTheme().obtainStyledAttributes( null, new int[]{ android.R.attr.textColorPrimary }, 0, 0); int bouncerIconColor = typedArray.getColor(0, Color.WHITE); typedArray.recycle(); int keyguardIconColor = Utils.getColorAttrDefaultColor( - mLockIcon.getContext(), com.android.systemui.R.attr.wallpaperTextColor); + mView.getContext(), com.android.systemui.R.attr.wallpaperTextColor); iconColor = (int) new ArgbEvaluator().evaluate( mBouncerHiddenAmount, bouncerIconColor, keyguardIconColor); } - mLockIcon.updateColor(iconColor); + mView.updateColor(iconColor); } /** @@ -497,14 +297,16 @@ public class LockscreenLockIconController { } private void update(boolean force) { + if (mView == null) { + return; + } int state = getState(); boolean shouldUpdate = mLastState != state || force; if (mBlockUpdates && canBlockUpdates()) { shouldUpdate = false; } - if (shouldUpdate && mLockIcon != null && mLockIcon.getVisibility() != GONE) { - mLockIcon.update(state, - mStatusBarStateController.isDozing(), mKeyguardJustShown); + if (shouldUpdate && mView.getVisibility() != GONE) { + mView.update(state, mDozing, mKeyguardJustShown); } mLastState = state; mKeyguardJustShown = false; @@ -531,10 +333,6 @@ public class LockscreenLockIconController { return mKeyguardShowing || mKeyguardStateController.isKeyguardFadingAway(); } - private void setDozing(boolean isDozing) { - update(); - } - /** Set the StatusBarState. */ private void setStatusBarState(int statusBarState) { mStatusBarState = statusBarState; @@ -546,17 +344,16 @@ public class LockscreenLockIconController { * @return true if the visibility changed */ private boolean updateIconVisibility() { - if (mLockIcon == null) { + if (mView == null) { return false; } - - if (!mKeyguardUpdateMonitor.shouldShowLockIcon()) { - boolean changed = mLockIcon.getVisibility() != GONE; - mLockIcon.setVisibility(GONE); + if (!mKeyguardUpdateMonitor.canShowLockIcon()) { + boolean changed = mView.getVisibility() != GONE; + mView.setVisibility(GONE); return changed; } - boolean onAodOrDocked = mStatusBarStateController.isDozing() || mDocked; + boolean onAodOrDocked = mDozing || mDocked; boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance; boolean fingerprintOrBypass = mFingerprintUnlock || mKeyguardBypassController.getBypassEnabled(); @@ -569,21 +366,202 @@ public class LockscreenLockIconController { invisible = true; } } - return mLockIcon.updateIconVisibility(!invisible); + return mView.updateIconVisibility(!invisible); } private void updateClickability() { - if (mAccessibilityController == null) { + if (mView == null) { return; } boolean canLock = mKeyguardStateController.isMethodSecure() && mKeyguardStateController.canDismissLockScreen(); boolean clickToUnlock = mAccessibilityController.isAccessibilityEnabled(); - if (mLockIcon != null) { - mLockIcon.setClickable(clickToUnlock); - mLockIcon.setLongClickable(canLock && !clickToUnlock); - mLockIcon.setFocusable(mAccessibilityController.isAccessibilityEnabled()); - } + mView.setClickable(clickToUnlock); + mView.setLongClickable(canLock && !clickToUnlock); + mView.setFocusable(mAccessibilityController.isAccessibilityEnabled()); } + private final StatusBarStateController.StateListener mSBStateListener = + new StatusBarStateController.StateListener() { + @Override + public void onDozingChanged(boolean isDozing) { + if (mDozing != isDozing) { + mDozing = isDozing; + update(); + } + } + + @Override + public void onDozeAmountChanged(float linear, float eased) { + if (mView != null) { + mView.setDozeAmount(eased); + } + } + + @Override + public void onStateChanged(int newState) { + setStatusBarState(newState); + } + }; + + private final ConfigurationListener mConfigurationListener = new ConfigurationListener() { + private int mDensity; + + @Override + public void onUiModeChanged() { + updateColor(); + } + + @Override + public void onOverlayChanged() { + updateColor(); + } + + @Override + public void onDensityOrFontScaleChanged() { + ViewGroup.LayoutParams lp = mView.getLayoutParams(); + if (lp == null) { + return; + } + lp.width = mView.getResources().getDimensionPixelSize(R.dimen.keyguard_lock_width); + lp.height = mView.getResources().getDimensionPixelSize( + R.dimen.keyguard_lock_height); + mView.setLayoutParams(lp); + update(true /* force */); + } + + @Override + public void onLocaleListChanged() { + mView.setContentDescription( + mView.getResources().getText(R.string.accessibility_unlock_button)); + update(true /* force */); + } + + @Override + public void onConfigChanged(Configuration newConfig) { + final int density = newConfig.densityDpi; + if (density != mDensity) { + mDensity = density; + update(); + } + } + }; + + private final WakeUpListener mWakeUpListener = new WakeUpListener() { + @Override + public void onPulseExpansionChanged(boolean expandingChanged) { + } + + @Override + public void onFullyHiddenChanged(boolean isFullyHidden) { + if (mKeyguardBypassController.getBypassEnabled()) { + boolean changed = updateIconVisibility(); + if (changed) { + update(); + } + } + } + }; + + private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = + new KeyguardUpdateMonitorCallback() { + @Override + public void onSimStateChanged(int subId, int slotId, int simState) { + mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure(); + update(); + } + + @Override + public void onKeyguardVisibilityChanged(boolean showing) { + update(); + } + + @Override + public void onBiometricRunningStateChanged(boolean running, + BiometricSourceType biometricSourceType) { + update(); + } + + @Override + public void onStrongAuthStateChanged(int userId) { + update(); + } + }; + + private final DockManager.DockEventListener mDockEventListener = + event -> { + boolean docked = + event == DockManager.STATE_DOCKED || event == DockManager.STATE_DOCKED_HIDE; + if (docked != mDocked) { + mDocked = docked; + update(); + } + }; + + private final KeyguardStateController.Callback mKeyguardMonitorCallback = + new KeyguardStateController.Callback() { + @Override + public void onKeyguardShowingChanged() { + boolean force = false; + boolean wasShowing = mKeyguardShowing; + mKeyguardShowing = mKeyguardStateController.isShowing(); + if (!wasShowing && mKeyguardShowing && mBlockUpdates) { + mBlockUpdates = false; + force = true; + } + if (!wasShowing && mKeyguardShowing) { + setBouncerHideAmount(KeyguardBouncer.EXPANSION_HIDDEN); + mKeyguardJustShown = true; + } + update(force); + } + + @Override + public void onKeyguardFadingAwayChanged() { + if (!mKeyguardStateController.isKeyguardFadingAway()) { + if (mBlockUpdates) { + mBlockUpdates = false; + update(true /* force */); + } + } + } + + @Override + public void onUnlockedChanged() { + update(); + } + }; + + private final View.AccessibilityDelegate mAccessibilityDelegate = + new View.AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo(View host, + AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + boolean fingerprintRunning = + mKeyguardUpdateMonitor.isFingerprintDetectionRunning(); + // Only checking if unlocking with Biometric is allowed (no matter strong or + // non-strong as long as primary auth, i.e. PIN/pattern/password, is not + // required), so it's ok to pass true for isStrongBiometric to + // isUnlockingWithBiometricAllowed() to bypass the check of whether non-strong + // biometric is allowed + boolean unlockingAllowed = mKeyguardUpdateMonitor + .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */); + if (fingerprintRunning && unlockingAllowed) { + AccessibilityNodeInfo.AccessibilityAction unlock = + new AccessibilityNodeInfo.AccessibilityAction( + AccessibilityNodeInfo.ACTION_CLICK, + mResources.getString( + R.string.accessibility_unlock_without_fingerprint)); + info.addAction(unlock); + info.setHintText(mResources.getString( + R.string.accessibility_waiting_for_fingerprint)); + } else if (getState() == STATE_SCANNING_FACE) { + //Avoid 'button' to be spoken for scanning face + info.setClassName(LockIcon.class.getName()); + info.setContentDescription(mResources.getString( + R.string.accessibility_scanning_face)); + } + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index b24d0e7762ad..a5284f1421a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -910,7 +910,7 @@ public class NotificationPanelViewController extends PanelViewController { clockPreferredY, hasCustomClock(), hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount, bypassEnabled, getUnlockedStackScrollerPadding(), - mUpdateMonitor.shouldShowLockIcon(), + mUpdateMonitor.canShowLockIcon(), getQsExpansionFraction(), mDisplayCutoutTopInset); mClockPositionAlgorithm.run(mClockPositionResult); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 83651398be43..4a3d8d67e85d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -368,7 +368,6 @@ public class StatusBar extends SystemUI implements DemoMode, protected NotificationShadeWindowController mNotificationShadeWindowController; protected StatusBarWindowController mStatusBarWindowController; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final LockscreenLockIconController mLockscreenLockIconController; @VisibleForTesting DozeServiceHost mDozeServiceHost; private boolean mWakeUpComingFromTouch; @@ -415,6 +414,7 @@ public class StatusBar extends SystemUI implements DemoMode, // expanded notifications // the sliding/resizing panel within the notification window protected NotificationPanelViewController mNotificationPanelViewController; + protected LockscreenLockIconController mLockscreenLockIconController; // settings private QSPanelController mQSPanelController; @@ -725,7 +725,6 @@ public class StatusBar extends SystemUI implements DemoMode, Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, NotificationShadeWindowController notificationShadeWindowController, - LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, @Nullable KeyguardLiftController keyguardLiftController, @@ -807,7 +806,6 @@ public class StatusBar extends SystemUI implements DemoMode, mAssistManagerLazy = assistManagerLazy; mConfigurationController = configurationController; mNotificationShadeWindowController = notificationShadeWindowController; - mLockscreenLockIconController = lockscreenLockIconController; mDozeServiceHost = dozeServiceHost; mPowerManager = powerManager; mDozeParameters = dozeParameters; @@ -1173,9 +1171,7 @@ public class StatusBar extends SystemUI implements DemoMode, mScrimController.setScrimVisibleListener(scrimsVisible -> { mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible); - if (mNotificationShadeWindowView != null) { - mLockscreenLockIconController.onScrimVisibilityChanged(scrimsVisible); - } + mLockscreenLockIconController.onScrimVisibilityChanged(scrimsVisible); }); mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble); @@ -1208,9 +1204,6 @@ public class StatusBar extends SystemUI implements DemoMode, createUserSwitcher(); } - mNotificationPanelViewController.setLaunchAffordanceListener( - mLockscreenLockIconController::onShowingLaunchAffordanceChanged); - // Set up the quick settings tile panel final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame); if (container != null) { @@ -1490,6 +1483,11 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarWindowController = statusBarComponent.getStatusBarWindowController(); mPhoneStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView(); mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController(); + mLockscreenLockIconController = statusBarComponent.getLockscreenLockIconController(); + mLockscreenLockIconController.init(); + + mNotificationPanelViewController.setLaunchAffordanceListener( + mLockscreenLockIconController::onShowingLaunchAffordanceChanged); } protected void startKeyguard() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java index 802da3e8c21c..ecd9613f84b2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone.dagger; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController; @@ -73,4 +74,9 @@ public interface StatusBarComponent { @StatusBarScope NotificationPanelViewController getNotificationPanelViewController(); + /** + * Creates a LockscreenLockIconController. + */ + @StatusBarScope + LockscreenLockIconController getLockscreenLockIconController(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 26e19596b577..9e9533d0e199 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -77,7 +77,6 @@ import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.phone.KeyguardLiftController; import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LightsOutNotifController; -import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; @@ -167,7 +166,6 @@ public interface StatusBarPhoneModule { Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, NotificationShadeWindowController notificationShadeWindowController, - LockscreenLockIconController lockscreenLockIconController, DozeParameters dozeParameters, ScrimController scrimController, @Nullable KeyguardLiftController keyguardLiftController, @@ -248,7 +246,6 @@ public interface StatusBarPhoneModule { assistManagerLazy, configurationController, notificationShadeWindowController, - lockscreenLockIconController, dozeParameters, scrimController, keyguardLiftController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 37d8c9ae2958..781abe6cef3e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -16,6 +16,10 @@ package com.android.systemui.statusbar.phone.dagger; +import android.annotation.Nullable; + +import com.android.systemui.R; +import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; @@ -32,4 +36,12 @@ public abstract class StatusBarViewModule { return notificationShadeWindowView.getNotificationPanelView(); } + /** */ + @Provides + @StatusBarComponent.StatusBarScope + @Nullable + public static LockIcon getLockIcon( + NotificationShadeWindowView notificationShadeWindowView) { + return notificationShadeWindowView.findViewById(R.id.lock_icon); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt index 9762ffffb02e..eb5dd4e6fef6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt @@ -72,7 +72,7 @@ class PrivacyDialogTest : SysuiTestCase() { ) dialog = PrivacyDialog(context, list, starter) dialog.show() - dialog.requireViewById<View>(R.id.link).callOnClick() + dialog.requireViewById<View>(R.id.privacy_item).callOnClick() verify(starter).invoke(PrivacyType.TYPE_MICROPHONE.permGroupName) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java index 23c093033ae0..bdde82289e86 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java @@ -88,7 +88,6 @@ public class DozeServiceHostTest extends SysuiTestCase { @Mock private NotificationPanelViewController mNotificationPanel; @Mock private View mAmbientIndicationContainer; @Mock private BiometricUnlockController mBiometricUnlockController; - @Mock private LockscreenLockIconController mLockscreenLockIconController; @Mock private AuthController mAuthController; @Before @@ -100,7 +99,7 @@ public class DozeServiceHostTest extends SysuiTestCase { mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController, mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController, mNotificationWakeUpCoordinator, - mLockscreenLockIconController, mAuthController, mNotificationIconAreaController); + mAuthController, mNotificationIconAreaController); mDozeServiceHost.initialize( mStatusBar, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java index 95a35050c09e..60af16acbb7e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.phone; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -30,12 +29,12 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.KeyguardIndicationController; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -45,6 +44,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -64,7 +64,7 @@ public class LockscreenIconControllerTest extends SysuiTestCase { @Mock private KeyguardIndicationController mKeyguardIndicationController; @Mock - private LockIcon mLockIcon; // TODO: make this not a mock once inject is removed. + private LockIcon mLockIcon; @Mock private StatusBarStateController mStatusBarStateController; @Mock @@ -81,34 +81,36 @@ public class LockscreenIconControllerTest extends SysuiTestCase { private Resources mResources; @Mock private HeadsUpManagerPhone mHeadsUpManagerPhone; - @Mock - private KeyguardSecurityModel mKeyguardSecurityModel; private LockscreenLockIconController mLockIconController; + + @Captor ArgumentCaptor<OnAttachStateChangeListener> mOnAttachStateChangeCaptor; + @Captor ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerCaptor; + private OnAttachStateChangeListener mOnAttachStateChangeListener; + private StatusBarStateController.StateListener mStatusBarStateListener; @Before public void setUp() { MockitoAnnotations.initMocks(this); - when(mKeyguardUpdateMonitor.shouldShowLockIcon()).thenReturn(true); + when(mKeyguardUpdateMonitor.canShowLockIcon()).thenReturn(true); when(mLockIcon.getContext()).thenReturn(mContext); - mLockIconController = new LockscreenLockIconController( + mLockIconController = new LockscreenLockIconController(mLockIcon, mLockscreenGestureLogger, mKeyguardUpdateMonitor, mLockPatternUtils, mShadeController, mAccessibilityController, mKeyguardIndicationController, mStatusBarStateController, mConfigurationController, mNotificationWakeUpCoordinator, mKeyguardBypassController, mDockManager, mKeyguardStateController, mResources, - mHeadsUpManagerPhone, mKeyguardSecurityModel); + mHeadsUpManagerPhone); - ArgumentCaptor<OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor = - ArgumentCaptor.forClass(OnAttachStateChangeListener.class); + when(mLockIcon.isAttachedToWindow()).thenReturn(true); + mLockIconController.init(); - doNothing().when(mLockIcon) - .addOnAttachStateChangeListener( - onAttachStateChangeListenerArgumentCaptor.capture()); - mLockIconController.attach(mLockIcon); - - mOnAttachStateChangeListener = onAttachStateChangeListenerArgumentCaptor.getValue(); + verify(mLockIcon).addOnAttachStateChangeListener( + mOnAttachStateChangeCaptor.capture()); + mOnAttachStateChangeListener = mOnAttachStateChangeCaptor.getValue(); + verify(mStatusBarStateController).addCallback(mStateListenerCaptor.capture()); + mStatusBarStateListener = mStateListenerCaptor.getValue(); } @Test @@ -133,23 +135,17 @@ public class LockscreenIconControllerTest extends SysuiTestCase { @Test public void testVisibility_Dozing() { - ArgumentCaptor<StatusBarStateController.StateListener> sBStateListenerCaptor = - ArgumentCaptor.forClass(StatusBarStateController.StateListener.class); - - mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon); - verify(mStatusBarStateController).addCallback(sBStateListenerCaptor.capture()); - when(mStatusBarStateController.isDozing()).thenReturn(true); - sBStateListenerCaptor.getValue().onDozingChanged(true); + mStatusBarStateListener.onDozingChanged(true); verify(mLockIcon).updateIconVisibility(false); } @Test public void testVisibility_doNotShowLockIcon() { - when(mKeyguardUpdateMonitor.shouldShowLockIcon()).thenReturn(false); + when(mKeyguardUpdateMonitor.canShowLockIcon()).thenReturn(false); + mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); - mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon); verify(mLockIcon).setVisibility(View.GONE); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 2c781bad10c2..cae488a561a2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -386,7 +386,6 @@ public class StatusBarTest extends SysuiTestCase { () -> mAssistManager, configurationController, mNotificationShadeWindowController, - mLockscreenLockIconController, mDozeParameters, mScrimController, mKeyguardLiftController, @@ -436,6 +435,7 @@ public class StatusBarTest extends SysuiTestCase { // initialized automatically. mStatusBar.mNotificationShadeWindowView = mNotificationShadeWindowView; mStatusBar.mNotificationPanelViewController = mNotificationPanelViewController; + mStatusBar.mLockscreenLockIconController = mLockscreenLockIconController; mStatusBar.mDozeScrimController = mDozeScrimController; mStatusBar.mPresenter = mNotificationPresenter; mStatusBar.mKeyguardIndicationController = mKeyguardIndicationController; diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java index dbad8b364270..a725dd34fbf6 100644 --- a/services/core/java/com/android/server/wm/CompatModePackages.java +++ b/services/core/java/com/android/server/wm/CompatModePackages.java @@ -24,6 +24,9 @@ import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; import android.app.ActivityManager; import android.app.AppGlobals; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.Disabled; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.res.CompatibilityInfo; @@ -32,6 +35,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.os.UserHandle; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseArray; @@ -63,6 +67,58 @@ public final class CompatModePackages { // Compatibility state: compatibility mode is enabled. private static final int COMPAT_FLAG_ENABLED = 1<<1; + /** + * CompatModePackages#DOWNSCALED is the gatekeeper of all per-app buffer downscaling + * changes. Disabling this change will prevent the following scaling factors from working: + * CompatModePackages#DOWNSCALE_87_5 + * CompatModePackages#DOWNSCALE_75 + * CompatModePackages#DOWNSCALE_62_5 + * CompatModePackages#DOWNSCALE_50 + * + * If CompatModePackages#DOWNSCALED is enabled for an app package, then the app will be forcibly + * resized to the highest enabled scaling factor e.g. 87.5% if both 87.5% and 75% were + * enabled. + */ + @ChangeId + @Disabled + private static final long DOWNSCALED = 168419799L; + + /** + * With CompatModePackages#DOWNSCALED enabled, subsequently enabling change-id + * CompatModePackages#DOWNSCALE_87_5 for a package will force the app to assume it's + * running on a display with 87.5% the vertical and horizontal resolution of the real display. + */ + @ChangeId + @Disabled + private static final long DOWNSCALE_87_5 = 176926753L; + + /** + * With CompatModePackages#DOWNSCALED enabled, subsequently enabling change-id + * CompatModePackages#DOWNSCALE_75 for a package will force the app to assume it's + * running on a display with 75% the vertical and horizontal resolution of the real display. + */ + @ChangeId + @Disabled + private static final long DOWNSCALE_75 = 176926829L; + + /** + * With CompatModePackages#DOWNSCALED enabled, subsequently enabling change-id + * CompatModePackages#DOWNSCALE_62_5 for a package will force the app to assume it's + * running on a display with 62.5% the vertical and horizontal resolution of the real display. + */ + @ChangeId + @Disabled + private static final long DOWNSCALE_62_5 = 176926771L; + + /** + * With CompatModePackages#DOWNSCALED enabled, subsequently enabling change-id + * CompatModePackages#DOWNSCALE_50 for a package will force the app to assume it's + * running on a display with 50% vertical and horizontal resolution of the real display. + */ + @ChangeId + @Disabled + private static final long DOWNSCALE_50 = 176926741L; + private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>(); private static final int MSG_WRITE = 300; @@ -191,11 +247,39 @@ public final class CompatModePackages { mHandler.sendMessageDelayed(msg, 10000); } + float getCompatScale(String packageName, int uid) { + if (!CompatChanges.isChangeEnabled( + DOWNSCALED, packageName, UserHandle.getUserHandleForUid(uid))) { + return 1f; + } + if (CompatChanges.isChangeEnabled( + DOWNSCALE_87_5, packageName, UserHandle.getUserHandleForUid(uid))) { + // 8/7 == (1 / 0.875) ~= 1.14285714286 + return 8f / 7f; + } + if (CompatChanges.isChangeEnabled( + DOWNSCALE_75, packageName, UserHandle.getUserHandleForUid(uid))) { + // 4/3 == (1 / 0.75) ~= 1.333333333 + return 4f / 3f; + } + if (CompatChanges.isChangeEnabled( + DOWNSCALE_62_5, packageName, UserHandle.getUserHandleForUid(uid))) { + // (1 / 0.625) == 1.6 + return 1.6f; + } + if (CompatChanges.isChangeEnabled( + DOWNSCALE_50, packageName, UserHandle.getUserHandleForUid(uid))) { + return 2f; + } + return 1f; + } + public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) { final Configuration globalConfig = mService.getGlobalConfiguration(); + final float requestedScale = getCompatScale(ai.packageName, ai.uid); CompatibilityInfo ci = new CompatibilityInfo(ai, globalConfig.screenLayout, globalConfig.smallestScreenWidthDp, - (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0); + (getPackageFlags(ai.packageName) & COMPAT_FLAG_ENABLED) != 0, requestedScale); //Slog.i(TAG, "*********** COMPAT FOR PKG " + ai.packageName + ": " + ci); return ci; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index f2be5ffb2ab2..025037688c8c 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -441,6 +441,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP float mGlobalScale=1; float mLastGlobalScale=1; float mInvGlobalScale=1; + float mOverrideScale = 1; float mHScale=1, mVScale=1; float mLastHScale=1, mLastVScale=1; final Matrix mTmpMatrix = new Matrix(); @@ -1014,6 +1015,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mLastRequestedWidth = 0; mLastRequestedHeight = 0; mLayer = 0; + mOverrideScale = mWmService.mAtmService.mCompatModePackages.getCompatScale( + mAttrs.packageName, s.mUid); // Make sure we initial all fields before adding to parentWindow, to prevent exception // during onDisplayChanged. @@ -1046,8 +1049,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mSession.windowAddedLocked(mAttrs.packageName); } + /** + * @return {@code true} if the application runs in size compatibility mode or has an app level + * scaling override set. + * @see CompatModePackages#getCompatScale + * @see android.content.res.CompatibilityInfo#supportsScreen + * @see ActivityRecord#inSizeCompatMode() + */ boolean inSizeCompatMode() { - return inSizeCompatMode(mAttrs, mActivityRecord); + return mOverrideScale != 1f || inSizeCompatMode(mAttrs, mActivityRecord); } /** @@ -1682,7 +1692,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void prelayout() { if (inSizeCompatMode()) { - mGlobalScale = mToken.getSizeCompatScale(); + if (mOverrideScale != 1f) { + mGlobalScale = mToken.hasSizeCompatBounds() + ? mToken.getSizeCompatScale() * mOverrideScale + : mOverrideScale; + } else { + mGlobalScale = mToken.getSizeCompatScale(); + } mInvGlobalScale = 1 / mGlobalScale; } else { mGlobalScale = mInvGlobalScale = 1; @@ -2640,8 +2656,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // scaling but the existing logic doesn't expect that. The result is that the already- // scaled region ends up getting sent to surfaceflinger which then applies the scale // (again). Until this is resolved, apply an inverse-scale here. - if (mActivityRecord != null && mActivityRecord.hasSizeCompatBounds() - && mGlobalScale != 1.f) { + if (mInvGlobalScale != 1.f) { region.scale(mInvGlobalScale); } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt index ba12fbed2b2f..6b6d21bc6e54 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt @@ -21,9 +21,12 @@ import com.android.server.wm.flicker.dsl.EventLogAssertionBuilder import com.android.server.wm.flicker.dsl.LayersAssertionBuilder import com.android.server.wm.flicker.dsl.WmAssertionBuilder import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.NAV_BAR_LAYER_NAME +import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.NAV_BAR_WINDOW_NAME +import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.STATUS_BAR_LAYER_NAME +import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.STATUS_BAR_WINDOW_NAME -const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar" -const val STATUS_BAR_WINDOW_TITLE = "StatusBar" +const val APP_PAIR_SPLIT_DIVIDER = "AppPairSplitDivider" const val DOCKED_STACK_DIVIDER = "DockedStackDivider" const val WALLPAPER_TITLE = "Wallpaper" @@ -33,7 +36,7 @@ fun WmAssertionBuilder.statusBarWindowIsAlwaysVisible( enabled: Boolean = bugId == 0 ) { all("statusBarWindowIsAlwaysVisible", bugId, enabled) { - this.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE) + this.showsAboveAppWindow(STATUS_BAR_WINDOW_NAME) } } @@ -43,7 +46,7 @@ fun WmAssertionBuilder.navBarWindowIsAlwaysVisible( enabled: Boolean = bugId == 0 ) { all("navBarWindowIsAlwaysVisible", bugId, enabled) { - this.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE) + this.showsAboveAppWindow(NAV_BAR_WINDOW_NAME) } } @@ -113,6 +116,18 @@ fun WmAssertionBuilder.appWindowBecomesVisible( } } +fun WmAssertionBuilder.appWindowBecomesInVisible( + appName: String, + bugId: Int = 0, + enabled: Boolean = bugId == 0 +) { + all("appWindowBecomesInVisible", bugId, enabled) { + this.showsAppWindow(appName) + .then() + .hidesAppWindow(appName) + } +} + @JvmOverloads fun LayersAssertionBuilder.noUncoveredRegions( beginRotation: Int, @@ -151,15 +166,15 @@ fun LayersAssertionBuilder.navBarLayerIsAlwaysVisible( ) { if (rotatesScreen) { all("navBarLayerIsAlwaysVisible", bugId, enabled) { - this.showsLayer(NAVIGATION_BAR_WINDOW_TITLE) + this.showsLayer(NAV_BAR_LAYER_NAME) .then() - .hidesLayer(NAVIGATION_BAR_WINDOW_TITLE) + .hidesLayer(NAV_BAR_LAYER_NAME) .then() - .showsLayer(NAVIGATION_BAR_WINDOW_TITLE) + .showsLayer(NAV_BAR_LAYER_NAME) } } else { all("navBarLayerIsAlwaysVisible", bugId, enabled) { - this.showsLayer(NAVIGATION_BAR_WINDOW_TITLE) + this.showsLayer(NAV_BAR_LAYER_NAME) } } } @@ -172,15 +187,15 @@ fun LayersAssertionBuilder.statusBarLayerIsAlwaysVisible( ) { if (rotatesScreen) { all("statusBarLayerIsAlwaysVisible", bugId, enabled) { - this.showsLayer(STATUS_BAR_WINDOW_TITLE) + this.showsLayer(STATUS_BAR_LAYER_NAME) .then() - hidesLayer(STATUS_BAR_WINDOW_TITLE) + hidesLayer(STATUS_BAR_LAYER_NAME) .then() - .showsLayer(STATUS_BAR_WINDOW_TITLE) + .showsLayer(STATUS_BAR_LAYER_NAME) } } else { all("statusBarLayerIsAlwaysVisible", bugId, enabled) { - this.showsLayer(STATUS_BAR_WINDOW_TITLE) + this.showsLayer(STATUS_BAR_LAYER_NAME) } } } @@ -196,15 +211,15 @@ fun LayersAssertionBuilder.navBarLayerRotatesAndScales( val endingPos = WindowUtils.getNavigationBarPosition(endRotation) start("navBarLayerRotatesAndScales_StartingPos", bugId, enabled) { - this.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos) + this.hasVisibleRegion(NAV_BAR_LAYER_NAME, startingPos) } end("navBarLayerRotatesAndScales_EndingPost", bugId, enabled) { - this.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, endingPos) + this.hasVisibleRegion(NAV_BAR_LAYER_NAME, endingPos) } if (startingPos == endingPos) { all("navBarLayerRotatesAndScales", enabled = false, bugId = 167747321) { - this.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos) + this.hasVisibleRegion(NAV_BAR_LAYER_NAME, startingPos) } } } @@ -220,10 +235,10 @@ fun LayersAssertionBuilder.statusBarLayerRotatesScales( val endingPos = WindowUtils.getStatusBarPosition(endRotation) start("statusBarLayerRotatesScales_StartingPos", bugId, enabled) { - this.hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, startingPos) + this.hasVisibleRegion(STATUS_BAR_LAYER_NAME, startingPos) } end("statusBarLayerRotatesScales_EndingPos", bugId, enabled) { - this.hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, endingPos) + this.hasVisibleRegion(STATUS_BAR_LAYER_NAME, endingPos) } } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt index b569edac1a95..1a4744980b1e 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt @@ -41,6 +41,9 @@ fun Flicker.setRotation(rotation: Int) { wmHelper.waitForRotation(rotation) wmHelper.waitForNavBarStatusBarVisible() wmHelper.waitForAppTransitionIdle() + + // Ensure WindowManagerService wait until all animations have completed + instrumentation.getUiAutomation().syncInputTransactions() } catch (e: RemoteException) { throw RuntimeException(e) } diff --git a/tests/net/Android.bp b/tests/net/Android.bp index f6a2846c9b3c..e630da04a512 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -53,6 +53,7 @@ android_test { jarjar_rules: "jarjar-rules.txt", static_libs: [ "androidx.test.rules", + "bouncycastle-repackaged-unbundled", "FrameworksNetCommonTests", "frameworks-base-testutils", "frameworks-net-integration-testutils", diff --git a/tests/net/java/android/net/Ikev2VpnProfileTest.java b/tests/net/java/android/net/Ikev2VpnProfileTest.java index 076e41d33a8d..1abd39a32bdf 100644 --- a/tests/net/java/android/net/Ikev2VpnProfileTest.java +++ b/tests/net/java/android/net/Ikev2VpnProfileTest.java @@ -30,7 +30,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.net.VpnProfile; import com.android.net.module.util.ProxyUtils; -import com.android.org.bouncycastle.x509.X509V1CertificateGenerator; +import com.android.internal.org.bouncycastle.x509.X509V1CertificateGenerator; import org.junit.Before; import org.junit.Test; |