diff options
59 files changed, 725 insertions, 860 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 0c118114d159..4af2c5271d20 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1893,6 +1893,7 @@ package android { field public static final int windowFullscreen = 16843277; // 0x101020d field public static final int windowHideAnimation = 16842935; // 0x10100b7 field public static final int windowIsFloating = 16842839; // 0x1010057 + field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final int windowIsFrameRatePowerSavingsBalanced; field public static final int windowIsTranslucent = 16842840; // 0x1010058 field public static final int windowLayoutAffinity = 16844313; // 0x1010619 field public static final int windowLayoutInDisplayCutoutMode = 16844166; // 0x1010586 @@ -4488,6 +4489,7 @@ package android.app { method @CallSuper public void onActionModeStarted(android.view.ActionMode); method public void onActivityReenter(int, android.content.Intent); method protected void onActivityResult(int, int, android.content.Intent); + method @FlaggedApi("android.security.content_uri_permission_apis") public void onActivityResult(int, int, @NonNull android.content.Intent, @NonNull android.app.ComponentCaller); method @Deprecated public void onAttachFragment(android.app.Fragment); method public void onAttachedToWindow(); method @Deprecated public void onBackPressed(); @@ -18055,24 +18057,6 @@ package android.graphics.pdf { method public android.graphics.pdf.PdfDocument.PageInfo.Builder setContentRect(android.graphics.Rect); } - public final class PdfRenderer implements java.lang.AutoCloseable { - ctor public PdfRenderer(@NonNull android.os.ParcelFileDescriptor) throws java.io.IOException; - method public void close(); - method public int getPageCount(); - method public android.graphics.pdf.PdfRenderer.Page openPage(int); - method public boolean shouldScaleForPrinting(); - } - - public final class PdfRenderer.Page implements java.lang.AutoCloseable { - method public void close(); - method public int getHeight(); - method public int getIndex(); - method public int getWidth(); - method public void render(@NonNull android.graphics.Bitmap, @Nullable android.graphics.Rect, @Nullable android.graphics.Matrix, int); - field public static final int RENDER_MODE_FOR_DISPLAY = 1; // 0x1 - field public static final int RENDER_MODE_FOR_PRINT = 2; // 0x2 - } - } package android.graphics.text { @@ -18596,6 +18580,7 @@ package android.hardware { @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public final class OverlayProperties implements android.os.Parcelable { method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public int describeContents(); + method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public boolean isCombinationSupported(int, int); method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public boolean isMixedColorSpacesSupported(); method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public void writeToParcel(@NonNull android.os.Parcel, int); field @FlaggedApi("android.hardware.flags.overlayproperties_class_api") @NonNull public static final android.os.Parcelable.Creator<android.hardware.OverlayProperties> CREATOR; @@ -19329,6 +19314,7 @@ package android.hardware.camera2 { public abstract static class CameraExtensionSession.ExtensionCaptureCallback { ctor public CameraExtensionSession.ExtensionCaptureCallback(); method public void onCaptureFailed(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest); + method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureFailed(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest, int); method public void onCaptureProcessProgressed(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest, @IntRange(from=0, to=100) int); method public void onCaptureProcessStarted(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest); method public void onCaptureResultAvailable(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest, @NonNull android.hardware.camera2.TotalCaptureResult); @@ -26097,7 +26083,6 @@ package android.media.metrics { method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.media.metrics.MediaItemInfo> CREATOR; field public static final long DATA_TYPE_AUDIO = 4L; // 0x4L - field public static final long DATA_TYPE_CUE_POINTS = 128L; // 0x80L field public static final long DATA_TYPE_DEPTH = 16L; // 0x10L field public static final long DATA_TYPE_GAIN_MAP = 32L; // 0x20L field public static final long DATA_TYPE_GAPLESS = 256L; // 0x100L @@ -26106,6 +26091,7 @@ package android.media.metrics { field public static final long DATA_TYPE_IMAGE = 1L; // 0x1L field public static final long DATA_TYPE_METADATA = 8L; // 0x8L field public static final long DATA_TYPE_SPATIAL_AUDIO = 512L; // 0x200L + field public static final long DATA_TYPE_SPEED_SETTING_CUE_POINTS = 128L; // 0x80L field public static final long DATA_TYPE_VIDEO = 2L; // 0x2L field public static final int SOURCE_TYPE_CAMERA = 2; // 0x2 field public static final int SOURCE_TYPE_EDITING_SESSION = 3; // 0x3 @@ -54098,6 +54084,7 @@ package android.view { method public abstract void invalidatePanelMenu(int); method public final boolean isActive(); method public abstract boolean isFloating(); + method @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public boolean isFrameRatePowerSavingsBalanced(); method public boolean isNavigationBarContrastEnforced(); method public abstract boolean isShortcutKey(int, android.view.KeyEvent); method @Deprecated public boolean isStatusBarContrastEnforced(); @@ -54147,6 +54134,7 @@ package android.view { method public void setFlags(int, int); method public void setFormat(int); method @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public void setFrameRateBoostOnTouchEnabled(boolean); + method @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public void setFrameRatePowerSavingsBalanced(boolean); method public void setGravity(int); method @RequiresPermission(android.Manifest.permission.HIDE_OVERLAY_WINDOWS) public final void setHideOverlayWindows(boolean); method public void setIcon(@DrawableRes int); @@ -54518,6 +54506,7 @@ package android.view { method @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public boolean getFrameRateBoostOnTouchEnabled(); method public final CharSequence getTitle(); method public boolean isFitInsetsIgnoringVisibility(); + method @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public boolean isFrameRatePowerSavingsBalanced(); method public boolean isHdrConversionEnabled(); method public static boolean mayUseInputMethod(int); method public void setBlurBehindRadius(@IntRange(from=0) int); @@ -54528,6 +54517,7 @@ package android.view { method public void setFitInsetsSides(int); method public void setFitInsetsTypes(int); method @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public void setFrameRateBoostOnTouchEnabled(boolean); + method @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public void setFrameRatePowerSavingsBalanced(boolean); method public void setHdrConversionEnabled(boolean); method public final void setTitle(CharSequence); method public void setWallpaperTouchEventsEnabled(boolean); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 15de42afbc66..af5ea217ff3f 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -4828,7 +4828,7 @@ package android.hardware.camera2.extension { @FlaggedApi("com.android.internal.camera.flags.concert_mode") public static interface SessionProcessor.CaptureCallback { method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureCompleted(long, int, @NonNull android.hardware.camera2.CaptureResult); - method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureFailed(int); + method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureFailed(int, int); method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureProcessStarted(int); method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureSequenceAborted(int); method @FlaggedApi("com.android.internal.camera.flags.concert_mode") public void onCaptureSequenceCompleted(int); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index fae9f839317b..251f82320ae5 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -858,11 +858,15 @@ public class Activity extends ContextThemeWrapper */ private ComponentCaller mCaller; /** - * Caller associated with an Intent within {@link #onNewIntent}. Can be retrieved from - * {@link #getCurrentCaller}, or by overriding {@link #onNewIntent(Intent, ComponentCaller)} and - * getting the second argument. + * Caller associated with an Intent within {@link #onNewIntent} and {@link #onActivityResult}. + * Can be retrieved from either of these methods: + * - {@link #getCurrentCaller} + * - By overriding {@link #onNewIntent(Intent, ComponentCaller)} and getting the second argument + * - By overriding {@link #onActivityResult(int, int, Intent, ComponentCaller)} and getting the + * fourth argument * - * <p>The value of this field will be {@code null} outside of {@link #onNewIntent}. + * <p>The value of this field will be {@code null} outside of {@link #onNewIntent} and + * {@link #onActivityResult}. */ private ComponentCaller mCurrentCaller; @@ -7138,13 +7142,15 @@ public class Activity extends ContextThemeWrapper /** * Returns the ComponentCaller instance of the app that re-launched this activity with a new - * intent via {@link #onNewIntent}. + * intent via {@link #onNewIntent} or {@link #onActivityResult}. * - * <p>Note that this method only works within the {@link #onNewIntent} method. If you call this - * method outside {@link #onNewIntent}, it will throw an {@link IllegalStateException}. + * <p>Note that this method only works within the {@link #onNewIntent} and + * {@link #onActivityResult} methods. If you call this method outside {@link #onNewIntent} and + * {@link #onActivityResult}, it will throw an {@link IllegalStateException}. * * <p>You can also retrieve the caller if you override - * {@link #onNewIntent(Intent, ComponentCaller)}. + * {@link #onNewIntent(Intent, ComponentCaller)} or + * {@link #onActivityResult(int, int, Intent, ComponentCaller)}. * * <p>To keep the ComponentCaller instance for future use, call * {@link #setIntent(Intent, ComponentCaller)}, and use {@link #getCaller} to retrieve it. @@ -7425,6 +7431,31 @@ public class Activity extends ContextThemeWrapper } /** + * Same as {@link #onActivityResult(int, int, Intent)}, but with an extra parameter for the + * ComponentCaller instance associated with the app that sent the result. + * + * <p>If you want to retrieve the caller without overriding this method, call + * {@link #getCurrentCaller} inside your existing {@link #onActivityResult(int, int, Intent)}. + * + * <p>Note that you should only override one {@link #onActivityResult} method. + * + * @param requestCode The integer request code originally supplied to + * startActivityForResult(), allowing you to identify who this + * result came from. + * @param resultCode The integer result code returned by the child activity + * through its setResult(). + * @param data An Intent, which can return result data to the caller + * (various data can be attached to Intent "extras"). + * @param caller The {@link ComponentCaller} instance associated with the app that sent the + * intent. + */ + @FlaggedApi(android.security.Flags.FLAG_CONTENT_URI_PERMISSION_APIS) + public void onActivityResult(int requestCode, int resultCode, @NonNull Intent data, + @NonNull ComponentCaller caller) { + onActivityResult(requestCode, resultCode, data); + } + + /** * Called when an activity you launched with an activity transition exposes this * Activity through a returning activity transition, giving you the resultCode * and any additional data from it. This method will only be called if the activity @@ -9268,15 +9299,36 @@ public class Activity extends ContextThemeWrapper } } + void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data, + ComponentCaller caller, String reason) { + internalDispatchActivityResult(who, requestCode, resultCode, data, caller, reason); + } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data, String reason) { + if (android.security.Flags.contentUriPermissionApis()) { + internalDispatchActivityResult(who, requestCode, resultCode, data, + new ComponentCaller(getActivityToken(), /* callerToken */ null), reason); + } else { + internalDispatchActivityResult(who, requestCode, resultCode, data, null, reason); + } + } + + private void internalDispatchActivityResult(String who, int requestCode, int resultCode, + Intent data, ComponentCaller caller, String reason) { if (false) Log.v( TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode + ", resCode=" + resultCode + ", data=" + data); mFragments.noteStateNotSaved(); if (who == null) { - onActivityResult(requestCode, resultCode, data); + if (android.security.Flags.contentUriPermissionApis()) { + mCurrentCaller = caller; + onActivityResult(requestCode, resultCode, data, caller); + mCurrentCaller = null; + } else { + onActivityResult(requestCode, resultCode, data); + } } else if (who.startsWith(REQUEST_PERMISSIONS_WHO_PREFIX)) { who = who.substring(REQUEST_PERMISSIONS_WHO_PREFIX.length()); if (TextUtils.isEmpty(who)) { diff --git a/core/java/android/app/ActivityGroup.java b/core/java/android/app/ActivityGroup.java index cb06eea2059e..21c67edc607e 100644 --- a/core/java/android/app/ActivityGroup.java +++ b/core/java/android/app/ActivityGroup.java @@ -111,7 +111,7 @@ public class ActivityGroup extends Activity { @Override void dispatchActivityResult(String who, int requestCode, int resultCode, - Intent data, String reason) { + Intent data, ComponentCaller caller, String reason) { if (who != null) { Activity act = mLocalActivityManager.getActivity(who); /* @@ -125,7 +125,7 @@ public class ActivityGroup extends Activity { return; } } - super.dispatchActivityResult(who, requestCode, resultCode, data, reason); + super.dispatchActivityResult(who, requestCode, resultCode, data, caller, reason); } } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 00ccd043a5a7..926e297a1098 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3758,7 +3758,7 @@ public final class ActivityThread extends ClientTransactionHandler if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id + " req=" + requestCode + " res=" + resultCode + " data=" + data); final ArrayList<ResultInfo> list = new ArrayList<>(); - list.add(new ResultInfo(id, requestCode, resultCode, data)); + list.add(new ResultInfo(id, requestCode, resultCode, data, activityToken)); final ClientTransaction clientTransaction = ClientTransaction.obtain(mAppThread); final ActivityResultItem activityResultItem = ActivityResultItem.obtain( activityToken, list); @@ -5799,8 +5799,14 @@ public final class ActivityThread extends ClientTransactionHandler } if (DEBUG_RESULTS) Slog.v(TAG, "Delivering result to activity " + r + " : " + ri); - r.activity.dispatchActivityResult(ri.mResultWho, - ri.mRequestCode, ri.mResultCode, ri.mData, reason); + if (android.security.Flags.contentUriPermissionApis()) { + ComponentCaller caller = new ComponentCaller(r.token, ri.mCallerToken); + r.activity.dispatchActivityResult(ri.mResultWho, + ri.mRequestCode, ri.mResultCode, ri.mData, caller, reason); + } else { + r.activity.dispatchActivityResult(ri.mResultWho, + ri.mRequestCode, ri.mResultCode, ri.mData, reason); + } } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( diff --git a/core/java/android/app/ResultInfo.java b/core/java/android/app/ResultInfo.java index 535f69f0e264..213c38c71543 100644 --- a/core/java/android/app/ResultInfo.java +++ b/core/java/android/app/ResultInfo.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.content.Intent; import android.os.Build; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; @@ -36,14 +37,21 @@ public class ResultInfo implements Parcelable { public final int mResultCode; @UnsupportedAppUsage public final Intent mData; + public final IBinder mCallerToken; @UnsupportedAppUsage public ResultInfo(String resultWho, int requestCode, int resultCode, Intent data) { + this(resultWho, requestCode, resultCode, data, /* callerToken */ null); + } + + public ResultInfo(String resultWho, int requestCode, int resultCode, + Intent data, IBinder callerToken) { mResultWho = resultWho; mRequestCode = requestCode; mResultCode = resultCode; mData = data; + mCallerToken = callerToken; } public String toString() { @@ -65,6 +73,7 @@ public class ResultInfo implements Parcelable { } else { out.writeInt(0); } + out.writeStrongBinder(mCallerToken); } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @@ -88,6 +97,7 @@ public class ResultInfo implements Parcelable { } else { mData = null; } + mCallerToken = in.readStrongBinder(); } @Override @@ -100,7 +110,8 @@ public class ResultInfo implements Parcelable { : mData.filterEquals(other.mData); return intentsEqual && Objects.equals(mResultWho, other.mResultWho) && mResultCode == other.mResultCode - && mRequestCode == other.mRequestCode; + && mRequestCode == other.mRequestCode + && mCallerToken == other.mCallerToken; } @Override @@ -112,6 +123,7 @@ public class ResultInfo implements Parcelable { if (mData != null) { result = 31 * result + mData.filterHashCode(); } + result = 31 * result + Objects.hashCode(mCallerToken); return result; } } diff --git a/core/java/android/hardware/OverlayProperties.java b/core/java/android/hardware/OverlayProperties.java index 72586b2b22cb..88089eed50f4 100644 --- a/core/java/android/hardware/OverlayProperties.java +++ b/core/java/android/hardware/OverlayProperties.java @@ -71,17 +71,36 @@ public final class OverlayProperties implements Parcelable { /** * @return True if the device can support fp16, false otherwise. + * TODO: Move this to isCombinationSupported once the flag flips * @hide */ public boolean isFp16SupportedForHdr() { if (mNativeObject == 0) { return false; } - return nSupportFp16ForHdr(mNativeObject); + return nIsCombinationSupported( + mNativeObject, DataSpace.DATASPACE_SCRGB, HardwareBuffer.RGBA_FP16); } /** - * Indicates that hw composition of two or more overlays + * Indicates that hardware composition of a buffer encoded with the provided {@link DataSpace} + * and {@link HardwareBuffer.Format} is supported on the device. + * + * @return True if the device can support efficiently compositing the content described by the + * dataspace and format. False if GPOU composition fallback is otherwise required. + */ + @FlaggedApi(Flags.FLAG_OVERLAYPROPERTIES_CLASS_API) + public boolean isCombinationSupported(@DataSpace.ColorDataSpace int dataspace, + @HardwareBuffer.Format int format) { + if (mNativeObject == 0) { + return false; + } + + return nIsCombinationSupported(mNativeObject, dataspace, format); + } + + /** + * Indicates that hardware composition of two or more overlays * with different colorspaces is supported on the device. * * @return True if the device can support mixed colorspaces efficiently, @@ -131,6 +150,8 @@ public final class OverlayProperties implements Parcelable { private static native long nCreateDefault(); private static native boolean nSupportFp16ForHdr(long nativeObject); private static native boolean nSupportMixedColorSpaces(long nativeObject); + private static native boolean nIsCombinationSupported( + long nativeObject, int dataspace, int format); private static native void nWriteOverlayPropertiesToParcel(long nativeObject, Parcel dest); private static native long nReadOverlayPropertiesFromParcel(Parcel in); } diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java index f6b22edaafb1..76c20ce2184a 100644 --- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java @@ -808,13 +808,11 @@ public final class CameraExtensionCharacteristics { extender.init(mCameraId, mCharacteristicsMapNative); CameraMetadataNative metadata = extender.getAvailableCharacteristicsKeyValues(mCameraId); - CameraCharacteristics fallbackCharacteristics = mCharacteristicsMap.get(mCameraId); if (metadata == null) { - return fallbackCharacteristics.get(key); + return null; } CameraCharacteristics characteristics = new CameraCharacteristics(metadata); - T value = characteristics.get(key); - return value == null ? fallbackCharacteristics.get(key) : value; + return characteristics.get(key); } } catch (RemoteException e) { Log.e(TAG, "Failed to query the extension for the specified key! Extension " diff --git a/core/java/android/hardware/camera2/CameraExtensionSession.java b/core/java/android/hardware/camera2/CameraExtensionSession.java index 21fead980cdd..2d9433e31ab2 100644 --- a/core/java/android/hardware/camera2/CameraExtensionSession.java +++ b/core/java/android/hardware/camera2/CameraExtensionSession.java @@ -16,11 +16,14 @@ package android.hardware.camera2; +import android.annotation.FlaggedApi; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.camera2.utils.HashCodeHelpers; +import com.android.internal.camera.flags.Flags; + import java.util.concurrent.Executor; /** @@ -132,6 +135,34 @@ public abstract class CameraExtensionSession implements AutoCloseable { } /** + * This method is called instead of + * {@link #onCaptureProcessStarted} when the camera device failed + * to produce the required input for the device-specific extension. The + * cause could be a failed camera capture request, a failed + * capture result or dropped camera frame. More information about + * the reason is included in the 'failure' argument. + * + * <p>Other requests are unaffected, and some or all image buffers + * from the capture may have been pushed to their respective output + * streams.</p> + * + * <p>The default implementation of this method does nothing.</p> + * + * @param session the session received during + * {@link StateCallback#onConfigured(CameraExtensionSession)} + * @param request The request that was given to the CameraDevice + * @param failure The capture failure reason + * + * @see #capture + * @see #setRepeatingRequest + */ + @FlaggedApi(Flags.FLAG_CONCERT_MODE) + public void onCaptureFailed(@NonNull CameraExtensionSession session, + @NonNull CaptureRequest request, @CaptureFailure.FailureReason int failure) { + // default empty implementation + } + + /** * This method is called independently of the others in * ExtensionCaptureCallback, when a capture sequence finishes. * diff --git a/core/java/android/hardware/camera2/extension/ICaptureCallback.aidl b/core/java/android/hardware/camera2/extension/ICaptureCallback.aidl index 02a4690c3b77..b1f10ee103c1 100644 --- a/core/java/android/hardware/camera2/extension/ICaptureCallback.aidl +++ b/core/java/android/hardware/camera2/extension/ICaptureCallback.aidl @@ -15,6 +15,7 @@ */ package android.hardware.camera2.extension; +import android.hardware.camera2.extension.CaptureFailure; import android.hardware.camera2.extension.Request; import android.hardware.camera2.impl.CameraMetadataNative; @@ -28,4 +29,5 @@ interface ICaptureCallback void onCaptureSequenceAborted(int captureSequenceId); void onCaptureCompleted(long shutterTimestamp, int requestId, in CameraMetadataNative results); void onCaptureProcessProgressed(int progress); + void onCaptureProcessFailed(int captureSequenceId, int captureFailureReason); } diff --git a/core/java/android/hardware/camera2/extension/SessionProcessor.java b/core/java/android/hardware/camera2/extension/SessionProcessor.java index e7cc5303fc18..d8594e5e1175 100644 --- a/core/java/android/hardware/camera2/extension/SessionProcessor.java +++ b/core/java/android/hardware/camera2/extension/SessionProcessor.java @@ -18,8 +18,10 @@ package android.hardware.camera2.extension; import android.annotation.FlaggedApi; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; import android.hardware.camera2.impl.CameraExtensionUtils.HandlerExecutor; @@ -132,13 +134,14 @@ public abstract class SessionProcessor { * This method is called instead of * {@link #onCaptureProcessStarted} when the camera device failed * to produce the required input for the device-specific - * extension. The cause could be a failed camera capture request, - * a failed capture result or dropped camera frame. + * extension. The callback allows clients to be notified + * about failure reason. * * @param captureSequenceId id of the current capture sequence + * @param failure The capture failure reason */ @FlaggedApi(Flags.FLAG_CONCERT_MODE) - void onCaptureFailed(int captureSequenceId); + void onCaptureFailed(int captureSequenceId, @CaptureFailure.FailureReason int failure); /** * This method is called independently of the others in the @@ -474,9 +477,9 @@ public abstract class SessionProcessor { } @Override - public void onCaptureFailed(int captureSequenceId) { + public void onCaptureFailed(int captureSequenceId, int failure) { try { - mCaptureCallback.onCaptureFailed(captureSequenceId); + mCaptureCallback.onCaptureProcessFailed(captureSequenceId, failure); } catch (RemoteException e) { Log.e(TAG, "Failed to notify capture failure start due to remote exception!"); } diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java index b2032fa3db81..a7d6caf9d9df 100644 --- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java @@ -66,6 +66,8 @@ import android.util.Log; import android.util.Size; import android.view.Surface; +import com.android.internal.camera.flags.Flags; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -779,6 +781,22 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes } @Override + public void onCaptureProcessFailed(int captureSequenceId, int captureFailureReason) { + if (Flags.concertMode()) { + final long ident = Binder.clearCallingIdentity(); + try { + mClientExecutor.execute( + () -> mClientCallbacks.onCaptureFailed( + CameraAdvancedExtensionSessionImpl.this, mClientRequest, + captureFailureReason + )); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + @Override public void onCaptureSequenceCompleted(int captureSequenceId) { final long ident = Binder.clearCallingIdentity(); try { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9474a698c1a9..75deceb5826f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1022,6 +1022,11 @@ public final class ViewRootImpl implements ViewParent, // Used to check if there is a message in the message queue // for idleness handling. private boolean mHasIdledMessage = false; + // Used to allow developers to opt out Toolkit dVRR feature. + // This feature allows device to adjust refresh rate + // as needed and can be useful for power saving. + // Should not enable the dVRR feature if the value is false. + private boolean mIsFrameRatePowerSavingsBalanced = true; // time for touch boost period. private static final int FRAME_RATE_TOUCH_BOOST_TIME = 3000; // time for checking idle status periodically. @@ -2533,8 +2538,10 @@ public final class ViewRootImpl implements ViewParent, // Set the frame rate selection strategy to FRAME_RATE_SELECTION_STRATEGY_SELF // This strategy ensures that the frame rate specifications do not cascade down to // the descendant layers. This is particularly important for applications like Chrome, - // where child surfaces should adhere to default behavior instead of no preference - if (sToolkitSetFrameRateReadOnlyFlagValue) { + // where child surfaces should adhere to default behavior instead of no preference. + // This issue only happens when ViewRootImpl calls setFrameRateCategory. This is + // no longer needed if the dVRR feature is disabled. + if (shouldEnableDvrr()) { try { mFrameRateTransaction.setFrameRateSelectionStrategy(sc, sc.FRAME_RATE_SELECTION_STRATEGY_SELF).applyAsyncUnsafe(); @@ -3258,7 +3265,7 @@ public final class ViewRootImpl implements ViewParent, destroyHardwareResources(); } - if (sToolkitSetFrameRateReadOnlyFlagValue && viewVisibility == View.VISIBLE) { + if (shouldEnableDvrr() && viewVisibility == View.VISIBLE) { // Boost frame rate when the viewVisibility becomes true. // This is mainly for lanuchers that lanuch new windows. boostFrameRate(FRAME_RATE_TOUCH_BOOST_TIME); @@ -3973,7 +3980,7 @@ public final class ViewRootImpl implements ViewParent, } } - if (sToolkitSetFrameRateReadOnlyFlagValue) { + if (shouldEnableDvrr()) { // Boost the frame rate when the ViewRootImpl first becomes available. boostFrameRate(FRAME_RATE_TOUCH_BOOST_TIME); } @@ -5187,7 +5194,10 @@ public final class ViewRootImpl implements ViewParent, // Force recalculation of transparent regions if (accessibilityFocusDirty) { - requestLayout(); + final Rect bounds = mAttachInfo.mTmpInvalRect; + if (getAccessibilityFocusedRect(bounds)) { + requestLayout(); + } } mAttachInfo.mDrawingTime = @@ -12340,12 +12350,12 @@ public final class ViewRootImpl implements ViewParent, private boolean shouldSetFrameRateCategory() { // use toolkitSetFrameRate flag to gate the change - return mSurface.isValid() && sToolkitSetFrameRateReadOnlyFlagValue; + return mSurface.isValid() && shouldEnableDvrr(); } private boolean shouldSetFrameRate() { // use toolkitSetFrameRate flag to gate the change - return sToolkitSetFrameRateReadOnlyFlagValue; + return mSurface.isValid() && mPreferredFrameRate > 0 && shouldEnableDvrr(); } private boolean shouldTouchBoost(int motionEventAction, int windowType) { @@ -12354,7 +12364,7 @@ public final class ViewRootImpl implements ViewParent, || motionEventAction == MotionEvent.ACTION_UP; boolean undesiredType = windowType == TYPE_INPUT_METHOD && mShouldSuppressBoostOnTyping; // use toolkitSetFrameRate flag to gate the change - return desiredAction && !undesiredType && sToolkitSetFrameRateReadOnlyFlagValue + return desiredAction && !undesiredType && shouldEnableDvrr() && getFrameRateBoostOnTouchEnabled(); } @@ -12476,4 +12486,27 @@ public final class ViewRootImpl implements ViewParent, // Record the largest view of percentage to the display size. mLargestChildPercentage = Math.max(percentage, mLargestChildPercentage); } + + /** + * Get the value of mIsFrameRatePowerSavingsBalanced + * Can be used to checked if toolkit dVRR feature is enabled. The default value is true. + */ + @VisibleForTesting + public boolean isFrameRatePowerSavingsBalanced() { + return mIsFrameRatePowerSavingsBalanced; + } + + /** + * Set the value of mIsFrameRatePowerSavingsBalanced + * Can be used to checked if toolkit dVRR feature is enabled. + */ + public void setFrameRatePowerSavingsBalanced(boolean enabled) { + if (sToolkitSetFrameRateReadOnlyFlagValue) { + mIsFrameRatePowerSavingsBalanced = enabled; + } + } + + private boolean shouldEnableDvrr() { + return sToolkitSetFrameRateReadOnlyFlagValue && mIsFrameRatePowerSavingsBalanced; + } } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 4ba4ee3ffff7..6b427fc00766 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -1409,6 +1409,42 @@ public abstract class Window { } /** + * Set whether frameratepowersavingsbalance is enabled for this Window. + * This allows device to adjust refresh rate + * as needed and can be useful for power saving. + * + * @param enabled whether the frameratepowersavingsbalance is enabled. + * @see #isFrameRatePowerSavingsBalanced() + * @see WindowManager.LayoutParams#setFrameRatePowerSavingsBalanced(boolean) + */ + @FlaggedApi(android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) + public void setFrameRatePowerSavingsBalanced(boolean enabled) { + if (sToolkitSetFrameRateReadOnlyFlagValue) { + final WindowManager.LayoutParams attrs = getAttributes(); + attrs.setFrameRatePowerSavingsBalanced(enabled); + dispatchWindowAttributesChanged(attrs); + } + } + + /** + * Get whether frameratepowersavingsbalance is enabled for this Window. + * This allows device to adjust refresh rate + * as needed and can be useful for power saving. + * {@link #setFrameRateBoostOnTouchEnabled(boolean)} + * + * @return whether the frameratepowersavingsbalance is enabled. + * @see #setFrameRatePowerSavingsBalanced(boolean) + * @see WindowManager.LayoutParams#isFrameRatePowerSavingsBalanced() + */ + @FlaggedApi(android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) + public boolean isFrameRatePowerSavingsBalanced() { + if (sToolkitSetFrameRateReadOnlyFlagValue) { + return getAttributes().isFrameRatePowerSavingsBalanced(); + } + return false; + } + + /** * If {@code isPreferred} is true, this method requests that the connected display does minimal * post processing when this window is visible on the screen. Otherwise, it requests that the * display switches back to standard image processing. diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index e4be016dac7a..0e17626c5598 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -4439,6 +4439,7 @@ public interface WindowManager extends ViewManager { * For variable refresh rate project. */ private boolean mFrameRateBoostOnTouch = true; + private boolean mIsFrameRatePowerSavingsBalanced = true; private static boolean sToolkitSetFrameRateReadOnlyFlagValue = android.view.flags.Flags.toolkitSetFrameRateReadOnly(); @@ -4903,6 +4904,36 @@ public interface WindowManager extends ViewManager { } /** + * Set the value whether frameratepowersavingsbalance is enabled for this Window. + * This allows device to adjust refresh rate + * as needed and can be useful for power saving. + * + * @param enabled Whether we should enable frameratepowersavingsbalance. + */ + @FlaggedApi(android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) + public void setFrameRatePowerSavingsBalanced(boolean enabled) { + if (sToolkitSetFrameRateReadOnlyFlagValue) { + mIsFrameRatePowerSavingsBalanced = enabled; + } + } + + /** + * Get the value whether frameratepowersavingsbalance is enabled for this Window. + * This allows device to adjust refresh rate + * as needed and can be useful for power saving. + * by {@link #setFrameRatePowerSavingsBalanced(boolean)} + * + * @return Whether we should enable frameratepowersavingsbalance. + */ + @FlaggedApi(android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) + public boolean isFrameRatePowerSavingsBalanced() { + if (sToolkitSetFrameRateReadOnlyFlagValue) { + return mIsFrameRatePowerSavingsBalanced; + } + return true; + } + + /** * <p> * Blurs the screen behind the window. The effect is similar to that of {@link #dimAmount}, * but instead of dimmed, the content behind the window will be blurred (or combined with @@ -5055,6 +5086,7 @@ public interface WindowManager extends ViewManager { out.writeFloat(mDesiredHdrHeadroom); if (sToolkitSetFrameRateReadOnlyFlagValue) { out.writeBoolean(mFrameRateBoostOnTouch); + out.writeBoolean(mIsFrameRatePowerSavingsBalanced); } } @@ -5130,6 +5162,7 @@ public interface WindowManager extends ViewManager { mDesiredHdrHeadroom = in.readFloat(); if (sToolkitSetFrameRateReadOnlyFlagValue) { mFrameRateBoostOnTouch = in.readBoolean(); + mIsFrameRatePowerSavingsBalanced = in.readBoolean(); } } @@ -5473,6 +5506,12 @@ public interface WindowManager extends ViewManager { changes |= LAYOUT_CHANGED; } + if (sToolkitSetFrameRateReadOnlyFlagValue + && mIsFrameRatePowerSavingsBalanced != o.mIsFrameRatePowerSavingsBalanced) { + mIsFrameRatePowerSavingsBalanced = o.mIsFrameRatePowerSavingsBalanced; + changes |= LAYOUT_CHANGED; + } + return changes; } @@ -5700,6 +5739,11 @@ public interface WindowManager extends ViewManager { sb.append(prefix).append(" frameRateBoostOnTouch="); sb.append(mFrameRateBoostOnTouch); } + if (sToolkitSetFrameRateReadOnlyFlagValue && mIsFrameRatePowerSavingsBalanced) { + sb.append(System.lineSeparator()); + sb.append(prefix).append(" dvrrWindowFrameRateHint="); + sb.append(mIsFrameRatePowerSavingsBalanced); + } if (paramsForRotation != null && paramsForRotation.length != 0) { sb.append(System.lineSeparator()); sb.append(prefix).append(" paramsForRotation:"); diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 523924566dd7..0dd01e48db0a 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -363,6 +363,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private boolean mUseDecorContext = false; + private boolean mIsFrameRatePowerSavingsBalanced = true; + /** @see ViewRootImpl#mActivityConfigCallback */ private ActivityConfigCallback mActivityConfigCallback; @@ -2211,6 +2213,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { void onViewRootImplSet(ViewRootImpl viewRoot) { viewRoot.setActivityConfigCallback(mActivityConfigCallback); viewRoot.getOnBackInvokedDispatcher().updateContext(getContext()); + viewRoot.setFrameRatePowerSavingsBalanced(mIsFrameRatePowerSavingsBalanced); mProxyOnBackInvokedDispatcher.setActualDispatcher(viewRoot.getOnBackInvokedDispatcher()); applyDecorFitsSystemWindows(); } @@ -2559,6 +2562,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (a.getBoolean(R.styleable.Window_windowActivityTransitions, false)) { requestFeature(FEATURE_ACTIVITY_TRANSITIONS); } + if (a.hasValue(R.styleable.Window_windowIsFrameRatePowerSavingsBalanced)) { + mIsFrameRatePowerSavingsBalanced = + a.getBoolean(R.styleable.Window_windowIsFrameRatePowerSavingsBalanced, true); + } mIsTranslucent = a.getBoolean(R.styleable.Window_windowIsTranslucent, false); diff --git a/core/jni/android_hardware_OverlayProperties.cpp b/core/jni/android_hardware_OverlayProperties.cpp index f6fe3dd842da..96494b16cc21 100644 --- a/core/jni/android_hardware_OverlayProperties.cpp +++ b/core/jni/android_hardware_OverlayProperties.cpp @@ -35,7 +35,6 @@ static struct { jclass clazz; jmethodID ctor; } gOverlayPropertiesClassInfo; - // ---------------------------------------------------------------------------- // OverlayProperties lifecycle // ---------------------------------------------------------------------------- @@ -52,21 +51,21 @@ static jlong android_hardware_OverlayProperties_getDestructor(JNIEnv*, jclass) { // Accessors // ---------------------------------------------------------------------------- -static jboolean android_hardware_OverlayProperties_supportFp16ForHdr(JNIEnv* env, jobject thiz, - jlong nativeObject) { +static jboolean android_hardware_OverlayProperties_isCombinationSupported(JNIEnv* env, jobject thiz, + jlong nativeObject, + jint dataspace, + jint format) { gui::OverlayProperties* properties = reinterpret_cast<gui::OverlayProperties*>(nativeObject); if (properties != nullptr) { for (const auto& i : properties->combinations) { - if (std::find(i.pixelFormats.begin(), i.pixelFormats.end(), - static_cast<int32_t>(HAL_PIXEL_FORMAT_RGBA_FP16)) != + if (std::find(i.pixelFormats.begin(), i.pixelFormats.end(), format) != i.pixelFormats.end() && std::find(i.standards.begin(), i.standards.end(), - static_cast<int32_t>(HAL_DATASPACE_STANDARD_BT709)) != - i.standards.end() && + dataspace & HAL_DATASPACE_STANDARD_MASK) != i.standards.end() && std::find(i.transfers.begin(), i.transfers.end(), - static_cast<int32_t>(HAL_DATASPACE_TRANSFER_SRGB)) != i.transfers.end() && - std::find(i.ranges.begin(), i.ranges.end(), - static_cast<int32_t>(HAL_DATASPACE_RANGE_EXTENDED)) != i.ranges.end()) { + dataspace & HAL_DATASPACE_TRANSFER_MASK) != i.transfers.end() && + std::find(i.ranges.begin(), i.ranges.end(), dataspace & HAL_DATASPACE_RANGE_MASK) != + i.ranges.end()) { return true; } } @@ -88,7 +87,7 @@ static jlong android_hardware_OverlayProperties_createDefault(JNIEnv* env, jobje gui::OverlayProperties* overlayProperties = new gui::OverlayProperties; gui::OverlayProperties::SupportedBufferCombinations combination; combination.pixelFormats = {HAL_PIXEL_FORMAT_RGBA_8888}; - combination.standards = {HAL_DATASPACE_BT709}; + combination.standards = {HAL_DATASPACE_STANDARD_BT709}; combination.transfers = {HAL_DATASPACE_TRANSFER_SRGB}; combination.ranges = {HAL_DATASPACE_RANGE_FULL}; overlayProperties->combinations.emplace_back(combination); @@ -153,8 +152,8 @@ const char* const kClassPathName = "android/hardware/OverlayProperties"; // clang-format off static const JNINativeMethod gMethods[] = { { "nGetDestructor", "()J", (void*) android_hardware_OverlayProperties_getDestructor }, - { "nSupportFp16ForHdr", "(J)Z", - (void*) android_hardware_OverlayProperties_supportFp16ForHdr }, + { "nIsCombinationSupported", "(JII)Z", + (void*) android_hardware_OverlayProperties_isCombinationSupported }, { "nSupportMixedColorSpaces", "(J)Z", (void*) android_hardware_OverlayProperties_supportMixedColorSpaces }, { "nWriteOverlayPropertiesToParcel", "(JLandroid/os/Parcel;)V", @@ -172,6 +171,5 @@ int register_android_hardware_OverlayProperties(JNIEnv* env) { gOverlayPropertiesClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); gOverlayPropertiesClassInfo.ctor = GetMethodIDOrDie(env, gOverlayPropertiesClassInfo.clazz, "<init>", "(J)V"); - return err; } diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index cc6460ea7d4d..c1fd61948e68 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2514,6 +2514,13 @@ <!-- The icon is shown unless the launching app specified SPLASH_SCREEN_STYLE_EMPTY --> <enum name="icon_preferred" value="1" /> </attr> + <!-- Offer Window the ability to opt out the UI Toolkit discrete variable refresh rate. + This feature allows device to adjust refresh rate as needed and + can be useful for power saving. + Set to false to reduce the frame rate optimizations on devices with + variable refresh rate screens. + The default is true. --> + <attr name="windowIsFrameRatePowerSavingsBalanced" format="boolean"/> <!-- Flag indicating whether this window would opt-out the edge-to-edge enforcement. diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml index 8af8cb84a217..c797210345a2 100644 --- a/core/res/res/values/public-staging.xml +++ b/core/res/res/values/public-staging.xml @@ -165,6 +165,8 @@ <public name="allowCrossUidActivitySwitchFromBelow"/> <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") --> <public name="shiftDrawingOffsetForStartOverhang" /> + <!-- @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") --> + <public name="windowIsFrameRatePowerSavingsBalanced"/> </staging-public-group> <staging-public-group type="id" first-id="0x01bc0000"> diff --git a/core/tests/coretests/res/values/styles.xml b/core/tests/coretests/res/values/styles.xml index 32eebb35e0c3..78cd1e1e47e8 100644 --- a/core/tests/coretests/res/values/styles.xml +++ b/core/tests/coretests/res/values/styles.xml @@ -55,4 +55,10 @@ <style name="ViewDefaultBackground"> <item name="android:background">#00000000</item> </style> + <style name="IsFrameRatePowerSavingsBalancedDisabled"> + <item name="android:windowIsFrameRatePowerSavingsBalanced">false</item> + </style> + <style name="IsFrameRatePowerSavingsBalancedEnabled"> + <item name="android:windowIsFrameRatePowerSavingsBalanced">true</item> + </style> </resources> diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java index 433d353e5074..038c00e3823c 100644 --- a/core/tests/coretests/src/android/view/ViewRootImplTest.java +++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java @@ -953,6 +953,22 @@ public class ViewRootImplTest { }); } + /** + * Test the IsFrameRatePowerSavingsBalanced values are properly set + */ + @UiThreadTest + @Test + @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) + public void votePreferredFrameRate_isFrameRatePowerSavingsBalanced() { + ViewRootImpl viewRootImpl = new ViewRootImpl(sContext, + sContext.getDisplayNoVerify()); + assertEquals(viewRootImpl.isFrameRatePowerSavingsBalanced(), true); + viewRootImpl.setFrameRatePowerSavingsBalanced(false); + assertEquals(viewRootImpl.isFrameRatePowerSavingsBalanced(), false); + viewRootImpl.setFrameRatePowerSavingsBalanced(true); + assertEquals(viewRootImpl.isFrameRatePowerSavingsBalanced(), true); + } + @Test public void forceInvertOffDarkThemeOff_forceDarkModeDisabled() { mSetFlagsRule.enableFlags(FLAG_FORCE_INVERT_COLOR); diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java index 3df3b9d2c555..b9841ff997e7 100644 --- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java +++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java @@ -21,17 +21,28 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import android.app.Instrumentation; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.os.Binder; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.view.ActionMode; import android.view.ContextThemeWrapper; +import android.view.ViewRootImpl; +import android.view.WindowManager; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -40,6 +51,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.coretests.R; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -54,6 +66,12 @@ public final class PhoneWindowTest { private PhoneWindow mPhoneWindow; private Context mContext; + private static Instrumentation sInstrumentation = + InstrumentationRegistry.getInstrumentation(); + + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @Before public void setUp() throws Exception { mContext = InstrumentationRegistry.getContext(); @@ -154,6 +172,48 @@ public final class PhoneWindowTest { assertThat(colorDrawable.getColor(), is(Color.BLUE)); } + @Test + @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) + public void testWindowFrameRateHint_disabled() { + createPhoneWindowWithTheme(R.style.IsFrameRatePowerSavingsBalancedDisabled); + installDecor(); + + DecorView decorView = (DecorView) mPhoneWindow.getDecorView(); + + WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY); + wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check + + sInstrumentation.runOnMainSync(() -> { + WindowManager wm = mContext.getSystemService(WindowManager.class); + wm.addView(decorView, wmlp); + }); + sInstrumentation.waitForIdleSync(); + + ViewRootImpl viewRootImpl = decorView.getViewRootImpl(); + assertFalse(viewRootImpl.isFrameRatePowerSavingsBalanced()); + } + + @Test + @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) + public void testWindowFrameRateHint_enabled() { + createPhoneWindowWithTheme(R.style.IsFrameRatePowerSavingsBalancedEnabled); + installDecor(); + + DecorView decorView = (DecorView) mPhoneWindow.getDecorView(); + + WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY); + wmlp.token = new Binder(); // Set a fake token to bypass 'is your activity running' check + + sInstrumentation.runOnMainSync(() -> { + WindowManager wm = mContext.getSystemService(WindowManager.class); + wm.addView(decorView, wmlp); + }); + sInstrumentation.waitForIdleSync(); + + ViewRootImpl viewRootImpl = decorView.getViewRootImpl(); + assertTrue(viewRootImpl.isFrameRatePowerSavingsBalanced()); + } + private void createPhoneWindowWithTheme(int theme) { mPhoneWindow = new PhoneWindow(new ContextThemeWrapper(mContext, theme)); } diff --git a/data/etc/com.android.intentresolver.xml b/data/etc/com.android.intentresolver.xml index af6492609157..afd4f7cdba53 100644 --- a/data/etc/com.android.intentresolver.xml +++ b/data/etc/com.android.intentresolver.xml @@ -17,8 +17,10 @@ <permissions> <privapp-permissions package="com.android.intentresolver"> <permission name="android.permission.INTERACT_ACROSS_USERS"/> + <permission name="android.permission.LOG_COMPAT_CHANGE"/> <permission name="android.permission.MANAGE_USERS"/> <permission name="android.permission.PACKAGE_USAGE_STATS"/> <permission name="android.permission.QUERY_CLONED_APPS"/> + <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> </privapp-permissions> </permissions> diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java index 3cd709ea10e5..69e19824da26 100644 --- a/graphics/java/android/graphics/pdf/PdfEditor.java +++ b/graphics/java/android/graphics/pdf/PdfEditor.java @@ -25,7 +25,9 @@ import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; + import dalvik.system.CloseGuard; + import libcore.io.IoUtils; import java.io.IOException; @@ -37,6 +39,12 @@ import java.io.IOException; */ public final class PdfEditor { + /** + * Any call the native pdfium code has to be single threaded as the library does not support + * parallel use. + */ + private static final Object sPdfiumLock = new Object(); + private final CloseGuard mCloseGuard = CloseGuard.get(); private long mNativeDocument; @@ -79,7 +87,7 @@ public final class PdfEditor { } mInput = input; - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { mNativeDocument = nativeOpen(mInput.getFd(), size); try { mPageCount = nativeGetPageCount(mNativeDocument); @@ -112,7 +120,7 @@ public final class PdfEditor { throwIfClosed(); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { mPageCount = nativeRemovePage(mNativeDocument, pageIndex); } } @@ -138,12 +146,12 @@ public final class PdfEditor { Point size = new Point(); getPageSize(pageIndex, size); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), 0, 0, size.x, size.y); } } else { - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.ni(), clip.left, clip.top, clip.right, clip.bottom); } @@ -161,7 +169,7 @@ public final class PdfEditor { throwIfOutSizeNull(outSize); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeGetPageSize(mNativeDocument, pageIndex, outSize); } } @@ -177,7 +185,7 @@ public final class PdfEditor { throwIfOutMediaBoxNull(outMediaBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox); } } @@ -193,7 +201,7 @@ public final class PdfEditor { throwIfMediaBoxNull(mediaBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox); } } @@ -209,7 +217,7 @@ public final class PdfEditor { throwIfOutCropBoxNull(outCropBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox); } } @@ -225,7 +233,7 @@ public final class PdfEditor { throwIfCropBoxNull(cropBox); throwIfPageNotInDocument(pageIndex); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox); } } @@ -238,7 +246,7 @@ public final class PdfEditor { public boolean shouldScaleForPrinting() { throwIfClosed(); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { return nativeScaleForPrinting(mNativeDocument); } } @@ -255,7 +263,7 @@ public final class PdfEditor { try { throwIfClosed(); - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeWrite(mNativeDocument, output.getFd()); } } finally { @@ -287,7 +295,7 @@ public final class PdfEditor { private void doClose() { if (mNativeDocument != 0) { - synchronized (PdfRenderer.sPdfiumLock) { + synchronized (sPdfiumLock) { nativeClose(mNativeDocument); } mNativeDocument = 0; diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java deleted file mode 100644 index 4666963b5dd4..000000000000 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2014 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.graphics.pdf; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.compat.annotation.UnsupportedAppUsage; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Matrix; -import android.graphics.Point; -import android.graphics.Rect; -import android.os.Build; -import android.os.ParcelFileDescriptor; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; - -import com.android.internal.util.Preconditions; - -import dalvik.system.CloseGuard; - -import libcore.io.IoUtils; - -import java.io.IOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * <p> - * This class enables rendering a PDF document. This class is not thread safe. - * </p> - * <p> - * If you want to render a PDF, you create a renderer and for every page you want - * to render, you open the page, render it, and close the page. After you are done - * with rendering, you close the renderer. After the renderer is closed it should not - * be used anymore. Note that the pages are rendered one by one, i.e. you can have - * only a single page opened at any given time. - * </p> - * <p> - * A typical use of the APIs to render a PDF looks like this: - * </p> - * <pre> - * // create a new renderer - * PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor()); - * - * // let us just render all pages - * final int pageCount = renderer.getPageCount(); - * for (int i = 0; i < pageCount; i++) { - * Page page = renderer.openPage(i); - * - * // say we render for showing on the screen - * page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY); - * - * // do stuff with the bitmap - * - * // close the page - * page.close(); - * } - * - * // close the renderer - * renderer.close(); - * </pre> - * - * <h3>Print preview and print output</h3> - * <p> - * If you are using this class to rasterize a PDF for printing or show a print - * preview, it is recommended that you respect the following contract in order - * to provide a consistent user experience when seeing a preview and printing, - * i.e. the user sees a preview that is the same as the printout. - * </p> - * <ul> - * <li> - * Respect the property whether the document would like to be scaled for printing - * as per {@link #shouldScaleForPrinting()}. - * </li> - * <li> - * When scaling a document for printing the aspect ratio should be preserved. - * </li> - * <li> - * Do not inset the content with any margins from the {@link android.print.PrintAttributes} - * as the application is responsible to render it such that the margins are respected. - * </li> - * <li> - * If document page size is greater than the printed media size the content should - * be anchored to the upper left corner of the page for left-to-right locales and - * top right corner for right-to-left locales. - * </li> - * </ul> - * - * @see #close() - */ -public final class PdfRenderer implements AutoCloseable { - /** - * Any call the native pdfium code has to be single threaded as the library does not support - * parallel use. - */ - final static Object sPdfiumLock = new Object(); - - private final CloseGuard mCloseGuard = CloseGuard.get(); - - private final Point mTempPoint = new Point(); - - private long mNativeDocument; - - private final int mPageCount; - - private ParcelFileDescriptor mInput; - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private Page mCurrentPage; - - /** @hide */ - @IntDef({ - Page.RENDER_MODE_FOR_DISPLAY, - Page.RENDER_MODE_FOR_PRINT - }) - @Retention(RetentionPolicy.SOURCE) - public @interface RenderMode {} - - /** - * Creates a new instance. - * <p> - * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>, - * i.e. its data being randomly accessed, e.g. pointing to a file. - * </p> - * <p> - * <strong>Note:</strong> This class takes ownership of the passed in file descriptor - * and is responsible for closing it when the renderer is closed. - * </p> - * <p> - * If the file is from an untrusted source it is recommended to run the renderer in a separate, - * isolated process with minimal permissions to limit the impact of security exploits. - * </p> - * - * @param input Seekable file descriptor to read from. - * - * @throws java.io.IOException If an error occurs while reading the file. - * @throws java.lang.SecurityException If the file requires a password or - * the security scheme is not supported. - */ - public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException { - if (input == null) { - throw new NullPointerException("input cannot be null"); - } - - final long size; - try { - Os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET); - size = Os.fstat(input.getFileDescriptor()).st_size; - } catch (ErrnoException ee) { - throw new IllegalArgumentException("file descriptor not seekable"); - } - mInput = input; - - synchronized (sPdfiumLock) { - mNativeDocument = nativeCreate(mInput.getFd(), size); - try { - mPageCount = nativeGetPageCount(mNativeDocument); - } catch (Throwable t) { - nativeClose(mNativeDocument); - mNativeDocument = 0; - throw t; - } - } - - mCloseGuard.open("close"); - } - - /** - * Closes this renderer. You should not use this instance - * after this method is called. - */ - public void close() { - throwIfClosed(); - throwIfPageOpened(); - doClose(); - } - - /** - * Gets the number of pages in the document. - * - * @return The page count. - */ - public int getPageCount() { - throwIfClosed(); - return mPageCount; - } - - /** - * Gets whether the document prefers to be scaled for printing. - * You should take this info account if the document is rendered - * for printing and the target media size differs from the page - * size. - * - * @return If to scale the document. - */ - public boolean shouldScaleForPrinting() { - throwIfClosed(); - - synchronized (sPdfiumLock) { - return nativeScaleForPrinting(mNativeDocument); - } - } - - /** - * Opens a page for rendering. - * - * @param index The page index. - * @return A page that can be rendered. - * - * @see android.graphics.pdf.PdfRenderer.Page#close() PdfRenderer.Page.close() - */ - public Page openPage(int index) { - throwIfClosed(); - throwIfPageOpened(); - throwIfPageNotInDocument(index); - mCurrentPage = new Page(index); - return mCurrentPage; - } - - @Override - protected void finalize() throws Throwable { - try { - if (mCloseGuard != null) { - mCloseGuard.warnIfOpen(); - } - - doClose(); - } finally { - super.finalize(); - } - } - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private void doClose() { - if (mCurrentPage != null) { - mCurrentPage.close(); - mCurrentPage = null; - } - - if (mNativeDocument != 0) { - synchronized (sPdfiumLock) { - nativeClose(mNativeDocument); - } - mNativeDocument = 0; - } - - if (mInput != null) { - IoUtils.closeQuietly(mInput); - mInput = null; - } - mCloseGuard.close(); - } - - private void throwIfClosed() { - if (mInput == null) { - throw new IllegalStateException("Already closed"); - } - } - - private void throwIfPageOpened() { - if (mCurrentPage != null) { - throw new IllegalStateException("Current page not closed"); - } - } - - private void throwIfPageNotInDocument(int pageIndex) { - if (pageIndex < 0 || pageIndex >= mPageCount) { - throw new IllegalArgumentException("Invalid page index"); - } - } - - /** - * This class represents a PDF document page for rendering. - */ - public final class Page implements AutoCloseable { - - private final CloseGuard mCloseGuard = CloseGuard.get(); - - /** - * Mode to render the content for display on a screen. - */ - public static final int RENDER_MODE_FOR_DISPLAY = 1; - - /** - * Mode to render the content for printing. - */ - public static final int RENDER_MODE_FOR_PRINT = 2; - - private final int mIndex; - private final int mWidth; - private final int mHeight; - - private long mNativePage; - - private Page(int index) { - Point size = mTempPoint; - synchronized (sPdfiumLock) { - mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size); - } - mIndex = index; - mWidth = size.x; - mHeight = size.y; - mCloseGuard.open("close"); - } - - /** - * Gets the page index. - * - * @return The index. - */ - public int getIndex() { - return mIndex; - } - - /** - * Gets the page width in points (1/72"). - * - * @return The width in points. - */ - public int getWidth() { - return mWidth; - } - - /** - * Gets the page height in points (1/72"). - * - * @return The height in points. - */ - public int getHeight() { - return mHeight; - } - - /** - * Renders a page to a bitmap. - * <p> - * You may optionally specify a rectangular clip in the bitmap bounds. No rendering - * outside the clip will be performed, hence it is your responsibility to initialize - * the bitmap outside the clip. - * </p> - * <p> - * You may optionally specify a matrix to transform the content from page coordinates - * which are in points (1/72") to bitmap coordinates which are in pixels. If this - * matrix is not provided this method will apply a transformation that will fit the - * whole page to the destination clip if provided or the destination bitmap if no - * clip is provided. - * </p> - * <p> - * The clip and transformation are useful for implementing tile rendering where the - * destination bitmap contains a portion of the image, for example when zooming. - * Another useful application is for printing where the size of the bitmap holding - * the page is too large and a client can render the page in stripes. - * </p> - * <p> - * <strong>Note: </strong> The destination bitmap format must be - * {@link Config#ARGB_8888 ARGB}. - * </p> - * <p> - * <strong>Note: </strong> The optional transformation matrix must be affine as per - * {@link android.graphics.Matrix#isAffine() Matrix.isAffine()}. Hence, you can specify - * rotation, scaling, translation but not a perspective transformation. - * </p> - * - * @param destination Destination bitmap to which to render. - * @param destClip Optional clip in the bitmap bounds. - * @param transform Optional transformation to apply when rendering. - * @param renderMode The render mode. - * - * @see #RENDER_MODE_FOR_DISPLAY - * @see #RENDER_MODE_FOR_PRINT - */ - public void render(@NonNull Bitmap destination, @Nullable Rect destClip, - @Nullable Matrix transform, @RenderMode int renderMode) { - if (mNativePage == 0) { - throw new NullPointerException(); - } - - destination = Preconditions.checkNotNull(destination, "bitmap null"); - - if (destination.getConfig() != Config.ARGB_8888) { - throw new IllegalArgumentException("Unsupported pixel format"); - } - - if (destClip != null) { - if (destClip.left < 0 || destClip.top < 0 - || destClip.right > destination.getWidth() - || destClip.bottom > destination.getHeight()) { - throw new IllegalArgumentException("destBounds not in destination"); - } - } - - if (transform != null && !transform.isAffine()) { - throw new IllegalArgumentException("transform not affine"); - } - - if (renderMode != RENDER_MODE_FOR_PRINT && renderMode != RENDER_MODE_FOR_DISPLAY) { - throw new IllegalArgumentException("Unsupported render mode"); - } - - if (renderMode == RENDER_MODE_FOR_PRINT && renderMode == RENDER_MODE_FOR_DISPLAY) { - throw new IllegalArgumentException("Only single render mode supported"); - } - - final int contentLeft = (destClip != null) ? destClip.left : 0; - final int contentTop = (destClip != null) ? destClip.top : 0; - final int contentRight = (destClip != null) ? destClip.right - : destination.getWidth(); - final int contentBottom = (destClip != null) ? destClip.bottom - : destination.getHeight(); - - // If transform is not set, stretch page to whole clipped area - if (transform == null) { - int clipWidth = contentRight - contentLeft; - int clipHeight = contentBottom - contentTop; - - transform = new Matrix(); - transform.postScale((float)clipWidth / getWidth(), - (float)clipHeight / getHeight()); - transform.postTranslate(contentLeft, contentTop); - } - - // FIXME: This code is planned to be outside the UI rendering module, so it should not - // be able to access native instances from Bitmap, Matrix, etc. - final long transformPtr = transform.ni(); - - synchronized (sPdfiumLock) { - nativeRenderPage(mNativeDocument, mNativePage, destination.getNativeInstance(), - contentLeft, contentTop, contentRight, contentBottom, transformPtr, - renderMode); - } - } - - /** - * Closes this page. - * - * @see android.graphics.pdf.PdfRenderer#openPage(int) - */ - @Override - public void close() { - throwIfClosed(); - doClose(); - } - - @Override - protected void finalize() throws Throwable { - try { - if (mCloseGuard != null) { - mCloseGuard.warnIfOpen(); - } - - doClose(); - } finally { - super.finalize(); - } - } - - private void doClose() { - if (mNativePage != 0) { - synchronized (sPdfiumLock) { - nativeClosePage(mNativePage); - } - mNativePage = 0; - } - - mCloseGuard.close(); - mCurrentPage = null; - } - - private void throwIfClosed() { - if (mNativePage == 0) { - throw new IllegalStateException("Already closed"); - } - } - } - - private static native long nativeCreate(int fd, long size); - private static native void nativeClose(long documentPtr); - private static native int nativeGetPageCount(long documentPtr); - private static native boolean nativeScaleForPrinting(long documentPtr); - private static native void nativeRenderPage(long documentPtr, long pagePtr, long bitmapHandle, - int clipLeft, int clipTop, int clipRight, int clipBottom, long transformPtr, - int renderMode); - private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex, - Point outSize); - private static native void nativeClosePage(long pagePtr); -} diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 4e330da417be..e4f3e2defb25 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -427,7 +427,6 @@ cc_defaults { "jni/MovieImpl.cpp", "jni/pdf/PdfDocument.cpp", "jni/pdf/PdfEditor.cpp", - "jni/pdf/PdfRenderer.cpp", "jni/pdf/PdfUtils.cpp", ], shared_libs: [ diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp index 883f273b5d3d..fb0cdb034575 100644 --- a/libs/hwui/apex/jni_runtime.cpp +++ b/libs/hwui/apex/jni_runtime.cpp @@ -70,7 +70,6 @@ extern int register_android_graphics_fonts_Font(JNIEnv* env); extern int register_android_graphics_fonts_FontFamily(JNIEnv* env); extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env); extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env); -extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env); extern int register_android_graphics_text_MeasuredText(JNIEnv* env); extern int register_android_graphics_text_LineBreaker(JNIEnv *env); extern int register_android_graphics_text_TextShaper(JNIEnv *env); @@ -142,7 +141,6 @@ extern int register_android_graphics_HardwareBufferRenderer(JNIEnv* env); REG_JNI(register_android_graphics_fonts_FontFamily), REG_JNI(register_android_graphics_pdf_PdfDocument), REG_JNI(register_android_graphics_pdf_PdfEditor), - REG_JNI(register_android_graphics_pdf_PdfRenderer), REG_JNI(register_android_graphics_text_MeasuredText), REG_JNI(register_android_graphics_text_LineBreaker), REG_JNI(register_android_graphics_text_TextShaper), diff --git a/libs/hwui/jni/pdf/PdfRenderer.cpp b/libs/hwui/jni/pdf/PdfRenderer.cpp deleted file mode 100644 index cc1f96197c74..000000000000 --- a/libs/hwui/jni/pdf/PdfRenderer.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2014 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 "PdfUtils.h" - -#include "GraphicsJNI.h" -#include "SkBitmap.h" -#include "SkMatrix.h" -#include "fpdfview.h" - -#include <vector> -#include <utils/Log.h> -#include <unistd.h> -#include <sys/types.h> -#include <unistd.h> - -namespace android { - -static const int RENDER_MODE_FOR_DISPLAY = 1; -static const int RENDER_MODE_FOR_PRINT = 2; - -static struct { - jfieldID x; - jfieldID y; -} gPointClassInfo; - -static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPtr, - jint pageIndex, jobject outSize) { - FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); - - FPDF_PAGE page = FPDF_LoadPage(document, pageIndex); - if (!page) { - jniThrowException(env, "java/lang/IllegalStateException", - "cannot load page"); - return -1; - } - - double width = 0; - double height = 0; - - int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); - if (!result) { - jniThrowException(env, "java/lang/IllegalStateException", - "cannot get page size"); - return -1; - } - - env->SetIntField(outSize, gPointClassInfo.x, width); - env->SetIntField(outSize, gPointClassInfo.y, height); - - return reinterpret_cast<jlong>(page); -} - -static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { - FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); - FPDF_ClosePage(page); -} - -static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr, - jlong bitmapPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom, - jlong transformPtr, jint renderMode) { - FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); - - SkBitmap skBitmap; - bitmap::toBitmap(bitmapPtr).getSkBitmap(&skBitmap); - - const int stride = skBitmap.width() * 4; - - FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(), - FPDFBitmap_BGRA, skBitmap.getPixels(), stride); - - int renderFlags = FPDF_REVERSE_BYTE_ORDER; - if (renderMode == RENDER_MODE_FOR_DISPLAY) { - renderFlags |= FPDF_LCD_TEXT; - } else if (renderMode == RENDER_MODE_FOR_PRINT) { - renderFlags |= FPDF_PRINTING; - } - - SkMatrix matrix = *reinterpret_cast<SkMatrix*>(transformPtr); - SkScalar transformValues[6]; - if (!matrix.asAffine(transformValues)) { - jniThrowException(env, "java/lang/IllegalArgumentException", - "transform matrix has perspective. Only affine matrices are allowed."); - return; - } - - FS_MATRIX transform = {transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY], - transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY], - transformValues[SkMatrix::kATransX], - transformValues[SkMatrix::kATransY]}; - - FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; - - FPDF_RenderPageBitmapWithMatrix(bitmap, page, &transform, &clip, renderFlags); - - skBitmap.notifyPixelsChanged(); -} - -static const JNINativeMethod gPdfRenderer_Methods[] = { - {"nativeCreate", "(IJ)J", (void*) nativeOpen}, - {"nativeClose", "(J)V", (void*) nativeClose}, - {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount}, - {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting}, - {"nativeRenderPage", "(JJJIIIIJI)V", (void*) nativeRenderPage}, - {"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize}, - {"nativeClosePage", "(J)V", (void*) nativeClosePage} -}; - -int register_android_graphics_pdf_PdfRenderer(JNIEnv* env) { - int result = RegisterMethodsOrDie( - env, "android/graphics/pdf/PdfRenderer", gPdfRenderer_Methods, - NELEM(gPdfRenderer_Methods)); - - jclass clazz = FindClassOrDie(env, "android/graphics/Point"); - gPointClassInfo.x = GetFieldIDOrDie(env, clazz, "x", "I"); - gPointClassInfo.y = GetFieldIDOrDie(env, clazz, "y", "I"); - - return result; -}; - -}; diff --git a/media/java/android/media/metrics/EditingEndedEvent.java b/media/java/android/media/metrics/EditingEndedEvent.java index 9b3477f4bd69..54496bff077f 100644 --- a/media/java/android/media/metrics/EditingEndedEvent.java +++ b/media/java/android/media/metrics/EditingEndedEvent.java @@ -199,7 +199,7 @@ public final class EditingEndedEvent extends Event implements Parcelable { /** Input audio was edited. */ public static final long OPERATION_TYPE_AUDIO_EDIT = 1L << 3; - /** Input video samples were writted (muxed) directly to the output file without transcoding. */ + /** Input video samples were written (muxed) directly to the output file without transcoding. */ public static final long OPERATION_TYPE_VIDEO_TRANSMUX = 1L << 4; /** Input audio samples were written (muxed) directly to the output file without transcoding. */ @@ -272,7 +272,8 @@ public final class EditingEndedEvent extends Event implements Parcelable { } /** - * Returns the name of the library implementing the exporting operation, or {@code null} if + * Returns the name of the library implementing the exporting operation, for example, a Maven + * artifact ID like "androidx.media3.media3-transformer:1.3.0-beta01", or {@code null} if * unknown. */ @Nullable @@ -281,8 +282,8 @@ public final class EditingEndedEvent extends Event implements Parcelable { } /** - * Returns the name of the library implementing the media muxing operation, or {@code null} if - * unknown. + * Returns the name of the library implementing the media muxing operation, for example, a Maven + * artifact ID like "androidx.media3.media3-muxer:1.3.0-beta01", or {@code null} if unknown. */ @Nullable public String getMuxerName() { diff --git a/media/java/android/media/metrics/MediaItemInfo.java b/media/java/android/media/metrics/MediaItemInfo.java index 63dd3ccd3b33..338697fef76b 100644 --- a/media/java/android/media/metrics/MediaItemInfo.java +++ b/media/java/android/media/metrics/MediaItemInfo.java @@ -92,7 +92,7 @@ public final class MediaItemInfo implements Parcelable { DATA_TYPE_DEPTH, DATA_TYPE_GAIN_MAP, DATA_TYPE_HIGH_FRAME_RATE, - DATA_TYPE_CUE_POINTS, + DATA_TYPE_SPEED_SETTING_CUE_POINTS, DATA_TYPE_GAPLESS, DATA_TYPE_SPATIAL_AUDIO, DATA_TYPE_HIGH_DYNAMIC_RANGE_VIDEO, @@ -109,7 +109,10 @@ public final class MediaItemInfo implements Parcelable { /** The media item includes audio data. */ public static final long DATA_TYPE_AUDIO = 1L << 2; - /** The media item includes metadata. */ + /** + * The media item includes static media container metadata (for example, capture frame rate or + * location information). + */ public static final long DATA_TYPE_METADATA = 1L << 3; /** The media item includes depth (z-distance) information. */ @@ -121,8 +124,11 @@ public final class MediaItemInfo implements Parcelable { /** The media item includes high frame rate video data. */ public static final long DATA_TYPE_HIGH_FRAME_RATE = 1L << 6; - /** The media item includes time-dependent speed setting metadata. */ - public static final long DATA_TYPE_CUE_POINTS = 1L << 7; + /** + * The media item includes time-dependent speed information (for example, slow motion cue + * points). + */ + public static final long DATA_TYPE_SPEED_SETTING_CUE_POINTS = 1L << 7; /** The media item includes gapless audio metadata. */ public static final long DATA_TYPE_GAPLESS = 1L << 8; diff --git a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java index 6766afc5e45a..b5951e8e7927 100644 --- a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java +++ b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java @@ -40,7 +40,6 @@ import android.provider.Settings; import android.sysprop.CrashRecoveryProperties; import android.text.TextUtils; import android.util.ArraySet; -import android.util.ExceptionUtils; import android.util.Log; import android.util.Slog; @@ -136,7 +135,7 @@ public class RescueParty { } // We're disabled on all engineering devices - if (Build.IS_ENG) { + if (Build.TYPE.equals("eng")) { Slog.v(TAG, "Disabled because of eng build"); return true; } @@ -144,7 +143,7 @@ public class RescueParty { // We're disabled on userdebug devices connected over USB, since that's // a decent signal that someone is actively trying to debug the device, // or that it's in a lab environment. - if (Build.IS_USERDEBUG && isUsbActive()) { + if (Build.TYPE.equals("userdebug") && isUsbActive()) { Slog.v(TAG, "Disabled because of active USB connection"); return true; } @@ -478,9 +477,18 @@ public class RescueParty { } } + private static String getCompleteMessage(Throwable t) { + final StringBuilder builder = new StringBuilder(); + builder.append(t.getMessage()); + while ((t = t.getCause()) != null) { + builder.append(": ").append(t.getMessage()); + } + return builder.toString(); + } + private static void logRescueException(int level, @Nullable String failedPackageName, Throwable t) { - final String msg = ExceptionUtils.getCompleteMessage(t); + final String msg = getCompleteMessage(t); EventLogTags.writeRescueFailure(level, msg); String failureMsg = "Failed rescue level " + levelToString(level); if (!TextUtils.isEmpty(failedPackageName)) { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt index d9493961e3ed..621ddf796f58 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt @@ -557,13 +557,18 @@ private fun StatusMessage( targetState = message, label = "Bouncer message", animationSpec = if (message.isUpdateAnimated) tween() else snap(), - modifier = modifier, + modifier = modifier.fillMaxWidth(), ) { - Text( - text = it.text, - color = MaterialTheme.colorScheme.onSurface, - style = MaterialTheme.typography.bodyLarge, - ) + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxWidth(), + ) { + Text( + text = it.text, + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.bodyLarge, + ) + } } } diff --git a/packages/SystemUI/plugin/proguard_plugins.flags b/packages/SystemUI/plugin/proguard_plugins.flags index abac27f0cbe6..23ba8d066bb2 100644 --- a/packages/SystemUI/plugin/proguard_plugins.flags +++ b/packages/SystemUI/plugin/proguard_plugins.flags @@ -7,3 +7,13 @@ -keep class com.android.systemui.log.core.** { *; } + +# This type is used in the plugin API boundary, so ensure the used public methods are kept. +-keepclassmembers class androidx.constraintlayout.widget.ConstraintSet { + public void connect(int, int, int, int, int); + public void constrainWidth(int, int); + public void constrainHeight(int, int); + public int getHeight(int); + public int getWidth(int); + public void setGoneMargin(int, int, int); +} diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt index 14fda5e96a9c..efbd59f6ce17 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt @@ -48,10 +48,14 @@ abstract class FlagDependenciesBase( private var unmetDependencies = emptyList<Dependency>() override fun start() { + if (!handler.enableDependencies) { + return + } defineDependencies() allDependencies = workingDependencies.toList() unmetDependencies = workingDependencies.filter { !it.isMet } workingDependencies.clear() + handler.onCollected(allDependencies) if (unmetDependencies.isNotEmpty()) { handler.warnAboutBadFlagConfiguration(all = allDependencies, unmet = unmetDependencies) } @@ -106,14 +110,24 @@ abstract class FlagDependenciesBase( /** Add a dependency to the working list */ private fun addDependency(first: FlagToken, second: FlagToken) { - if (!Compile.IS_DEBUG) return // `user` builds should omit all this code + if (!handler.enableDependencies) return workingDependencies.add( Dependency(first.name, first.isEnabled, second.name, second.isEnabled) ) } - /** An interface which handles a warning about a bad flag configuration. */ + /** An interface which handles dependency collection. */ interface Handler { + /** + * Should FlagDependencies do anything? + * + * @return false for user builds so that we skip this overhead. + */ + val enableDependencies: Boolean + get() = Compile.IS_DEBUG + /** Handle the complete list of dependencies. */ + fun onCollected(all: List<Dependency>) {} + /** Handle a bad flag configuration. */ fun warnAboutBadFlagConfiguration(all: List<Dependency>, unmet: List<Dependency>) } } @@ -133,7 +147,7 @@ constructor( all: List<FlagDependenciesBase.Dependency>, unmet: List<FlagDependenciesBase.Dependency> ) { - val title = "Invalid flag dependencies: ${unmet.size} of ${all.size}" + val title = "Invalid flag dependencies: ${unmet.size}" val details = unmet.joinToString("\n") { it.shortUnmetString() } Log.e("FlagDependencies", "$title:\n$details") val channel = NotificationChannel("FLAGS", "Flags", NotificationManager.IMPORTANCE_DEFAULT) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt index 94cc7e9d1a9f..f2b84827f3a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt @@ -76,6 +76,6 @@ class RowAppearanceCoordinator @Inject internal constructor( // Show/hide the feedback icon controller.setFeedbackIcon(mAssistantFeedbackController.getFeedbackIcon(entry)) // Show the "alerted" bell icon - controller.setLastAudiblyAlertedMs(entry.lastAudiblyAlertedMs) + controller.setLastAudibleMs(entry.lastAudiblyAlertedMs) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProvider.kt index 74ff78e25a2f..e8c59f44da0e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProvider.kt @@ -33,7 +33,7 @@ class LaunchFullScreenIntentProvider @Inject constructor() { private val listeners = ListenerSet<Listener>() /** - * Registers a listener with this provider. These listeners will be alerted whenever a full + * Registers a listener with this provider. These listeners will be updated whenever a full * screen intent should be launched for a notification entry. */ fun registerListener(listener: Listener) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt index 5ee94ba1624c..82b7e14adcc9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt @@ -29,10 +29,10 @@ interface NotifRowController { fun setSystemExpanded(systemExpanded: Boolean) /** - * Sets the timestamp that the notification was last audibly alerted, which the row uses to + * Sets the timestamp that the notification was last audible, which the row uses to * show a bell icon in the header which indicates to the user which notification made a noise. */ - fun setLastAudiblyAlertedMs(lastAudiblyAlertedMs: Long) + fun setLastAudibleMs(lastAudibleMs: Long) /** Shows the given feedback icon, or hides the icon if null. */ fun setFeedbackIcon(icon: FeedbackIcon?) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index 0afdefabd4f0..5614f3a3fcc5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -431,8 +431,8 @@ public class ExpandableNotificationRowController implements NotifViewController } @Override - public void setLastAudiblyAlertedMs(long lastAudiblyAlertedMs) { - mView.setLastAudiblyAlertedMs(lastAudiblyAlertedMs); + public void setLastAudibleMs(long lastAudibleMs) { + mView.setLastAudiblyAlertedMs(lastAudibleMs); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FullscreenLightRevealAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/FullscreenLightRevealAnimation.kt index 668b1439abab..ca5ea3bc1caa 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/FullscreenLightRevealAnimation.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/FullscreenLightRevealAnimation.kt @@ -45,7 +45,6 @@ import com.android.wm.shell.displayareahelper.DisplayAreaHelper import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import java.lang.IllegalArgumentException import java.util.Optional import java.util.concurrent.Executor import java.util.function.Consumer @@ -71,7 +70,7 @@ constructor( private val displayTracker: DisplayTracker, @Background private val applicationScope: CoroutineScope, @Main private val executor: Executor, - @Assisted private val displaySelector: Sequence<DisplayInfo>.() -> DisplayInfo?, + @Assisted private val displaySelector: List<DisplayInfo>.() -> DisplayInfo?, @Assisted private val lightRevealEffectFactory: (rotation: Int) -> LightRevealEffect, @Assisted private val overlayContainerName: String ) { @@ -84,13 +83,11 @@ constructor( private var scrimView: LightRevealScrim? = null private val rotationWatcher = RotationWatcher() - private val internalDisplayInfos: Sequence<DisplayInfo> - get() = - displayManager - .getDisplays(DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED) - .asSequence() - .map { DisplayInfo().apply { it.getDisplayInfo(this) } } - .filter { it.type == Display.TYPE_INTERNAL } + private val internalDisplayInfos: List<DisplayInfo> = + displayManager + .getDisplays(DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED) + .map { DisplayInfo().apply { it.getDisplayInfo(this) } } + .filter { it.type == Display.TYPE_INTERNAL } var isTouchBlocked: Boolean = false set(value) { @@ -252,7 +249,7 @@ constructor( @AssistedFactory interface Factory { fun create( - displaySelector: Sequence<DisplayInfo>.() -> DisplayInfo?, + displaySelector: List<DisplayInfo>.() -> DisplayInfo?, effectFactory: (rotation: Int) -> LightRevealEffect, overlayContainerName: String ): FullscreenLightRevealAnimationController diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java index 50d15475434b..e10d1cb833fa 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/Events.java +++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java @@ -60,6 +60,7 @@ public class Events { public static final int EVENT_DISMISS_USB_OVERHEAT_ALARM = 20; // (reason|int) (keyguard|bool) public static final int EVENT_ODI_CAPTIONS_CLICK = 21; public static final int EVENT_ODI_CAPTIONS_TOOLTIP_CLICK = 22; + public static final int EVENT_SLIDER_TOUCH_TRACKING = 23; // (tracking|bool) private static final String[] EVENT_TAGS = { "show_dialog", @@ -84,7 +85,8 @@ public class Events { "show_usb_overheat_alarm", "dismiss_usb_overheat_alarm", "odi_captions_click", - "odi_captions_tooltip_click" + "odi_captions_tooltip_click", + "slider_touch_tracking" }; public static final int DISMISS_REASON_UNKNOWN = 0; @@ -234,6 +236,10 @@ public class Events { VOLUME_DIALOG_SLIDER(150), @UiEvent(doc = "The audio stream was set to silent via slider") VOLUME_DIALOG_SLIDER_TO_ZERO(151), + @UiEvent(doc = "The right-most slider started tracking touch") + VOLUME_DIALOG_SLIDER_STARTED_TRACKING_TOUCH(1620), + @UiEvent(doc = "The right-most slider stopped tracking touch") + VOLUME_DIALOG_SLIDER_STOPPED_TRACKING_TOUCH(1621), @UiEvent(doc = "ODI captions was clicked") VOLUME_DIALOG_ODI_CAPTIONS_CLICKED(1503), @UiEvent(doc = "ODI captions tooltip dismiss was clicked") @@ -491,6 +497,15 @@ public class Events { .append(" keyguard=").append(keyguard); } break; + case EVENT_SLIDER_TOUCH_TRACKING: + final boolean startedTracking = (boolean) list[0]; + final VolumeDialogEvent event; + if (startedTracking) { + event = VolumeDialogEvent.VOLUME_DIALOG_SLIDER_STARTED_TRACKING_TOUCH; + } else { + event = VolumeDialogEvent.VOLUME_DIALOG_SLIDER_STOPPED_TRACKING_TOUCH; + } + sUiEventLogger.log(event); default: sb.append(Arrays.asList(list)); break; diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 90c5c62718ad..404563087041 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -2518,6 +2518,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, @Override public void onStartTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream); + Events.writeEvent(Events.EVENT_SLIDER_TOUCH_TRACKING, /* startedTracking= */true); if (mRow.mHapticPlugin != null) { mRow.mHapticPlugin.onStartTrackingTouch(seekBar); } @@ -2528,6 +2529,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, @Override public void onStopTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream); + Events.writeEvent(Events.EVENT_SLIDER_TOUCH_TRACKING, /* startedTracking= */false); if (mRow.mHapticPlugin != null) { mRow.mHapticPlugin.onStopTrackingTouch(seekBar); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagDependenciesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagDependenciesTest.kt index 936aa8bb819c..91da88e480d4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagDependenciesTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagDependenciesTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.flags import android.testing.AndroidTestingRunner +import android.util.Log import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import java.io.PrintWriter @@ -41,14 +42,21 @@ class FlagDependenciesTest : SysuiTestCase() { FlagDependencies(TestFeatureFlags(teamfood = teamfood), TestHandler()) private class TestHandler : FlagDependenciesBase.Handler { + override val enableDependencies: Boolean + get() = true override fun warnAboutBadFlagConfiguration( all: List<FlagDependenciesBase.Dependency>, unmet: List<FlagDependenciesBase.Dependency> ) { - val title = "${unmet.size} invalid of ${all.size} flag dependencies" + val title = "Invalid flag dependencies: ${unmet.size}" val details = unmet.joinToString("\n") fail("$title:\n$details") } + + override fun onCollected(all: List<FlagDependenciesBase.Dependency>) { + Log.d("FlagDependencies", "All: ${all.size}") + all.forEach { Log.d("FlagDependencies", " $it") } + } } private class TestFeatureFlags(val teamfood: Boolean) : FeatureFlagsClassic { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt index 3f3de009fb04..fa669fc222f5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt @@ -105,7 +105,7 @@ class RowAppearanceCoordinatorTest : SysuiTestCase() { @Test fun testSetLastAudiblyAlerted() { afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) - verify(controller1).setLastAudiblyAlertedMs(eq(17.toLong())) + verify(controller1).setLastAudibleMs(eq(17.toLong())) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index 25a0bc4fba61..1a3cb87b3422 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -58,6 +58,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityManager; import android.widget.ImageButton; +import android.widget.SeekBar; import androidx.test.core.view.MotionEventBuilder; import androidx.test.filters.SmallTest; @@ -111,6 +112,7 @@ public class VolumeDialogImplTest extends SysuiTestCase { View mDrawerVibrate; View mDrawerMute; View mDrawerNormal; + ViewGroup mDialogRowsView; CaptionsToggleImageButton mODICaptionsIcon; private TestableLooper mTestableLooper; @@ -222,6 +224,8 @@ public class VolumeDialogImplTest extends SysuiTestCase { } mODICaptionsIcon = mDialog.getDialogView().findViewById(R.id.odi_captions_icon); + mDialogRowsView = mDialog.getDialogView().findViewById(R.id.volume_dialog_rows); + Prefs.putInt(mContext, Prefs.Key.SEEN_RINGER_GUIDANCE_COUNT, VolumePrefs.SHOW_RINGER_TOAST_COUNT + 1); @@ -671,6 +675,45 @@ public class VolumeDialogImplTest extends SysuiTestCase { } @Test + public void volumeSliderTracksTouch_logsStartAndStopTrackingUiEvents() { + UiEventLoggerFake logger = new UiEventLoggerFake(); + Events.sUiEventLogger = logger; + + mDialog.show(SHOW_REASON_UNKNOWN); + mTestableLooper.processAllMessages(); + + MotionEvent down = MotionEventBuilder.newBuilder() + .setAction(MotionEvent.ACTION_DOWN).build(); + MotionEvent up = MotionEventBuilder.newBuilder().setAction(MotionEvent.ACTION_UP).build(); + + SeekBar slider = + mDialogRowsView.getChildAt(0).findViewById(R.id.volume_row_slider); + slider.onTouchEvent(down); + slider.onTouchEvent(up); + mTestableLooper.moveTimeForward(300); + mTestableLooper.processAllMessages(); + + boolean foundStartTrackingTouch = false; + boolean foundStopTrackingTouch = false; + for (UiEventLoggerFake.FakeUiEvent event : logger.getLogs()) { + if (event.eventId + == Events.VolumeDialogEvent.VOLUME_DIALOG_SLIDER_STARTED_TRACKING_TOUCH.getId() + ) { + foundStartTrackingTouch = true; + } + if (event.eventId + == Events.VolumeDialogEvent.VOLUME_DIALOG_SLIDER_STOPPED_TRACKING_TOUCH.getId() + ) { + foundStopTrackingTouch = true; + } + } + Assert.assertTrue("Did not log the event of start tracking touch.", + foundStartTrackingTouch); + Assert.assertTrue("Did not log the event of stop tracking touch.", + foundStopTrackingTouch); + } + + @Test public void turnOnDnD_volumeSliderIconChangesToDnd() { State state = createShellState(); state.zenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS; diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java index b62b3a211e58..353d9709b056 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java @@ -46,6 +46,7 @@ import androidx.core.animation.AndroidXAnimatorIsolationRule; import androidx.test.InstrumentationRegistry; import androidx.test.uiautomator.UiDevice; +import com.android.internal.protolog.common.ProtoLog; import com.android.systemui.broadcast.FakeBroadcastDispatcher; import com.android.systemui.flags.SceneContainerRule; @@ -170,6 +171,7 @@ public abstract class SysuiTestCase { @Before public void SysuiSetup() throws Exception { + ProtoLog.REQUIRE_PROTOLOGTOOL = false; mSysuiDependency = new SysuiTestDependency(mContext, shouldFailOnLeakedReceiver()); mDependency = mSysuiDependency.install(); // TODO(b/292141694): build out Ravenwood support for Instrumentation diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java index c134a4c5b2ad..d8a94d8b8b59 100644 --- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java +++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java @@ -1204,23 +1204,26 @@ public class CameraExtensionsProxyService extends Service { List<Pair<CameraCharacteristics.Key, Object>> entries = mAdvancedExtender.getAvailableCharacteristicsKeyValues(); - if ((entries != null) && !entries.isEmpty()) { - CameraMetadataNative ret = new CameraMetadataNative(); - long vendorId = mMetadataVendorIdMap.containsKey(cameraId) - ? mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE; - ret.setVendorId(vendorId); - int[] characteristicsKeyTags = new int[entries.size()]; - int i = 0; - for (Pair<CameraCharacteristics.Key, Object> entry : entries) { - int tag = CameraMetadataNative.getTag(entry.first.getName(), vendorId); - characteristicsKeyTags[i++] = tag; - ret.set(entry.first, entry.second); - } - ret.set(CameraCharacteristics.REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, - characteristicsKeyTags); + if (entries == null || entries.isEmpty()) { + throw new RuntimeException("A valid set of key/value pairs are required that " + + "are supported by the extension."); + } - return ret; + CameraMetadataNative ret = new CameraMetadataNative(); + long vendorId = mMetadataVendorIdMap.containsKey(cameraId) + ? mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE; + ret.setVendorId(vendorId); + int[] characteristicsKeyTags = new int[entries.size()]; + int i = 0; + for (Pair<CameraCharacteristics.Key, Object> entry : entries) { + int tag = CameraMetadataNative.getTag(entry.first.getName(), vendorId); + characteristicsKeyTags[i++] = tag; + ret.set(entry.first, entry.second); } + ret.set(CameraCharacteristics.REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, + characteristicsKeyTags); + + return ret; } return null; diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 1ca3923b325c..d5863a73a0c3 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -1638,21 +1638,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // SDR brightness is unchanged, so animate quickly as this is only impacting // a likely minority amount of display content // ie, the highlights of an HDR video or UltraHDR image + // Ideally we'd do this as fast as possible (ie, skip the animation entirely), + // but this requires display support and would need an entry in the + // display configuration. For now just do the fast animation slowChange = false; - - // Going from HDR to no HDR; visually this should be a "no-op" anyway - // as the remaining SDR content's brightness should be holding steady - // due to the sdr brightness not shifting - if (BrightnessSynchronizer.floatEquals(sdrAnimateValue, animateValue)) { - skipAnimation = true; - } - - // Going from no HDR to HDR; visually this is a significant scene change - // and the animation just prevents advanced clients from doing their own - // handling of enter/exit animations if they would like to do such a thing - if (BrightnessSynchronizer.floatEquals(sdrAnimateValue, currentBrightness)) { - skipAnimation = true; - } } if (skipAnimation) { animateScreenBrightness(animateValue, sdrAnimateValue, diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 8cb5cef38ec6..f97f6d2350bc 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -105,6 +105,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -151,7 +152,9 @@ public class MediaSessionService extends SystemService implements Monitor { private boolean mHasFeatureLeanback; private ActivityManagerInternal mActivityManagerInternal; private UsageStatsManagerInternal mUsageStatsManagerInternal; - private final Set<Integer> mUserEngagingSessions = new HashSet<>(); + + /* Maps uid with all user engaging session tokens associated to it */ + private final Map<Integer, Set<MediaSession.Token>> mUserEngagingSessions = new HashMap<>(); // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile) // It's always not null after the MediaSessionService is started. @@ -615,32 +618,36 @@ public class MediaSessionService extends SystemService implements Monitor { } private void reportMediaInteractionEvent(MediaSessionRecordImpl record, boolean userEngaged) { - if (!android.app.usage.Flags.userInteractionTypeApi()) { - return; - } + if (!android.app.usage.Flags.userInteractionTypeApi() + || !(record instanceof MediaSessionRecord)) { + return; + } - String packageName = record.getPackageName(); - int sessionUid = record.getUid(); - String actionToLog = null; - if (userEngaged) { - if (!mUserEngagingSessions.contains(sessionUid)) { - actionToLog = "start"; - } - mUserEngagingSessions.add(sessionUid); - } else { - if (mUserEngagingSessions.contains(sessionUid)) { - actionToLog = "stop"; - } + String packageName = record.getPackageName(); + int sessionUid = record.getUid(); + String actionToLog = null; + MediaSession.Token token = ((MediaSessionRecord) record).getSessionToken(); + if (userEngaged) { + if (!mUserEngagingSessions.containsKey(sessionUid)) { + mUserEngagingSessions.put(sessionUid, new HashSet<>()); + actionToLog = "start"; + } + mUserEngagingSessions.get(sessionUid).add(token); + } else if (mUserEngagingSessions.containsKey(sessionUid)) { + mUserEngagingSessions.get(sessionUid).remove(token); + if (mUserEngagingSessions.get(sessionUid).isEmpty()) { + actionToLog = "stop"; mUserEngagingSessions.remove(sessionUid); } + } - if (actionToLog != null) { - PersistableBundle extras = new PersistableBundle(); - extras.putString(UsageStatsManager.EXTRA_EVENT_CATEGORY, "android.media"); - extras.putString(UsageStatsManager.EXTRA_EVENT_ACTION, actionToLog); - mUsageStatsManagerInternal.reportUserInteractionEvent( - packageName, record.getUserId(), extras); - } + if (actionToLog != null) { + PersistableBundle extras = new PersistableBundle(); + extras.putString(UsageStatsManager.EXTRA_EVENT_CATEGORY, "android.media"); + extras.putString(UsageStatsManager.EXTRA_EVENT_ACTION, actionToLog); + mUsageStatsManagerInternal.reportUserInteractionEvent( + packageName, record.getUserId(), extras); + } } void tempAllowlistTargetPkgIfPossible(int targetUid, String targetPackage, diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index d751186b2869..53ae60b0cc76 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1879,11 +1879,11 @@ public class NotificationManagerService extends SystemService { true, record.getUserId(), REASON_TIMEOUT, null); // If cancellation will be prevented due to lifetime extension, we send an // update to system UI. + final int packageImportance = getPackageImportanceWithIdentity( + record.getSbn().getPackageName()); synchronized (mNotificationLock) { maybeNotifySystemUiListenerLifetimeExtendedLocked(record, - record.getSbn().getPackageName(), - mActivityManager.getPackageImportance( - record.getSbn().getPackageName())); + record.getSbn().getPackageName(), packageImportance); } } else { cancelNotification(record.getSbn().getUid(), @@ -3852,7 +3852,7 @@ public class NotificationManagerService extends SystemService { // If cancellation will be prevented due to lifetime extension, we send an update to // system UI. NotificationRecord record = null; - final int packageImportance = mActivityManager.getPackageImportance(pkg); + final int packageImportance = getPackageImportanceWithIdentity(pkg); synchronized (mNotificationLock) { record = findNotificationLocked(pkg, tag, id, userId); maybeNotifySystemUiListenerLifetimeExtendedLocked(record, pkg, @@ -3877,10 +3877,9 @@ public class NotificationManagerService extends SystemService { pkg, null, 0, FLAG_FOREGROUND_SERVICE | FLAG_USER_INITIATED_JOB | FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, userId, REASON_APP_CANCEL_ALL); + final int packageImportance = getPackageImportanceWithIdentity(pkg); // If cancellation will be prevented due to lifetime extension, we send updates // to system UI. - // In this case, we need to hold the lock to access these lists. - final int packageImportance = mActivityManager.getPackageImportance(pkg); synchronized (mNotificationLock) { notifySystemUiListenerLifetimeExtendedListLocked(mNotificationList, packageImportance); @@ -5029,7 +5028,7 @@ public class NotificationManagerService extends SystemService { pkg = info.component.getPackageName(); } if (lifetimeExtensionRefactor()) { - packageImportance = mActivityManager.getPackageImportance(pkg); + packageImportance = getPackageImportanceWithIdentity(pkg); } else { packageImportance = IMPORTANCE_NONE; } @@ -5348,7 +5347,7 @@ public class NotificationManagerService extends SystemService { final int packageImportance; try { if (lifetimeExtensionRefactor()) { - packageImportance = mActivityManager.getPackageImportance(pkg); + packageImportance = getPackageImportanceWithIdentity(pkg); } else { packageImportance = IMPORTANCE_NONE; } @@ -7609,14 +7608,9 @@ public class NotificationManagerService extends SystemService { } } - // Need escalated privileges to get package importance - final long token = Binder.clearCallingIdentity(); - boolean isAppForeground; - try { - isAppForeground = mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND; - } finally { - Binder.restoreCallingIdentity(token); - } + // Need escalated privileges to get package importance. + final int packageImportance = getPackageImportanceWithIdentity(pkg); + boolean isAppForeground = packageImportance == IMPORTANCE_FOREGROUND; mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground, tracker)); return true; } @@ -7944,9 +7938,9 @@ public class NotificationManagerService extends SystemService { NotificationRecord r = mNotificationsByKey.get(key); packageName = r != null ? r.getSbn().getPackageName() : null; } + final int packageImportance = getPackageImportanceWithIdentity(packageName); boolean isAppForeground = packageName != null - && mActivityManager.getPackageImportance(packageName) - == IMPORTANCE_FOREGROUND; + && packageImportance == IMPORTANCE_FOREGROUND; synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { @@ -11867,6 +11861,18 @@ public class NotificationManagerService extends SystemService { } } + @FlaggedApi(FLAG_LIFETIME_EXTENSION_REFACTOR) + private int getPackageImportanceWithIdentity(String pkg) { + final long token = Binder.clearCallingIdentity(); + final int packageImportance; + try { + packageImportance = mActivityManager.getPackageImportance(pkg); + } finally { + Binder.restoreCallingIdentity(token); + } + return packageImportance; + } + public class NotificationListeners extends ManagedServices { static final String TAG_ENABLED_NOTIFICATION_LISTENERS = "enabled_listeners"; static final String TAG_REQUESTED_LISTENERS = "request_listeners"; diff --git a/services/core/java/com/android/server/selinux/OWNERS b/services/core/java/com/android/server/selinux/OWNERS index 6ca4da2fd740..4cf2066018b5 100644 --- a/services/core/java/com/android/server/selinux/OWNERS +++ b/services/core/java/com/android/server/selinux/OWNERS @@ -1,3 +1,4 @@ # Bug component: 1117393 sandrom@google.com +melisacz@google.com diff --git a/services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java b/services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java index 0219645bee38..03822aaf76b2 100644 --- a/services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java +++ b/services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java @@ -88,7 +88,7 @@ class SelinuxAuditLogsCollector { if (eventTime.isAfter(latestTimestamp)) { latestTimestamp = eventTime; } - if (eventTime.isBefore(mLastWrite)) { + if (eventTime.compareTo(mLastWrite) <= 0) { continue; } Object eventData = event.getData(); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index b3a8b7818415..c36df8da77ae 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3545,6 +3545,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(resultGrants, resultTo.getUriPermissionsLocked()); } + IBinder callerToken = new Binder(); + if (android.security.Flags.contentUriPermissionApis()) { + try { + resultTo.computeCallerInfo(callerToken, intent, this.getUid(), + mAtmService.getPackageManager().getNameForUid(this.getUid()), + /* isShareIdentityEnabled */ false); + // Result callers cannot share their identity via + // {@link ActivityOptions#setShareIdentityEnabled(boolean)} since + // {@link android.app.Activity#setResult} doesn't have a + // {@link android.os.Bundle}. + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } if (mForceSendResultForMediaProjection || resultTo.isState(RESUMED)) { // Sending the result to the resultTo activity asynchronously to prevent the // resultTo activity getting results before this Activity paused. @@ -3552,12 +3566,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAtmService.mH.post(() -> { synchronized (mAtmService.mGlobalLock) { resultToActivity.sendResult(this.getUid(), resultWho, requestCode, - resultCode, resultData, resultGrants, + resultCode, resultData, callerToken, resultGrants, mForceSendResultForMediaProjection); } }); } else { - resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData); + resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData, + callerToken); } resultTo = null; } else if (DEBUG_RESULTS) { @@ -4841,9 +4856,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void addResultLocked(ActivityRecord from, String resultWho, int requestCode, int resultCode, - Intent resultData) { + Intent resultData, IBinder callerToken) { ActivityResult r = new ActivityResult(from, resultWho, - requestCode, resultCode, resultData); + requestCode, resultCode, resultData, callerToken); if (results == null) { results = new ArrayList<ResultInfo>(); } @@ -4869,13 +4884,27 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } void sendResult(int callingUid, String resultWho, int requestCode, int resultCode, - Intent data, NeededUriGrants dataGrants) { - sendResult(callingUid, resultWho, requestCode, resultCode, data, dataGrants, + Intent data, IBinder callerToken, NeededUriGrants dataGrants) { + sendResult(callingUid, resultWho, requestCode, resultCode, data, callerToken, dataGrants, false /* forceSendForMediaProjection */); } void sendResult(int callingUid, String resultWho, int requestCode, int resultCode, - Intent data, NeededUriGrants dataGrants, boolean forceSendForMediaProjection) { + Intent data, IBinder callerToken, NeededUriGrants dataGrants, + boolean forceSendForMediaProjection) { + if (android.security.Flags.contentUriPermissionApis() + && !mCallerState.hasCaller(callerToken)) { + try { + computeCallerInfo(callerToken, data, callingUid, + mAtmService.getPackageManager().getNameForUid(callingUid), + false /* isShareIdentityEnabled */); + // Result callers cannot share their identity via + // {@link ActivityOptions#setShareIdentityEnabled(boolean)} since + // {@link android.app.Activity#setResult} doesn't have a {@link android.os.Bundle}. + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } if (callingUid > 0) { mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(dataGrants, getUriPermissionsLocked()); @@ -4891,7 +4920,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (isState(RESUMED) && attachedToProcess()) { try { final ArrayList<ResultInfo> list = new ArrayList<>(); - list.add(new ResultInfo(resultWho, requestCode, resultCode, data)); + list.add(new ResultInfo(resultWho, requestCode, resultCode, data, callerToken)); mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(), ActivityResultItem.obtain(token, list)); return; @@ -4905,7 +4934,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A STOPPING, STOPPED)) { // Build result to be returned immediately. final ActivityResultItem activityResultItem = ActivityResultItem.obtain( - token, List.of(new ResultInfo(resultWho, requestCode, resultCode, data))); + token, List.of(new ResultInfo(resultWho, requestCode, resultCode, data, + callerToken))); // When the activity result is delivered, the activity will transition to RESUMED. // Since the activity is only resumed so the result can be immediately delivered, // return it to its original lifecycle state. @@ -4929,7 +4959,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } - addResultLocked(null /* from */, resultWho, requestCode, resultCode, data); + addResultLocked(null /* from */, resultWho, requestCode, resultCode, data, callerToken); } /** diff --git a/services/core/java/com/android/server/wm/ActivityResult.java b/services/core/java/com/android/server/wm/ActivityResult.java index f2510de6dfb2..c5c51b50961c 100644 --- a/services/core/java/com/android/server/wm/ActivityResult.java +++ b/services/core/java/com/android/server/wm/ActivityResult.java @@ -18,16 +18,17 @@ package com.android.server.wm; import android.app.ResultInfo; import android.content.Intent; +import android.os.IBinder; /** * Pending result information to send back to an activity. */ final class ActivityResult extends ResultInfo { final ActivityRecord mFrom; - + public ActivityResult(ActivityRecord from, String resultWho, - int requestCode, int resultCode, Intent data) { - super(resultWho, requestCode, resultCode, data); + int requestCode, int resultCode, Intent data, IBinder callerToken) { + super(resultWho, requestCode, resultCode, data, callerToken); mFrom = from; } } diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 65d01efc6143..cfd049508e65 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1103,7 +1103,7 @@ class ActivityStarter { if (err != START_SUCCESS) { if (resultRecord != null) { resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED, - null /* data */, null /* dataGrants */); + null /* data */, null /* callerToken */, null /* dataGrants */); } SafeActivityOptions.abort(options); return err; @@ -1128,7 +1128,8 @@ class ActivityStarter { .filterAppAccess(targetPackageName, callingUid, userId)) { if (resultRecord != null) { resultRecord.sendResult(INVALID_UID, resultWho, requestCode, - RESULT_CANCELED, null /* data */, null /* dataGrants */); + RESULT_CANCELED, null /* data */, null /* callerToken */, + null /* dataGrants */); } SafeActivityOptions.abort(options); return ActivityManager.START_CLASS_NOT_FOUND; @@ -1216,7 +1217,7 @@ class ActivityStarter { if (abort) { if (resultRecord != null) { resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED, - null /* data */, null /* dataGrants */); + null /* data */, null /* callerToken */, null /* dataGrants */); } // We pretend to the caller that it was really started, but they will just get a // cancel result. @@ -1380,7 +1381,7 @@ class ActivityStarter { int requestCode = r.requestCode; if (resultRecord != null) { resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED, - null /* data */, null /* dataGrants */); + null /* data */, null /* callerToken */, null /* dataGrants */); } // We pretend to the caller that it was really started to make it backward compatible, but // they will just get a cancel result. @@ -1727,7 +1728,7 @@ class ActivityStarter { if (startResult != START_SUCCESS) { if (r.resultTo != null) { r.resultTo.sendResult(INVALID_UID, r.resultWho, r.requestCode, RESULT_CANCELED, - null /* data */, null /* dataGrants */); + null /* data */, null /* callerToken */, null /* dataGrants */); } return startResult; } @@ -2226,7 +2227,7 @@ class ActivityStarter { if (mStartActivity.resultTo != null) { mStartActivity.resultTo.sendResult(INVALID_UID, mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, - null /* data */, null /* dataGrants */); + null /* data */, null /* callerToken */, null /* dataGrants */); mStartActivity.resultTo = null; } @@ -2607,7 +2608,7 @@ class ActivityStarter { Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result."); mStartActivity.resultTo.sendResult(INVALID_UID, mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, - null /* data */, null /* dataGrants */); + null /* data */, null /* callerToken */, null /* dataGrants */); mStartActivity.resultTo = null; } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 445295a1c3ff..52fdfda7acfe 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -6334,7 +6334,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final NeededUriGrants dataGrants = collectGrants(data, r); synchronized (mGlobalLock) { - r.sendResult(callingUid, resultWho, requestCode, resultCode, data, dataGrants); + r.sendResult(callingUid, resultWho, requestCode, resultCode, data, new Binder(), + dataGrants); } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 49df39664b1c..09f5eda5b571 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -1118,7 +1118,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { if (resultRecord != null) { resultRecord.sendResult(INVALID_UID, resultWho, requestCode, - Activity.RESULT_CANCELED, null /* data */, null /* dataGrants */); + Activity.RESULT_CANCELED, null /* data */, null /* callerToken */, + null /* dataGrants */); } final String msg; if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java index 57b86324e171..807774f90655 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -725,8 +725,8 @@ public final class DisplayPowerControllerTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FAST_HDR_TRANSITIONS) public void testDisplayBrightnessHdr_SkipAnimationOnHdrAppearance() { + when(mDisplayManagerFlagsMock.isFastHdrTransitionsEnabled()).thenReturn(true); Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); @@ -757,12 +757,12 @@ public final class DisplayPowerControllerTest { advanceTime(1); // Run updatePowerState verify(mHolder.animator).animateTo(eq(hdrBrightness), eq(sdrBrightness), - eq(BRIGHTNESS_RAMP_RATE_MINIMUM), eq(false)); + eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE), eq(false)); } @Test - @RequiresFlagsEnabled(Flags.FLAG_FAST_HDR_TRANSITIONS) public void testDisplayBrightnessHdr_SkipAnimationOnHdrRemoval() { + when(mDisplayManagerFlagsMock.isFastHdrTransitionsEnabled()).thenReturn(true); Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); @@ -797,7 +797,7 @@ public final class DisplayPowerControllerTest { advanceTime(1); // Run updatePowerState verify(mHolder.animator).animateTo(eq(sdrBrightness), eq(sdrBrightness), - eq(BRIGHTNESS_RAMP_RATE_MINIMUM), eq(false)); + eq(BRIGHTNESS_RAMP_RATE_FAST_DECREASE), eq(false)); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 31d6fa3e91f8..67c528cf40ae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -769,7 +769,8 @@ public class ActivityRecordTests extends WindowTestsBase { activity.setState(STOPPED, "Testing"); ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build(); - activity.addResultLocked(topActivity, "resultWho", 0, 0, new Intent()); + activity.addResultLocked(topActivity, "resultWho", 0, 0, new Intent(), + /* callerToken */ null); topActivity.finishing = true; doReturn(TASK_FRAGMENT_VISIBILITY_VISIBLE).when(task).getVisibility(null); @@ -1298,8 +1299,8 @@ public class ActivityRecordTests extends WindowTestsBase { targetActivity.finishIfPossible(0, new Intent(), null, "test", false /* oomAdj */); waitUntilHandlersIdle(); - verify(resultToActivity).sendResult(anyInt(), eq(null), anyInt(), anyInt(), any(), eq(null), - anyBoolean()); + verify(resultToActivity).sendResult(anyInt(), eq(null), anyInt(), anyInt(), any(), any(), + eq(null), anyBoolean()); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index d5eeaa745a69..6132ee3c89c4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -1857,7 +1857,7 @@ public class ActivityStarterTests extends WindowTestsBase { startActivityInner(starter, targetRecord, sourceRecord, null /* options */, null /* inTask */, null /* inTaskFragment */); verify(sourceRecord).sendResult(anyInt(), any(), anyInt(), eq(RESULT_CANCELED), any(), - any()); + any(), any()); } @Test |