diff options
44 files changed, 703 insertions, 337 deletions
diff --git a/api/current.txt b/api/current.txt index b274bff20f5a..968811d85d31 100644 --- a/api/current.txt +++ b/api/current.txt @@ -38407,14 +38407,12 @@ package android.provider { public final class MediaStore { ctor public MediaStore(); - method @NonNull public static android.net.Uri createPending(@NonNull android.content.Context, @NonNull android.provider.MediaStore.PendingParams); method @NonNull public static java.util.Set<java.lang.String> getAllVolumeNames(android.content.Context); method public static android.net.Uri getDocumentUri(android.content.Context, android.net.Uri); method public static android.net.Uri getMediaScannerUri(); method public static android.net.Uri getMediaUri(android.content.Context, android.net.Uri); method public static String getVersion(android.content.Context); method @NonNull public static String getVolumeName(@NonNull android.net.Uri); - method @NonNull public static android.provider.MediaStore.PendingSession openPending(@NonNull android.content.Context, @NonNull android.net.Uri); method @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri); method @NonNull public static android.net.Uri setRequireOriginal(@NonNull android.net.Uri); field public static final String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE"; @@ -38687,6 +38685,7 @@ package android.provider { public static interface MediaStore.MediaColumns extends android.provider.BaseColumns { field @Deprecated public static final String DATA = "_data"; field public static final String DATE_ADDED = "date_added"; + field public static final String DATE_EXPIRES = "date_expires"; field public static final String DATE_MODIFIED = "date_modified"; field public static final String DISPLAY_NAME = "_display_name"; field public static final String DOCUMENT_ID = "document_id"; @@ -38703,23 +38702,6 @@ package android.provider { field public static final String WIDTH = "width"; } - public static class MediaStore.PendingParams { - ctor public MediaStore.PendingParams(@NonNull android.net.Uri, @NonNull String, @NonNull String); - method public void setDownloadUri(@Nullable android.net.Uri); - method public void setPrimaryDirectory(@Nullable String); - method public void setRefererUri(@Nullable android.net.Uri); - method public void setSecondaryDirectory(@Nullable String); - } - - public static class MediaStore.PendingSession implements java.lang.AutoCloseable { - method public void abandon(); - method public void close(); - method public void notifyProgress(@IntRange(from=0, to=100) int); - method @NonNull public android.os.ParcelFileDescriptor open() throws java.io.FileNotFoundException; - method @NonNull public java.io.OutputStream openOutputStream() throws java.io.FileNotFoundException; - method @NonNull public android.net.Uri publish(); - } - public static final class MediaStore.Video { ctor public MediaStore.Video(); method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]); @@ -50520,6 +50502,7 @@ package android.view { method public android.animation.StateListAnimator getStateListAnimator(); method protected int getSuggestedMinimumHeight(); method protected int getSuggestedMinimumWidth(); + method @NonNull public java.util.List<android.graphics.Rect> getSystemGestureExclusionRects(); method public int getSystemUiVisibility(); method @android.view.ViewDebug.ExportedProperty public Object getTag(); method public Object getTag(int); @@ -50858,6 +50841,7 @@ package android.view { method public void setSelected(boolean); method public void setSoundEffectsEnabled(boolean); method public void setStateListAnimator(android.animation.StateListAnimator); + method public void setSystemGestureExclusionRects(@NonNull java.util.List<android.graphics.Rect>); method public void setSystemUiVisibility(int); method public void setTag(Object); method public void setTag(int, Object); @@ -51686,6 +51670,7 @@ package android.view { method public void addOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void addOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener); method public void addOnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener); + method public void addOnSystemGestureExclusionRectsChangedListener(java.util.function.Consumer<java.util.List<android.graphics.Rect>>); method public void addOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener); method public void addOnWindowAttachListener(android.view.ViewTreeObserver.OnWindowAttachListener); method public void addOnWindowFocusChangeListener(android.view.ViewTreeObserver.OnWindowFocusChangeListener); @@ -51700,6 +51685,7 @@ package android.view { method public void removeOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void removeOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener); method public void removeOnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener); + method public void removeOnSystemGestureExclusionRectsChangedListener(java.util.function.Consumer<java.util.List<android.graphics.Rect>>); method public void removeOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener); method public void removeOnWindowAttachListener(android.view.ViewTreeObserver.OnWindowAttachListener); method public void removeOnWindowFocusChangeListener(android.view.ViewTreeObserver.OnWindowFocusChangeListener); @@ -57778,16 +57764,16 @@ package android.widget { method @Deprecated public void onZoom(boolean); } - public class ZoomControls extends android.widget.LinearLayout { - ctor public ZoomControls(android.content.Context); - ctor public ZoomControls(android.content.Context, android.util.AttributeSet); - method public void hide(); - method public void setIsZoomInEnabled(boolean); - method public void setIsZoomOutEnabled(boolean); - method public void setOnZoomInClickListener(android.view.View.OnClickListener); - method public void setOnZoomOutClickListener(android.view.View.OnClickListener); - method public void setZoomSpeed(long); - method public void show(); + @Deprecated public class ZoomControls extends android.widget.LinearLayout { + ctor @Deprecated public ZoomControls(android.content.Context); + ctor @Deprecated public ZoomControls(android.content.Context, android.util.AttributeSet); + method @Deprecated public void hide(); + method @Deprecated public void setIsZoomInEnabled(boolean); + method @Deprecated public void setIsZoomOutEnabled(boolean); + method @Deprecated public void setOnZoomInClickListener(android.view.View.OnClickListener); + method @Deprecated public void setOnZoomOutClickListener(android.view.View.OnClickListener); + method @Deprecated public void setZoomSpeed(long); + method @Deprecated public void show(); } } diff --git a/api/removed.txt b/api/removed.txt index c4ed871d0661..40b1316a2a5d 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -508,6 +508,8 @@ package android.provider { } public final class MediaStore { + method @Deprecated @NonNull public static android.net.Uri createPending(@NonNull android.content.Context, @NonNull android.provider.MediaStore.PendingParams); + method @Deprecated @NonNull public static android.provider.MediaStore.PendingSession openPending(@NonNull android.content.Context, @NonNull android.net.Uri); method @Deprecated @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri); method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri); method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long); @@ -515,11 +517,27 @@ package android.provider { } public static interface MediaStore.MediaColumns extends android.provider.BaseColumns { - field @Deprecated public static final String DATE_EXPIRES = "date_expires"; field @Deprecated public static final String HASH = "_hash"; field @Deprecated public static final String IS_TRASHED = "is_trashed"; } + @Deprecated public static class MediaStore.PendingParams { + ctor public MediaStore.PendingParams(@NonNull android.net.Uri, @NonNull String, @NonNull String); + method public void setDownloadUri(@Nullable android.net.Uri); + method public void setPrimaryDirectory(@Nullable String); + method public void setRefererUri(@Nullable android.net.Uri); + method public void setSecondaryDirectory(@Nullable String); + } + + @Deprecated public static class MediaStore.PendingSession implements java.lang.AutoCloseable { + method public void abandon(); + method public void close(); + method public void notifyProgress(@IntRange(from=0, to=100) int); + method @NonNull public android.os.ParcelFileDescriptor open() throws java.io.FileNotFoundException; + method @NonNull public java.io.OutputStream openOutputStream() throws java.io.FileNotFoundException; + method @NonNull public android.net.Uri publish(); + } + public static final class Settings.Global extends android.provider.Settings.NameValueTable { field @Deprecated public static final String CONTACT_METADATA_SYNC = "contact_metadata_sync"; } diff --git a/api/system-current.txt b/api/system-current.txt index 1da03b32af27..a3bc88cbda85 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -565,7 +565,7 @@ package android.app { } public class StatusBarManager { - method public android.app.StatusBarManager.DisableInfo getDisableInfo(); + method @NonNull public android.app.StatusBarManager.DisableInfo getDisableInfo(); method public void setDisabledForSetup(boolean); } @@ -8521,14 +8521,14 @@ package android.telephony.ims { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException; - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSetting(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSetting(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSetting(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSetting(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback); field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1 @@ -8543,10 +8543,10 @@ package android.telephony.ims { public static class ImsMmTelManager.RegistrationCallback { ctor public ImsMmTelManager.RegistrationCallback(); - method public void onDeregistered(android.telephony.ims.ImsReasonInfo); method public void onRegistered(int); method public void onRegistering(int); method public void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo); + method public void onUnregistered(android.telephony.ims.ImsReasonInfo); } public final class ImsReasonInfo implements android.os.Parcelable { diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 077652cacc2d..af0366801275 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -17,6 +17,7 @@ package android.app; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -387,6 +388,7 @@ public class StatusBarManager { * @hide */ @SystemApi + @NonNull public DisableInfo getDisableInfo() { try { final int userId = Binder.getCallingUserHandle().getIdentifier(); diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java index baf972b26573..8629210c2a7b 100644 --- a/core/java/android/hardware/biometrics/BiometricPrompt.java +++ b/core/java/android/hardware/biometrics/BiometricPrompt.java @@ -616,8 +616,15 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan mExecutor = executor; mAuthenticationCallback = callback; final long sessionId = crypto != null ? crypto.getOpId() : 0; - mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver, - mContext.getOpPackageName(), mBundle); + if (BiometricManager.hasBiometrics(mContext)) { + mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver, + mContext.getOpPackageName(), mBundle); + } else { + mExecutor.execute(() -> { + callback.onAuthenticationError(BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT, + mContext.getString(R.string.biometric_error_hw_unavailable)); + }); + } } catch (RemoteException e) { Log.e(TAG, "Remote exception while authenticating", e); mExecutor.execute(() -> { diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 643307eb89ae..758db4925e26 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -529,7 +529,6 @@ public final class MediaStore { * * @see MediaColumns#IS_PENDING * @see MediaStore#setIncludePending(Uri) - * @see MediaStore#createPending(Context, PendingParams) */ public static @NonNull Uri setIncludePending(@NonNull Uri uri) { return setIncludePending(uri.buildUpon()).build(); @@ -586,7 +585,9 @@ public final class MediaStore { * @see MediaColumns#IS_PENDING * @see MediaStore#setIncludePending(Uri) * @see MediaStore#createPending(Context, PendingParams) + * @removed */ + @Deprecated public static @NonNull Uri createPending(@NonNull Context context, @NonNull PendingParams params) { return context.getContentResolver().insert(params.insertUri, params.insertValues); @@ -599,14 +600,19 @@ public final class MediaStore { * * @param uri token which was previously returned from * {@link #createPending(Context, PendingParams)}. + * @removed */ + @Deprecated public static @NonNull PendingSession openPending(@NonNull Context context, @NonNull Uri uri) { return new PendingSession(context, uri); } /** * Parameters that describe a pending media item. + * + * @removed */ + @Deprecated public static class PendingParams { /** {@hide} */ public final Uri insertUri; @@ -711,7 +717,10 @@ public final class MediaStore { * expected to have a short lifetime, and owners should either * {@link PendingSession#publish()} or {@link PendingSession#abandon()} a * pending item within a few hours after first creating it. + * + * @removed */ + @Deprecated public static class PendingSession implements AutoCloseable { /** {@hide} */ private final Context mContext; @@ -976,9 +985,7 @@ public final class MediaStore { * Flag indicating if a media item is pending, and still being inserted * by its owner. * - * @see MediaColumns#IS_PENDING * @see MediaStore#setIncludePending(Uri) - * @see MediaStore#createPending(Context, PendingParams) */ @Column(Cursor.FIELD_TYPE_INTEGER) public static final String IS_PENDING = "is_pending"; @@ -998,12 +1005,8 @@ public final class MediaStore { /** * The time the media item should be considered expired. Typically only - * meaningful in the context of {@link #IS_PENDING} or - * {@link #IS_TRASHED}. - * - * @removed + * meaningful in the context of {@link #IS_PENDING}. */ - @Deprecated @CurrentTimeSecondsLong @Column(Cursor.FIELD_TYPE_INTEGER) public static final String DATE_EXPIRES = "date_expires"; @@ -1030,8 +1033,6 @@ public final class MediaStore { /** * The primary directory name this media exists under. The value may be * {@code NULL} if the media doesn't have a primary directory name. - * - * @see PendingParams#setPrimaryDirectory(String) */ @Column(Cursor.FIELD_TYPE_STRING) public static final String PRIMARY_DIRECTORY = "primary_directory"; @@ -1039,8 +1040,6 @@ public final class MediaStore { /** * The secondary directory name this media exists under. The value may * be {@code NULL} if the media doesn't have a secondary directory name. - * - * @see PendingParams#setSecondaryDirectory(String) */ @Column(Cursor.FIELD_TYPE_STRING) public static final String SECONDARY_DIRECTORY = "secondary_directory"; @@ -1292,12 +1291,7 @@ public final class MediaStore { } /** - * Container for downloaded files. - * - * <p> - * Querying for downloads from this table will return files contributed via - * {@link PendingSession} and also ones which were downloaded using - * {@link android.app.DownloadManager} APIs. + * Collection of downloaded items. */ public static final class Downloads implements DownloadColumns { private Downloads() {} @@ -1620,9 +1614,9 @@ public final class MediaStore { * @param name The name of the image * @param description The description of the image * @return The URL to the newly created image - * @deprecated inserting of images should be performed through - * {@link MediaStore#createPending(Context, PendingParams)}, - * which offers richer control over lifecycle. + * @deprecated inserting of images should be performed using + * {@link MediaColumns#IS_PENDING}, which offers richer + * control over lifecycle. */ @Deprecated public static final String insertImage(ContentResolver cr, String imagePath, @@ -1651,9 +1645,9 @@ public final class MediaStore { * @param description The description of the image * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored * for any reason. - * @deprecated inserting of images should be performed through - * {@link MediaStore#createPending(Context, PendingParams)}, - * which offers richer control over lifecycle. + * @deprecated inserting of images should be performed using + * {@link MediaColumns#IS_PENDING}, which offers richer + * control over lifecycle. */ @Deprecated public static final String insertImage(ContentResolver cr, Bitmap source, diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java new file mode 100644 index 000000000000..8eccc04fa647 --- /dev/null +++ b/core/java/android/view/GestureExclusionTracker.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2019 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 android.view; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.graphics.Rect; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Used by {@link ViewRootImpl} to track system gesture exclusion rects reported by views. + */ +class GestureExclusionTracker { + private boolean mGestureExclusionViewsChanged = false; + private List<GestureExclusionViewInfo> mGestureExclusionViewInfos = new ArrayList<>(); + private List<Rect> mGestureExclusionRects = Collections.emptyList(); + + public void updateRectsForView(@NonNull View view) { + boolean found = false; + final Iterator<GestureExclusionViewInfo> i = mGestureExclusionViewInfos.iterator(); + while (i.hasNext()) { + final GestureExclusionViewInfo info = i.next(); + final View v = info.getView(); + if (v == null || !v.isAttachedToWindow()) { + mGestureExclusionViewsChanged = true; + i.remove(); + continue; + } + if (v == view) { + found = true; + info.mDirty = true; + break; + } + } + if (!found && view.isAttachedToWindow()) { + mGestureExclusionViewInfos.add(new GestureExclusionViewInfo(view)); + mGestureExclusionViewsChanged = true; + } + } + + @Nullable + public List<Rect> computeChangedRects() { + boolean changed = false; + final Iterator<GestureExclusionViewInfo> i = mGestureExclusionViewInfos.iterator(); + final List<Rect> rects = new ArrayList<>(); + while (i.hasNext()) { + final GestureExclusionViewInfo info = i.next(); + switch (info.update()) { + case GestureExclusionViewInfo.CHANGED: + changed = true; + // Deliberate fall-through + case GestureExclusionViewInfo.UNCHANGED: + rects.addAll(info.mExclusionRects); + break; + case GestureExclusionViewInfo.GONE: + mGestureExclusionViewsChanged = true; + i.remove(); + break; + } + } + if (changed || mGestureExclusionViewsChanged) { + mGestureExclusionViewsChanged = false; + if (!mGestureExclusionRects.equals(rects)) { + mGestureExclusionRects = rects; + return rects; + } + } + return null; + } + + private static class GestureExclusionViewInfo { + public static final int CHANGED = 0; + public static final int UNCHANGED = 1; + public static final int GONE = 2; + + private final WeakReference<View> mView; + boolean mDirty = true; + List<Rect> mExclusionRects = Collections.emptyList(); + + GestureExclusionViewInfo(View view) { + mView = new WeakReference<>(view); + } + + public View getView() { + return mView.get(); + } + + public int update() { + final View excludedView = getView(); + if (excludedView == null || !excludedView.isAttachedToWindow()) return GONE; + final List<Rect> localRects = excludedView.getSystemGestureExclusionRects(); + final List<Rect> newRects = new ArrayList<>(localRects.size()); + for (Rect src : localRects) { + Rect mappedRect = new Rect(src); + ViewParent p = excludedView.getParent(); + if (p != null && p.getChildVisibleRect(excludedView, mappedRect, null)) { + newRects.add(mappedRect); + } + } + + if (mExclusionRects.equals(localRects)) return UNCHANGED; + mExclusionRects = newRects; + return CHANGED; + } + } +} diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index fe9aa234ba54..ee8d66313ea2 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -210,7 +210,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - mRenderNode.requestPositionUpdates(mPositionListener); + mRenderNode.addPositionUpdateListener(mPositionListener); setWillNotDraw(true); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 7afdc7055e42..cc585b0294c7 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -881,12 +881,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static boolean sAlwaysRemeasureExactly = false; /** - * Relax constraints around whether setLayoutParams() must be called after - * modifying the layout params. - */ - private static boolean sLayoutParamsAlwaysChanged = false; - - /** * Allow setForeground/setBackground to be called (and ignored) on a textureview, * without throwing */ @@ -4603,6 +4597,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners; private WindowInsetsAnimationListener mWindowInsetsAnimationListener; + + /** + * This lives here since it's only valid for interactive views. + */ + private List<Rect> mSystemGestureExclusionRects; + + /** + * Used to track {@link #mSystemGestureExclusionRects} + */ + public RenderNode.PositionUpdateListener mPositionUpdateListener; } @UnsupportedAppUsage @@ -5170,11 +5174,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // modes, so we always need to run an additional EXACTLY pass. sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M; - // Prior to N, layout params could change without requiring a - // subsequent call to setLayoutParams() and they would usually - // work. Partial layout breaks this assumption. - sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M; - // Prior to N, TextureView would silently ignore calls to setBackground/setForeground. // On N+, we throw, but that breaks compatibility with apps that use these methods. sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M; @@ -10974,6 +10973,95 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Sets a list of areas within this view's post-layout coordinate space where the system + * should not intercept touch or other pointing device gestures. <em>This method should + * be called by {@link #onLayout(boolean, int, int, int, int)} or {@link #onDraw(Canvas)}.</em> + * + * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture + * input in order to function correctly in the presence of global system gestures that may + * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures + * to provide system-level navigation functionality, a view such as a navigation drawer + * container can mark the left (or starting) edge of itself as requiring gesture capture + * priority using this API. The system may then choose to relax its own gesture recognition + * to allow the app to consume the user's gesture. It is not necessary for an app to register + * exclusion rects for broadly spanning regions such as the entirety of a + * <code>ScrollView</code> or for simple press and release click targets such as + * <code>Button</code>. Mark an exclusion rect when interacting with a view requires + * a precision touch gesture in a small area in either the X or Y dimension, such as + * an edge swipe or dragging a <code>SeekBar</code> thumb.</p> + * + * <p>Do not modify the provided list after this method is called.</p> + * + * @param rects A list of precision gesture regions that this view needs to function correctly + */ + public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) { + if (rects.isEmpty() && mListenerInfo == null) return; + + final ListenerInfo info = getListenerInfo(); + if (rects.isEmpty()) { + info.mSystemGestureExclusionRects = null; + if (info.mPositionUpdateListener != null) { + mRenderNode.removePositionUpdateListener(info.mPositionUpdateListener); + } + } else { + info.mSystemGestureExclusionRects = rects; + if (info.mPositionUpdateListener == null) { + info.mPositionUpdateListener = new RenderNode.PositionUpdateListener() { + @Override + public void positionChanged(long n, int l, int t, int r, int b) { + postUpdateSystemGestureExclusionRects(); + } + + @Override + public void positionLost(long frameNumber) { + postUpdateSystemGestureExclusionRects(); + } + }; + mRenderNode.addPositionUpdateListener(info.mPositionUpdateListener); + } + } + postUpdateSystemGestureExclusionRects(); + } + + /** + * WARNING: this can be called by a hwui worker thread, not just the UI thread! + */ + void postUpdateSystemGestureExclusionRects() { + // Potentially racey from a background thread. It's ok if it's not perfect. + final Handler h = getHandler(); + if (h != null) { + h.postAtFrontOfQueue(this::updateSystemGestureExclusionRects); + } + } + + void updateSystemGestureExclusionRects() { + final AttachInfo ai = mAttachInfo; + if (ai != null) { + ai.mViewRootImpl.updateSystemGestureExclusionRectsForView(this); + } + } + + /** + * Retrieve the list of areas within this view's post-layout coordinate space where the system + * should not intercept touch or other pointing device gestures. + * + * <p>Do not modify the returned list.</p> + * + * @return the list set by {@link #setSystemGestureExclusionRects(List)} + */ + @NonNull + public List<Rect> getSystemGestureExclusionRects() { + final ListenerInfo info = mListenerInfo; + if (info != null) { + final List<Rect> list = info.mSystemGestureExclusionRects; + if (list != null) { + return list; + } + } + return Collections.emptyList(); + } + + /** * Compute the view's coordinate within the surface. * * <p>Computes the coordinates of this view in its surface. The argument @@ -17988,21 +18076,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Utility method to transform a given Rect by the current matrix of this view. - */ - void transformRect(final Rect rect) { - if (!getMatrix().isIdentity()) { - RectF boundingRect = mAttachInfo.mTmpTransformRect; - boundingRect.set(rect); - getMatrix().mapRect(boundingRect); - rect.set((int) Math.floor(boundingRect.left), - (int) Math.floor(boundingRect.top), - (int) Math.ceil(boundingRect.right), - (int) Math.ceil(boundingRect.bottom)); - } - } - - /** * Used to indicate that the parent of this view should clear its caches. This functionality * is used to force the parent to rebuild its display list (when hardware-accelerated), * which is necessary when various parent-managed properties of the view change, such as diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index ad0aaa6edff6..65b1abd715d9 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -605,6 +605,8 @@ public final class ViewRootImpl implements ViewParent, private final InsetsController mInsetsController = new InsetsController(this); + private final GestureExclusionTracker mGestureExclusionTracker = new GestureExclusionTracker(); + static final class SystemUiVisibilityInfo { int seq; int globalVisibility; @@ -3977,6 +3979,20 @@ public final class ViewRootImpl implements ViewParent, return mAttachInfo.mAccessibilityFocusDrawable; } + void updateSystemGestureExclusionRectsForView(View view) { + mGestureExclusionTracker.updateRectsForView(view); + mHandler.sendEmptyMessage(MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED); + } + + void systemGestureExclusionChanged() { + final List<Rect> rectsForWindowManager = mGestureExclusionTracker.computeChangedRects(); + if (rectsForWindowManager != null) { + // TODO Send to WM + mAttachInfo.mTreeObserver + .dispatchOnSystemGestureExclusionRectsChanged(rectsForWindowManager); + } + } + /** * Requests that the root render node is invalidated next time we perform a draw, such that * {@link WindowCallbacks#onPostDraw} gets called. @@ -4433,35 +4449,36 @@ public final class ViewRootImpl implements ViewParent, } } - private final static int MSG_INVALIDATE = 1; - private final static int MSG_INVALIDATE_RECT = 2; - private final static int MSG_DIE = 3; - private final static int MSG_RESIZED = 4; - private final static int MSG_RESIZED_REPORT = 5; - private final static int MSG_WINDOW_FOCUS_CHANGED = 6; - private final static int MSG_DISPATCH_INPUT_EVENT = 7; - private final static int MSG_DISPATCH_APP_VISIBILITY = 8; - private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9; - private final static int MSG_DISPATCH_KEY_FROM_IME = 11; - private final static int MSG_DISPATCH_KEY_FROM_AUTOFILL = 12; - private final static int MSG_CHECK_FOCUS = 13; - private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14; - private final static int MSG_DISPATCH_DRAG_EVENT = 15; - private final static int MSG_DISPATCH_DRAG_LOCATION_EVENT = 16; - private final static int MSG_DISPATCH_SYSTEM_UI_VISIBILITY = 17; - private final static int MSG_UPDATE_CONFIGURATION = 18; - private final static int MSG_PROCESS_INPUT_EVENTS = 19; - private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 21; - private final static int MSG_INVALIDATE_WORLD = 22; - private final static int MSG_WINDOW_MOVED = 23; - private final static int MSG_SYNTHESIZE_INPUT_EVENT = 24; - private final static int MSG_DISPATCH_WINDOW_SHOWN = 25; - private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26; - private final static int MSG_UPDATE_POINTER_ICON = 27; - private final static int MSG_POINTER_CAPTURE_CHANGED = 28; - private final static int MSG_DRAW_FINISHED = 29; - private final static int MSG_INSETS_CHANGED = 30; - private final static int MSG_INSETS_CONTROL_CHANGED = 31; + private static final int MSG_INVALIDATE = 1; + private static final int MSG_INVALIDATE_RECT = 2; + private static final int MSG_DIE = 3; + private static final int MSG_RESIZED = 4; + private static final int MSG_RESIZED_REPORT = 5; + private static final int MSG_WINDOW_FOCUS_CHANGED = 6; + private static final int MSG_DISPATCH_INPUT_EVENT = 7; + private static final int MSG_DISPATCH_APP_VISIBILITY = 8; + private static final int MSG_DISPATCH_GET_NEW_SURFACE = 9; + private static final int MSG_DISPATCH_KEY_FROM_IME = 11; + private static final int MSG_DISPATCH_KEY_FROM_AUTOFILL = 12; + private static final int MSG_CHECK_FOCUS = 13; + private static final int MSG_CLOSE_SYSTEM_DIALOGS = 14; + private static final int MSG_DISPATCH_DRAG_EVENT = 15; + private static final int MSG_DISPATCH_DRAG_LOCATION_EVENT = 16; + private static final int MSG_DISPATCH_SYSTEM_UI_VISIBILITY = 17; + private static final int MSG_UPDATE_CONFIGURATION = 18; + private static final int MSG_PROCESS_INPUT_EVENTS = 19; + private static final int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 21; + private static final int MSG_INVALIDATE_WORLD = 22; + private static final int MSG_WINDOW_MOVED = 23; + private static final int MSG_SYNTHESIZE_INPUT_EVENT = 24; + private static final int MSG_DISPATCH_WINDOW_SHOWN = 25; + private static final int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26; + private static final int MSG_UPDATE_POINTER_ICON = 27; + private static final int MSG_POINTER_CAPTURE_CHANGED = 28; + private static final int MSG_DRAW_FINISHED = 29; + private static final int MSG_INSETS_CHANGED = 30; + private static final int MSG_INSETS_CONTROL_CHANGED = 31; + private static final int MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED = 32; final class ViewRootHandler extends Handler { @Override @@ -4519,6 +4536,10 @@ public final class ViewRootImpl implements ViewParent, return "MSG_DRAW_FINISHED"; case MSG_INSETS_CHANGED: return "MSG_INSETS_CHANGED"; + case MSG_INSETS_CONTROL_CHANGED: + return "MSG_INSETS_CONTROL_CHANGED"; + case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED: + return "MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED"; } return super.getMessageName(message); } @@ -4750,6 +4771,9 @@ public final class ViewRootImpl implements ViewParent, case MSG_DRAW_FINISHED: { pendingDrawFinished(); } break; + case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED: { + systemGestureExclusionChanged(); + } break; } } } diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index 763ce4f45b01..2896bd049e7c 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -26,7 +26,9 @@ import android.os.Build; import android.util.Log; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Consumer; /** * A view tree observer is used to register listeners that can be notified of global @@ -57,6 +59,7 @@ public final class ViewTreeObserver { private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners; private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners; private CopyOnWriteArray<OnWindowShownListener> mOnWindowShownListeners; + private CopyOnWriteArray<Consumer<List<Rect>>> mGestureExclusionListeners; // These listeners cannot be mutated during dispatch private boolean mInDispatchOnDraw; @@ -450,6 +453,14 @@ public final class ViewTreeObserver { } } + if (observer.mGestureExclusionListeners != null) { + if (mGestureExclusionListeners != null) { + mGestureExclusionListeners.addAll(observer.mGestureExclusionListeners); + } else { + mGestureExclusionListeners = observer.mGestureExclusionListeners; + } + } + observer.kill(); } @@ -913,6 +924,35 @@ public final class ViewTreeObserver { mOnEnterAnimationCompleteListeners.remove(listener); } + /** + * Add a listener to be notified when the tree's <em>transformed</em> gesture exclusion rects + * change. This could be the result of an animation or other layout change, or a view calling + * {@link View#setSystemGestureExclusionRects(List)}. + * + * @param listener listener to add + * @see View#setSystemGestureExclusionRects(List) + */ + public void addOnSystemGestureExclusionRectsChangedListener(Consumer<List<Rect>> listener) { + checkIsAlive(); + if (mGestureExclusionListeners == null) { + mGestureExclusionListeners = new CopyOnWriteArray<>(); + } + mGestureExclusionListeners.add(listener); + } + + /** + * Unsubscribe the given listener from gesture exclusion rect changes. + * @see #addOnSystemGestureExclusionRectsChangedListener(Consumer) + * @see View#setSystemGestureExclusionRects(List) + */ + public void removeOnSystemGestureExclusionRectsChangedListener(Consumer<List<Rect>> listener) { + checkIsAlive(); + if (mGestureExclusionListeners == null) { + return; + } + mGestureExclusionListeners.remove(listener); + } + private void checkIsAlive() { if (!mAlive) { throw new IllegalStateException("This ViewTreeObserver is not alive, call " @@ -1178,6 +1218,21 @@ public final class ViewTreeObserver { } } + void dispatchOnSystemGestureExclusionRectsChanged(@NonNull List<Rect> rects) { + final CopyOnWriteArray<Consumer<List<Rect>>> listeners = mGestureExclusionListeners; + if (listeners != null && listeners.size() > 0) { + CopyOnWriteArray.Access<Consumer<List<Rect>>> access = listeners.start(); + try { + final int count = access.size(); + for (int i = 0; i < count; i++) { + access.get(i).accept(rects); + } + } finally { + listeners.end(); + } + } + } + /** * Copy on write array. This array is not thread safe, and only one loop can * iterate over this array at any given time. This class avoids allocations diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java index e0950948afb8..3b60aee8f604 100644 --- a/core/java/android/view/animation/Animation.java +++ b/core/java/android/view/animation/Animation.java @@ -207,6 +207,7 @@ public abstract class Animation implements Cloneable { private float mScaleFactor = 1f; private boolean mShowWallpaper; + private boolean mHasRoundedCorners; private boolean mMore = true; private boolean mOneMoreTime = true; @@ -263,6 +264,8 @@ public abstract class Animation implements Cloneable { a.getBoolean(com.android.internal.R.styleable.Animation_detachWallpaper, false)); setShowWallpaper( a.getBoolean(com.android.internal.R.styleable.Animation_showWallpaper, false)); + setHasRoundedCorners( + a.getBoolean(com.android.internal.R.styleable.Animation_hasRoundedCorners, false)); final int resID = a.getResourceId(com.android.internal.R.styleable.Animation_interpolator, 0); @@ -678,6 +681,19 @@ public abstract class Animation implements Cloneable { } /** + * If this is a window animation, the window will have rounded corners matching the display + * corner radius. + * + * @param hasRoundedCorners Whether the window should have rounded corners or not. + * @attr ref android.R.styleable#Animation_hasRoundedCorners + * @see com.android.internal.policy.ScreenDecorationsUtils#getWindowCornerRadius(Resources) + * @hide + */ + public void setHasRoundedCorners(boolean hasRoundedCorners) { + mHasRoundedCorners = hasRoundedCorners; + } + + /** * Gets the acceleration curve type for this animation. * * @return the {@link Interpolator} associated to this animation @@ -804,6 +820,16 @@ public abstract class Animation implements Cloneable { } /** + * @return if a window animation should have rounded corners or not. + * + * @attr ref android.R.styleable#Animation_hasRoundedCorners + * @hide + */ + public boolean hasRoundedCorners() { + return mHasRoundedCorners; + } + + /** * <p>Indicates whether or not this animation will affect the transformation * matrix. For instance, a fade animation will not affect the matrix whereas * a scale animation will.</p> diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java index dd6a27b8f1e4..7a5b7e8058f3 100644 --- a/core/java/android/widget/ZoomControls.java +++ b/core/java/android/widget/ZoomControls.java @@ -30,7 +30,11 @@ import com.android.internal.R; /** * The {@code ZoomControls} class displays a simple set of controls used for zooming and - * provides callbacks to register for events. */ + * provides callbacks to register for events. + * @deprecated This functionality and UI is better handled with custom views and layouts + * rather than a dedicated zoom-control widget + */ +@Deprecated @Widget public class ZoomControls extends LinearLayout { diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 464f24901eb1..a9002945ff91 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -58,8 +58,6 @@ namespace android { -using ui::Dataspace; - static const char* const OutOfResourcesException = "android/view/Surface$OutOfResourcesException"; @@ -129,135 +127,17 @@ jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env, } int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) { - - switch(f) { - case PublicFormat::JPEG: - case PublicFormat::DEPTH_POINT_CLOUD: - case PublicFormat::DEPTH_JPEG: - case PublicFormat::HEIC: - return HAL_PIXEL_FORMAT_BLOB; - case PublicFormat::DEPTH16: - return HAL_PIXEL_FORMAT_Y16; - case PublicFormat::RAW_SENSOR: - case PublicFormat::RAW_DEPTH: - return HAL_PIXEL_FORMAT_RAW16; - default: - // Most formats map 1:1 - return static_cast<int>(f); - } + return mapPublicFormatToHalFormat(f); } android_dataspace android_view_Surface_mapPublicFormatToHalDataspace( PublicFormat f) { - Dataspace dataspace; - switch(f) { - case PublicFormat::JPEG: - dataspace = Dataspace::V0_JFIF; - break; - case PublicFormat::DEPTH_POINT_CLOUD: - case PublicFormat::DEPTH16: - case PublicFormat::RAW_DEPTH: - dataspace = Dataspace::DEPTH; - break; - case PublicFormat::RAW_SENSOR: - case PublicFormat::RAW_PRIVATE: - case PublicFormat::RAW10: - case PublicFormat::RAW12: - dataspace = Dataspace::ARBITRARY; - break; - case PublicFormat::YUV_420_888: - case PublicFormat::NV21: - case PublicFormat::YV12: - dataspace = Dataspace::V0_JFIF; - break; - case PublicFormat::DEPTH_JPEG: - dataspace = Dataspace::DYNAMIC_DEPTH; - break; - case PublicFormat::HEIC: - dataspace = Dataspace::HEIF; - break; - default: - // Most formats map to UNKNOWN - dataspace = Dataspace::UNKNOWN; - break; - } - return static_cast<android_dataspace>(dataspace); + return mapPublicFormatToHalDataspace(f); } PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( int format, android_dataspace dataSpace) { - Dataspace ds = static_cast<Dataspace>(dataSpace); - switch(format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - case HAL_PIXEL_FORMAT_RGBX_8888: - case HAL_PIXEL_FORMAT_RGBA_FP16: - case HAL_PIXEL_FORMAT_RGBA_1010102: - case HAL_PIXEL_FORMAT_RGB_888: - case HAL_PIXEL_FORMAT_RGB_565: - case HAL_PIXEL_FORMAT_Y8: - case HAL_PIXEL_FORMAT_RAW10: - case HAL_PIXEL_FORMAT_RAW12: - case HAL_PIXEL_FORMAT_YCbCr_420_888: - case HAL_PIXEL_FORMAT_YV12: - // Enums overlap in both name and value - return static_cast<PublicFormat>(format); - case HAL_PIXEL_FORMAT_RAW16: - switch (ds) { - case Dataspace::DEPTH: - return PublicFormat::RAW_DEPTH; - default: - return PublicFormat::RAW_SENSOR; - } - case HAL_PIXEL_FORMAT_RAW_OPAQUE: - // Name differs, though value is the same - return PublicFormat::RAW_PRIVATE; - case HAL_PIXEL_FORMAT_YCbCr_422_SP: - // Name differs, though the value is the same - return PublicFormat::NV16; - case HAL_PIXEL_FORMAT_YCrCb_420_SP: - // Name differs, though the value is the same - return PublicFormat::NV21; - case HAL_PIXEL_FORMAT_YCbCr_422_I: - // Name differs, though the value is the same - return PublicFormat::YUY2; - case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: - // Name differs, though the value is the same - return PublicFormat::PRIVATE; - case HAL_PIXEL_FORMAT_Y16: - // Dataspace-dependent - switch (ds) { - case Dataspace::DEPTH: - return PublicFormat::DEPTH16; - default: - // Assume non-depth Y16 is just Y16. - return PublicFormat::Y16; - } - break; - case HAL_PIXEL_FORMAT_BLOB: - // Dataspace-dependent - switch (ds) { - case Dataspace::DEPTH: - return PublicFormat::DEPTH_POINT_CLOUD; - case Dataspace::V0_JFIF: - return PublicFormat::JPEG; - case Dataspace::HEIF: - return PublicFormat::HEIC; - default: - if (dataSpace == static_cast<android_dataspace>(HAL_DATASPACE_DYNAMIC_DEPTH)) { - return PublicFormat::DEPTH_JPEG; - } else { - // Assume otherwise-marked blobs are also JPEG - return PublicFormat::JPEG; - } - } - break; - case HAL_PIXEL_FORMAT_BGRA_8888: - // Not defined in public API - return PublicFormat::UNKNOWN; - - default: - return PublicFormat::UNKNOWN; - } + return mapHalFormatDataspaceToPublicFormat(format, dataSpace); } // ---------------------------------------------------------------------------- diff --git a/core/jni/include/android_runtime/android_view_Surface.h b/core/jni/include/android_runtime/android_view_Surface.h index 3f7c00c9ff01..04718cd981ff 100644 --- a/core/jni/include/android_runtime/android_view_Surface.h +++ b/core/jni/include/android_runtime/android_view_Surface.h @@ -19,6 +19,7 @@ #include <android/native_window.h> #include <system/graphics.h> +#include <ui/PublicFormat.h> #include "jni.h" @@ -27,41 +28,6 @@ namespace android { class Surface; class IGraphicBufferProducer; -/** - * Enum mirroring the public API definitions for image and pixel formats. - * Some of these are hidden in the public API - * - * Keep up to date with android.graphics.ImageFormat and - * android.graphics.PixelFormat - */ -enum class PublicFormat { - UNKNOWN = 0x0, - RGBA_8888 = 0x1, - RGBX_8888 = 0x2, - RGB_888 = 0x3, - RGB_565 = 0x4, - NV16 = 0x10, - NV21 = 0x11, - YUY2 = 0x14, - RGBA_FP16 = 0x16, - RAW_SENSOR = 0x20, - PRIVATE = 0x22, - YUV_420_888 = 0x23, - RAW_PRIVATE = 0x24, - RAW10 = 0x25, - RAW12 = 0x26, - RGBA_1010102 = 0x2b, - JPEG = 0x100, - DEPTH_POINT_CLOUD = 0x101, - RAW_DEPTH = 0x1002, // @hide - YV12 = 0x32315659, - Y8 = 0x20203859, - Y16 = 0x20363159, // @hide - DEPTH16 = 0x44363159, - DEPTH_JPEG = 0x69656963, - HEIC = 0x48454946, -}; - /* Gets the underlying ANativeWindow for a Surface. */ extern sp<ANativeWindow> android_view_Surface_getNativeWindow( JNIEnv* env, jobject surfaceObj); diff --git a/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml index 6f3dc8c7de0e..5add19bba51b 100644 --- a/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml +++ b/core/res/res/anim-ldrtl/cross_profile_apps_thumbnail_enter.xml @@ -18,7 +18,9 @@ --> <!-- This should be kept in sync with task_open_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" android:zAdjustment="top"> + android:hasRoundedCorners="true" + android:shareInterpolator="false" + android:zAdjustment="top"> <alpha android:fromAlpha="1" diff --git a/core/res/res/anim-ldrtl/task_close_enter.xml b/core/res/res/anim-ldrtl/task_close_enter.xml index 7abada332fb6..e00141a8c155 100644 --- a/core/res/res/anim-ldrtl/task_close_enter.xml +++ b/core/res/res/anim-ldrtl/task_close_enter.xml @@ -16,6 +16,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:zAdjustment="top" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim-ldrtl/task_close_exit.xml b/core/res/res/anim-ldrtl/task_close_exit.xml index a017820a4b3e..71a44ae7d2fc 100644 --- a/core/res/res/anim-ldrtl/task_close_exit.xml +++ b/core/res/res/anim-ldrtl/task_close_exit.xml @@ -16,6 +16,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim-ldrtl/task_open_enter.xml b/core/res/res/anim-ldrtl/task_open_enter.xml index 0433664717eb..7815f7d661d0 100644 --- a/core/res/res/anim-ldrtl/task_open_enter.xml +++ b/core/res/res/anim-ldrtl/task_open_enter.xml @@ -18,6 +18,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:zAdjustment="top" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml b/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml index 45ca80e00e22..5fccd6df14a5 100644 --- a/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml +++ b/core/res/res/anim-ldrtl/task_open_enter_cross_profile_apps.xml @@ -18,6 +18,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:zAdjustment="top" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim-ldrtl/task_open_exit.xml b/core/res/res/anim-ldrtl/task_open_exit.xml index f50494d81eb5..025e1bdc05c9 100644 --- a/core/res/res/anim-ldrtl/task_open_exit.xml +++ b/core/res/res/anim-ldrtl/task_open_exit.xml @@ -16,6 +16,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml index 4c2559f1e47d..2cfeecf4685d 100644 --- a/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml +++ b/core/res/res/anim/cross_profile_apps_thumbnail_enter.xml @@ -18,7 +18,9 @@ --> <!-- This should be kept in sync with task_open_enter.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:shareInterpolator="false" android:zAdjustment="top"> + android:shareInterpolator="false" + android:hasRoundedCorners="true" + android:zAdjustment="top"> <alpha android:fromAlpha="1" diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml index b059aa9cb28c..487ff5c748d3 100644 --- a/core/res/res/anim/task_close_enter.xml +++ b/core/res/res/anim/task_close_enter.xml @@ -18,6 +18,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:zAdjustment="top" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml index c9ade227819b..afc3256cb617 100644 --- a/core/res/res/anim/task_close_exit.xml +++ b/core/res/res/anim/task_close_exit.xml @@ -18,6 +18,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml index 5c618594364f..0aafc1c0b91c 100644 --- a/core/res/res/anim/task_open_enter.xml +++ b/core/res/res/anim/task_open_enter.xml @@ -20,6 +20,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:zAdjustment="top" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim/task_open_enter_cross_profile_apps.xml b/core/res/res/anim/task_open_enter_cross_profile_apps.xml index 644104721463..702f7ba162aa 100644 --- a/core/res/res/anim/task_open_enter_cross_profile_apps.xml +++ b/core/res/res/anim/task_open_enter_cross_profile_apps.xml @@ -20,6 +20,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" android:zAdjustment="top" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml index 9394c577da78..691317d2e6e0 100644 --- a/core/res/res/anim/task_open_exit.xml +++ b/core/res/res/anim/task_open_exit.xml @@ -18,6 +18,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" + android:hasRoundedCorners="true" android:showWallpaper="true"> <alpha diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 088669da7b91..743496fdffb5 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -6488,6 +6488,9 @@ <!-- Special option for window animations: show the wallpaper behind when running this animation. --> <attr name="showWallpaper" format="boolean" /> + <!-- Special option for window animations: whether window should have rounded corners. + @see ScreenDecorationsUtils#getWindowCornerRadius(Resources) --> + <attr name="hasRoundedCorners" format="boolean" /> </declare-styleable> <declare-styleable name="AnimationSet"> diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index e98879d0c5bd..42b6acd3b25a 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -27,6 +27,8 @@ import android.view.RenderNodeAnimator; import android.view.Surface; import android.view.View; +import com.android.internal.util.ArrayUtils; + import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; @@ -179,6 +181,10 @@ public final class RenderNode { private final AnimationHost mAnimationHost; private RecordingCanvas mCurrentRecordingCanvas; + // Will be null if not currently registered + @Nullable + private CompositePositionUpdateListener mCompositePositionUpdateListener; + /** * Creates a new RenderNode that can be used to record batches of * drawing operations, and store / apply render properties when drawn. @@ -248,15 +254,70 @@ public final class RenderNode { } + private static final class CompositePositionUpdateListener implements PositionUpdateListener { + private final PositionUpdateListener[] mListeners; + + CompositePositionUpdateListener(PositionUpdateListener... listeners) { + mListeners = listeners; + } + + public CompositePositionUpdateListener with(PositionUpdateListener listener) { + return new CompositePositionUpdateListener( + ArrayUtils.appendElement(PositionUpdateListener.class, mListeners, listener)); + } + + public CompositePositionUpdateListener without(PositionUpdateListener listener) { + return new CompositePositionUpdateListener( + ArrayUtils.removeElement(PositionUpdateListener.class, mListeners, listener)); + } + + @Override + public void positionChanged(long frameNumber, int left, int top, int right, int bottom) { + for (PositionUpdateListener pul : mListeners) { + pul.positionChanged(frameNumber, left, top, right, bottom); + } + } + + @Override + public void positionLost(long frameNumber) { + for (PositionUpdateListener pul : mListeners) { + pul.positionLost(frameNumber); + } + } + } + /** - * Enable callbacks for position changes. + * Enable callbacks for position changes. Call only from the UI thread or with + * external synchronization. * * @hide */ - public void requestPositionUpdates(PositionUpdateListener listener) { - nRequestPositionUpdates(mNativeRenderNode, listener); + public void addPositionUpdateListener(@NonNull PositionUpdateListener listener) { + CompositePositionUpdateListener comp = mCompositePositionUpdateListener; + if (comp == null) { + comp = new CompositePositionUpdateListener(listener); + } else { + comp = comp.with(listener); + } + mCompositePositionUpdateListener = comp; + nRequestPositionUpdates(mNativeRenderNode, comp); } + /** + * Disable a callback for position changes. Call only from the UI thread or with + * external synchronization. + * + * @param listener Callback to remove + * @hide + */ + public void removePositionUpdateListener(@NonNull PositionUpdateListener listener) { + CompositePositionUpdateListener comp = mCompositePositionUpdateListener; + if (comp != null) { + comp = comp.without(listener); + mCompositePositionUpdateListener = comp; + nRequestPositionUpdates(mNativeRenderNode, comp); + } + } /** * Starts recording a display list for the render node. All diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 3b43f1297597..5af660c8738a 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -254,10 +254,36 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe float queuePriorities[1] = { 0.0 }; + void* queueNextPtr = nullptr; + + VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo; + + if (Properties::contextPriority != 0 + && grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) { + memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT)); + queuePriorityCreateInfo.sType = + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT; + queuePriorityCreateInfo.pNext = nullptr; + switch (Properties::contextPriority) { + case EGL_CONTEXT_PRIORITY_LOW_IMG: + queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT; + break; + case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: + queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT; + break; + case EGL_CONTEXT_PRIORITY_HIGH_IMG: + queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT; + break; + default: + LOG_ALWAYS_FATAL("Unsupported context priority"); + } + queueNextPtr = &queuePriorityCreateInfo; + } + const VkDeviceQueueCreateInfo queueInfo[2] = { { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType - nullptr, // pNext + queueNextPtr, // pNext 0, // VkDeviceQueueCreateFlags mGraphicsQueueIndex, // queueFamilyIndex 1, // queueCount @@ -265,7 +291,7 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe }, { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType - nullptr, // pNext + queueNextPtr, // pNext 0, // VkDeviceQueueCreateFlags mPresentQueueIndex, // queueFamilyIndex 1, // queueCount diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java index 385bc6cf3932..a18686da653e 100644 --- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java +++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java @@ -80,12 +80,7 @@ public final class ContentSuggestionsPerUserService extends @Override // from PerUserSystemService protected boolean updateLocked(boolean disabled) { final boolean enabledChanged = super.updateLocked(disabled); - if (enabledChanged) { - if (!isEnabledLocked()) { - // Clear the remote service for the next call - mRemoteService = null; - } - } + updateRemoteServiceLocked(); return enabledChanged; } @@ -133,6 +128,15 @@ public final class ContentSuggestionsPerUserService extends } @GuardedBy("mLock") + private void updateRemoteServiceLocked() { + if (mRemoteService != null) { + mRemoteService.destroy(); + mRemoteService = null; + } + } + + + @GuardedBy("mLock") @Nullable private RemoteContentSuggestionsService getRemoteServiceLocked() { if (mRemoteService == null) { diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java index 5519729c17f5..bbbf11d2a7a2 100644 --- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java +++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java @@ -118,7 +118,8 @@ class AppWindowThumbnail implements Animatable { anim.scaleCurrentDuration(mAppToken.mWmService.getTransitionAnimationScaleLocked()); mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter( new WindowAnimationSpec(anim, position, - mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame()), + mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame(), + mAppToken.mWmService.mWindowCornerRadius), mAppToken.mWmService.mSurfaceAnimationRunner), false /* hidden */); } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 05c4c2793a01..78199d4412a6 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -582,6 +582,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } } + // Changes in opening apps and closing apps may cause orientation change. + reportDescendantOrientationChangeIfNeeded(); return; } @@ -729,11 +731,31 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } SurfaceControl.closeTransaction(); } + + // Visibility changes may cause orientation request change. + reportDescendantOrientationChangeIfNeeded(); } return delayed; } + private void reportDescendantOrientationChangeIfNeeded() { + // Orientation request is exposed only when we're visible. Therefore visibility change + // will change requested orientation. Notify upward the hierarchy ladder to adjust + // configuration. This is important to cases where activities with incompatible + // orientations launch, or user goes back from an activity of bi-orientation to an + // activity with specified orientation. + if (mActivityRecord.getRequestedConfigurationOrientation() == getConfiguration().orientation + || getOrientationIgnoreVisibility() == SCREEN_ORIENTATION_UNSET) { + return; + } + + final IBinder freezeToken = + mActivityRecord.mayFreezeScreenLocked(mActivityRecord.app) + ? mActivityRecord.appToken : null; + onDescendantOrientationChanged(freezeToken, mActivityRecord); + } + /** * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns * true. @@ -2526,7 +2548,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree new WindowAnimationSpec(a, mTmpPoint, mTmpRect, getDisplayContent().mAppTransition.canSkipFirstFrame(), appStackClipMode, - true /* isAppAnimation */), + true /* isAppAnimation */, + mWmService.mWindowCornerRadius), mWmService.mSurfaceAnimationRunner); if (a.getZAdjustment() == Animation.ZORDER_TOP) { mNeedsZBoost = true; diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 888d74163163..499cbaf915a1 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -330,7 +330,7 @@ class Task extends WindowContainer<AppWindowToken> implements ConfigurationConta // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill // it if possible. // TODO: Move to TaskRecord after unification is done. - if (mTaskRecord != null) { + if (mTaskRecord != null && mTaskRecord.getParent() != null) { mTaskRecord.onConfigurationChanged(mTaskRecord.getParent().getConfiguration()); return true; } diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java index 98c77ac719f9..57311e19bc76 100644 --- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java +++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java @@ -17,10 +17,10 @@ package com.android.server.wm; import static com.android.server.wm.AnimationAdapter.STATUS_BAR_TRANSITION_DURATION; -import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; -import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; import static com.android.server.wm.AnimationSpecProto.WINDOW; import static com.android.server.wm.WindowAnimationSpecProto.ANIMATION; +import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; +import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; import android.graphics.Point; import android.graphics.Rect; @@ -51,18 +51,22 @@ public class WindowAnimationSpec implements AnimationSpec { private final Rect mStackBounds = new Rect(); private int mStackClipMode; private final Rect mTmpRect = new Rect(); + private final float mWindowCornerRadius; - public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame) { + public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame, + float windowCornerRadius) { this(animation, position, null /* stackBounds */, canSkipFirstFrame, STACK_CLIP_NONE, - false /* isAppAnimation */); + false /* isAppAnimation */, windowCornerRadius); } public WindowAnimationSpec(Animation animation, Point position, Rect stackBounds, - boolean canSkipFirstFrame, int stackClipMode, boolean isAppAnimation) { + boolean canSkipFirstFrame, int stackClipMode, boolean isAppAnimation, + float windowCornerRadius) { mAnimation = animation; if (position != null) { mPosition.set(position.x, position.y); } + mWindowCornerRadius = windowCornerRadius; mCanSkipFirstFrame = canSkipFirstFrame; mIsAppAnimation = isAppAnimation; mStackClipMode = stackClipMode; @@ -101,6 +105,9 @@ public class WindowAnimationSpec implements AnimationSpec { mTmpRect.intersect(tmp.transformation.getClipRect()); t.setWindowCrop(leash, mTmpRect); } + if (mAnimation.hasRoundedCorners() && mWindowCornerRadius > 0) { + t.setCornerRadius(leash, mWindowCornerRadius); + } } @Override diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 474a9dabf9c4..cbafb3f2f297 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -234,6 +234,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.IResultReceiver; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; +import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.LatencyTracker; @@ -753,24 +754,27 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayManager mDisplayManager; final ActivityTaskManagerService mAtmService; - // Indicates whether this device supports wide color gamut / HDR rendering + /** Corner radius that windows should have in order to match the display. */ + final float mWindowCornerRadius; + + /** Indicates whether this device supports wide color gamut / HDR rendering */ private boolean mHasWideColorGamutSupport; private boolean mHasHdrSupport; - // Who is holding the screen on. + /** Who is holding the screen on. */ private Session mHoldingScreenOn; private PowerManager.WakeLock mHoldingScreenWakeLock; - // Whether or not a layout can cause a wake up when theater mode is enabled. + /** Whether or not a layout can cause a wake up when theater mode is enabled. */ boolean mAllowTheaterModeWakeFromLayout; final TaskPositioningController mTaskPositioningController; final DragDropController mDragDropController; - // For frozen screen animations. + /** For frozen screen animations. */ private int mExitAnimId, mEnterAnimId; - // The display that the rotation animation is applying to. + /** The display that the rotation animation is applying to. */ private int mFrozenDisplayId; /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this @@ -977,7 +981,7 @@ public class WindowManagerService extends IWindowManager.Stub mInputManager = inputManager; // Must be before createDisplayContentLocked. mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mDisplayWindowSettings = new DisplayWindowSettings(this); - + mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context.getResources()); mTransactionFactory = transactionFactory; mTransaction = mTransactionFactory.make(); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index a13086dcc279..b7925f20be86 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4458,7 +4458,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP anim.restrictDuration(MAX_ANIMATION_DURATION); anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked()); final AnimationAdapter adapter = new LocalAnimationAdapter( - new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */), + new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */, + mWmService.mWindowCornerRadius), mWmService.mSurfaceAnimationRunner); startAnimation(mPendingTransaction, adapter); commitPendingTransaction(); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java index 2c575f59a020..68b40b92b9cc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java @@ -18,11 +18,11 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; -import static android.content.ActivityInfoProto.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; @@ -42,12 +42,16 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.verify; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; +import android.view.Display; import android.view.Surface; import android.view.WindowManager; @@ -55,6 +59,7 @@ import androidx.test.filters.SmallTest; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; /** * Tests for the {@link AppWindowToken} class. @@ -332,6 +337,46 @@ public class AppWindowTokenTests extends WindowTestsBase { } @Test + public void testReportOrientationChangeOnVisibilityChange() { + synchronized (mWm.mGlobalLock) { + mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); + + mDisplayContent.getDisplayRotation().setFixedToUserRotation( + DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED); + + doReturn(Configuration.ORIENTATION_LANDSCAPE).when(mToken.mActivityRecord) + .getRequestedConfigurationOrientation(); + + mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS); + mToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET, + true /* performLayout */, false /* isVoiceInteraction */); + } + + verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class)); + } + + @Test + public void testReportOrientationChangeOnOpeningClosingAppChange() { + synchronized (mWm.mGlobalLock) { + mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); + + mDisplayContent.getDisplayRotation().setFixedToUserRotation( + DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED); + mDisplayContent.getDisplayInfo().state = Display.STATE_ON; + mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_CLOSE, + false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */); + + doReturn(Configuration.ORIENTATION_LANDSCAPE).when(mToken.mActivityRecord) + .getRequestedConfigurationOrientation(); + + mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS); + mToken.setVisibility(false, false); + } + + verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class)); + } + + @Test public void testCreateRemoveStartingWindow() { mToken.addStartingWindow(mPackageName, android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true, diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java index 6cce9f088ee4..c48348992196 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java @@ -213,7 +213,8 @@ public class SurfaceAnimationRunnerTest extends WindowTestsBase { final Animation a = new TranslateAnimation(-10, 10, 0, 0); a.initialize(0, 0, 0, 0); a.setDuration(50); - return new WindowAnimationSpec(a, new Point(0, 0), false /* canSkipFirstFrame */); + return new WindowAnimationSpec(a, new Point(0, 0), false /* canSkipFirstFrame */, + 0 /* windowCornerRadius */); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java index 9a825e068584..897f0a2c6e81 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java @@ -24,6 +24,8 @@ import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.when; import android.graphics.Point; import android.graphics.Rect; @@ -56,7 +58,7 @@ public class WindowAnimationSpecTest { Animation a = createClipRectAnimation(windowCrop, windowCrop); WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null, mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE, - true /* isAppAnimation */); + true /* isAppAnimation */, 0 /* windowCornerRadius */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(rect -> rect.equals(windowCrop))); @@ -66,7 +68,7 @@ public class WindowAnimationSpecTest { public void testApply_clipAfter() { WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null, mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_AFTER_ANIM, - true /* isAppAnimation */); + true /* isAppAnimation */, 0 /* windowCornerRadius */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty)); } @@ -76,8 +78,7 @@ public class WindowAnimationSpecTest { // Stack bounds is (0, 0, 10, 10) position is (20, 40) WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, new Point(20, 40), mStackBounds, false /* canSkipFirstFrame */, - STACK_CLIP_AFTER_ANIM, - true /* isAppAnimation */); + STACK_CLIP_AFTER_ANIM, true /* isAppAnimation */, 0 /* windowCornerRadius */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty)); } @@ -87,7 +88,7 @@ public class WindowAnimationSpecTest { // Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 0, 0) WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null, mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM, - true /* isAppAnimation */); + true /* isAppAnimation */, 0 /* windowCornerRadius */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(rect -> rect.equals(mStackBounds))); @@ -101,19 +102,32 @@ public class WindowAnimationSpecTest { a.initialize(0, 0, 0, 0); WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null, null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM, - true /* isAppAnimation */); + true /* isAppAnimation */, 0 /* windowCornerRadius */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty)); } @Test + public void testApply_setCornerRadius() { + final float windowCornerRadius = 30f; + WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(mAnimation, null, + mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM, + true /* isAppAnimation */, windowCornerRadius); + windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); + verify(mTransaction, never()).setCornerRadius(eq(mSurfaceControl), eq(windowCornerRadius)); + when(mAnimation.hasRoundedCorners()).thenReturn(true); + windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); + verify(mTransaction).setCornerRadius(eq(mSurfaceControl), eq(windowCornerRadius)); + } + + @Test public void testApply_clipBeforeSmallerAnimationClip() { // Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 5, 5) Rect windowCrop = new Rect(0, 0, 5, 5); Animation a = createClipRectAnimation(windowCrop, windowCrop); WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null, mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM, - true /* isAppAnimation */); + true /* isAppAnimation */, 0 /* windowCornerRadius */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(rect -> rect.equals(windowCrop))); @@ -126,7 +140,7 @@ public class WindowAnimationSpecTest { Animation a = createClipRectAnimation(windowCrop, windowCrop); WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null, mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM, - true /* isAppAnimation */); + true /* isAppAnimation */, 0 /* windowCornerRadius */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(rect -> rect.equals(mStackBounds))); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java index da1defabeaaf..0dec8ee7776f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java @@ -82,6 +82,8 @@ class WindowTestUtils { }, new ComponentName("", ""), false, dc, true /* fillsParent */); mTargetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT; mSkipOnParentChanged = skipOnParentChanged; + mActivityRecord = mock(ActivityRecord.class); + mActivityRecord.app = mock(WindowProcessController.class); } int getWindowsCount() { diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index eb99d5dcaaeb..bb85be16eb3a 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -139,7 +139,7 @@ public class ImsMmTelManager { if (mLocalCallback == null) return; Binder.withCleanCallingIdentity(() -> - mExecutor.execute(() -> mLocalCallback.onDeregistered(info))); + mExecutor.execute(() -> mLocalCallback.onUnregistered(info))); } @Override @@ -199,7 +199,7 @@ public class ImsMmTelManager { * * @param info the {@link ImsReasonInfo} associated with why registration was disconnected. */ - public void onDeregistered(ImsReasonInfo info) { + public void onUnregistered(ImsReasonInfo info) { } /** @@ -485,7 +485,7 @@ public class ImsMmTelManager { * @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL - * @see #setAdvancedCallingSetting(boolean) + * @see #setAdvancedCallingSettingEnabled(boolean) * @return true if the user's setting for advanced calling is enabled, false otherwise. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @@ -519,9 +519,9 @@ public class ImsMmTelManager { * @see #isAdvancedCallingSettingEnabled() */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) - public void setAdvancedCallingSetting(boolean isEnabled) { + public void setAdvancedCallingSettingEnabled(boolean isEnabled) { try { - getITelephony().setAdvancedCallingSetting(mSubId, isEnabled); + getITelephony().setAdvancedCallingSettingEnabled(mSubId, isEnabled); return; } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -589,7 +589,7 @@ public class ImsMmTelManager { /** * The user's setting for whether or not they have enabled the "Video Calling" setting. * @return true if the user’s “Video Calling” setting is currently enabled. - * @see #setVtSetting(boolean) + * @see #setVtSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled() { @@ -605,9 +605,9 @@ public class ImsMmTelManager { * @see #isVtSettingEnabled() */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) - public void setVtSetting(boolean isEnabled) { + public void setVtSettingEnabled(boolean isEnabled) { try { - getITelephony().setVtSetting(mSubId, isEnabled); + getITelephony().setVtSettingEnabled(mSubId, isEnabled); return; } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -616,7 +616,7 @@ public class ImsMmTelManager { /** * @return true if the user's setting for Voice over WiFi is enabled and false if it is not. - * @see #setVoWiFiSetting(boolean) + * @see #setVoWiFiSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled() { @@ -633,9 +633,9 @@ public class ImsMmTelManager { * @see #isVoWiFiSettingEnabled() */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) - public void setVoWiFiSetting(boolean isEnabled) { + public void setVoWiFiSettingEnabled(boolean isEnabled) { try { - getITelephony().setVoWiFiSetting(mSubId, isEnabled); + getITelephony().setVoWiFiSettingEnabled(mSubId, isEnabled); return; } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -645,7 +645,7 @@ public class ImsMmTelManager { /** * @return true if the user's setting for Voice over WiFi while roaming is enabled, false * if disabled. - * @see #setVoWiFiRoamingSetting(boolean) + * @see #setVoWiFiRoamingSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled() { @@ -663,9 +663,9 @@ public class ImsMmTelManager { * @see #isVoWiFiRoamingSettingEnabled() */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) - public void setVoWiFiRoamingSetting(boolean isEnabled) { + public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) { try { - getITelephony().setVoWiFiRoamingSetting(mSubId, isEnabled); + getITelephony().setVoWiFiRoamingSettingEnabled(mSubId, isEnabled); return; } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -682,7 +682,7 @@ public class ImsMmTelManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} - * @see #setVoWiFiSetting(boolean) + * @see #setVoWiFiSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean isCapable, int mode) { @@ -700,7 +700,7 @@ public class ImsMmTelManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} - * @see #setVoWiFiSetting(boolean) + * @see #setVoWiFiSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @WiFiCallingMode int getVoWiFiModeSetting() { @@ -739,7 +739,7 @@ public class ImsMmTelManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} - * @see #setVoWiFiRoamingSetting(boolean) + * @see #setVoWiFiRoamingSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @WiFiCallingMode int getVoWiFiRoamingModeSetting() { diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 0a8890fc3d94..5c5d44a8f42e 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1701,7 +1701,7 @@ interface ITelephony { /** * Modify the user's setting for whether or not 4G LTE is enabled. */ - void setAdvancedCallingSetting(int subId, boolean isEnabled); + void setAdvancedCallingSettingEnabled(int subId, boolean isEnabled); /** * return true if the user's setting for VT is enabled for the subscription. @@ -1711,7 +1711,7 @@ interface ITelephony { /** * Modify the user's setting for whether or not VT is available for the subscrption specified. */ - void setVtSetting(int subId, boolean isEnabled); + void setVtSettingEnabled(int subId, boolean isEnabled); /** * return true if the user's setting for whether or not Voice over WiFi is currently enabled. @@ -1721,7 +1721,7 @@ interface ITelephony { /** * sets the user's setting for Voice over WiFi enabled state. */ - void setVoWiFiSetting(int subId, boolean isEnabled); + void setVoWiFiSettingEnabled(int subId, boolean isEnabled); /** * return true if the user's setting for Voice over WiFi while roaming is enabled. @@ -1732,7 +1732,7 @@ interface ITelephony { * Sets the user's preference for whether or not Voice over WiFi is enabled for the current * subscription while roaming. */ - void setVoWiFiRoamingSetting(int subId, boolean isEnabled); + void setVoWiFiRoamingSettingEnabled(int subId, boolean isEnabled); /** * Set the Voice over WiFi enabled state, but do not persist the setting. diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java index 316aad343d19..818d899413de 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java @@ -53,7 +53,7 @@ public class PositionListenerActivity extends Activity { MyPositionReporter(Context c) { super(c); mNode = new RenderNode("positionListener"); - mNode.requestPositionUpdates(this); + mNode.addPositionUpdateListener(this); setTextAlignment(TEXT_ALIGNMENT_VIEW_START); } |