Merge "Add derek to the WEAR_OWNERS file" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 0c11811..4af2c52 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1893,6 +1893,7 @@
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 @@
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 @@
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 @@
@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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 15de42a..af5ea21 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4828,7 +4828,7 @@
@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 fae9f83..251f823 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -858,11 +858,15 @@
*/
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 @@
/**
* 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 @@
}
/**
+ * 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 @@
}
}
+ 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 cb06eea..21c67edc6 100644
--- a/core/java/android/app/ActivityGroup.java
+++ b/core/java/android/app/ActivityGroup.java
@@ -111,7 +111,7 @@
@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 @@
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 00ccd04..926e297 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3758,7 +3758,7 @@
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 @@
}
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 535f69f..213c38c 100644
--- a/core/java/android/app/ResultInfo.java
+++ b/core/java/android/app/ResultInfo.java
@@ -20,6 +20,7 @@
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 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 @@
} else {
out.writeInt(0);
}
+ out.writeStrongBinder(mCallerToken);
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -88,6 +97,7 @@
} else {
mData = null;
}
+ mCallerToken = in.readStrongBinder();
}
@Override
@@ -100,7 +110,8 @@
: 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 @@
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 72586b2..88089ee 100644
--- a/core/java/android/hardware/OverlayProperties.java
+++ b/core/java/android/hardware/OverlayProperties.java
@@ -71,17 +71,36 @@
/**
* @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 @@
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 f6b22ed..76c20ce 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -808,13 +808,11 @@
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 21fead9..2d9433e 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 @@
}
/**
+ * 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 02a4690..b1f10ee 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 @@
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 e7cc5303..d8594e5 100644
--- a/core/java/android/hardware/camera2/extension/SessionProcessor.java
+++ b/core/java/android/hardware/camera2/extension/SessionProcessor.java
@@ -18,8 +18,10 @@
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 @@
* 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 @@
}
@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 b2032fa..a7d6caf 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.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 @@
}
@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 9474a69..75deceb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1022,6 +1022,11 @@
// 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 @@
// 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 @@
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 @@
}
}
- if (sToolkitSetFrameRateReadOnlyFlagValue) {
+ if (shouldEnableDvrr()) {
// Boost the frame rate when the ViewRootImpl first becomes available.
boostFrameRate(FRAME_RATE_TOUCH_BOOST_TIME);
}
@@ -5187,7 +5194,10 @@
// Force recalculation of transparent regions
if (accessibilityFocusDirty) {
- requestLayout();
+ final Rect bounds = mAttachInfo.mTmpInvalRect;
+ if (getAccessibilityFocusedRect(bounds)) {
+ requestLayout();
+ }
}
mAttachInfo.mDrawingTime =
@@ -12340,12 +12350,12 @@
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 @@
|| 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 @@
// 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 4ba4ee3..6b427fc 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1409,6 +1409,42 @@
}
/**
+ * 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 e4be016..0e17626 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -4439,6 +4439,7 @@
* 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 @@
}
/**
+ * 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 @@
out.writeFloat(mDesiredHdrHeadroom);
if (sToolkitSetFrameRateReadOnlyFlagValue) {
out.writeBoolean(mFrameRateBoostOnTouch);
+ out.writeBoolean(mIsFrameRatePowerSavingsBalanced);
}
}
@@ -5130,6 +5162,7 @@
mDesiredHdrHeadroom = in.readFloat();
if (sToolkitSetFrameRateReadOnlyFlagValue) {
mFrameRateBoostOnTouch = in.readBoolean();
+ mIsFrameRatePowerSavingsBalanced = in.readBoolean();
}
}
@@ -5473,6 +5506,12 @@
changes |= LAYOUT_CHANGED;
}
+ if (sToolkitSetFrameRateReadOnlyFlagValue
+ && mIsFrameRatePowerSavingsBalanced != o.mIsFrameRatePowerSavingsBalanced) {
+ mIsFrameRatePowerSavingsBalanced = o.mIsFrameRatePowerSavingsBalanced;
+ changes |= LAYOUT_CHANGED;
+ }
+
return changes;
}
@@ -5700,6 +5739,11 @@
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 5239245..0dd01e4 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -363,6 +363,8 @@
private boolean mUseDecorContext = false;
+ private boolean mIsFrameRatePowerSavingsBalanced = true;
+
/** @see ViewRootImpl#mActivityConfigCallback */
private ActivityConfigCallback mActivityConfigCallback;
@@ -2211,6 +2213,7 @@
void onViewRootImplSet(ViewRootImpl viewRoot) {
viewRoot.setActivityConfigCallback(mActivityConfigCallback);
viewRoot.getOnBackInvokedDispatcher().updateContext(getContext());
+ viewRoot.setFrameRatePowerSavingsBalanced(mIsFrameRatePowerSavingsBalanced);
mProxyOnBackInvokedDispatcher.setActualDispatcher(viewRoot.getOnBackInvokedDispatcher());
applyDecorFitsSystemWindows();
}
@@ -2559,6 +2562,10 @@
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 f6fe3dd..96494b1 100644
--- a/core/jni/android_hardware_OverlayProperties.cpp
+++ b/core/jni/android_hardware_OverlayProperties.cpp
@@ -35,7 +35,6 @@
jclass clazz;
jmethodID ctor;
} gOverlayPropertiesClassInfo;
-
// ----------------------------------------------------------------------------
// OverlayProperties lifecycle
// ----------------------------------------------------------------------------
@@ -52,21 +51,21 @@
// 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 @@
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 @@
// 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 @@
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 cc6460e..c1fd619 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 8af8cb8..c797210 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 32eebb35..78cd1e1 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 433d353..038c00e 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -953,6 +953,22 @@
});
}
+ /**
+ * 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 3df3b9d2..b9841ff 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_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 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 @@
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 @@
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 af64926..afd4f7c 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 3cd709e..69e1982 100644
--- a/graphics/java/android/graphics/pdf/PdfEditor.java
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -25,7 +25,9 @@
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 @@
*/
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 @@
}
mInput = input;
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
mNativeDocument = nativeOpen(mInput.getFd(), size);
try {
mPageCount = nativeGetPageCount(mNativeDocument);
@@ -112,7 +120,7 @@
throwIfClosed();
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
mPageCount = nativeRemovePage(mNativeDocument, pageIndex);
}
}
@@ -138,12 +146,12 @@
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 @@
throwIfOutSizeNull(outSize);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeGetPageSize(mNativeDocument, pageIndex, outSize);
}
}
@@ -177,7 +185,7 @@
throwIfOutMediaBoxNull(outMediaBox);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox);
}
}
@@ -193,7 +201,7 @@
throwIfMediaBoxNull(mediaBox);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox);
}
}
@@ -209,7 +217,7 @@
throwIfOutCropBoxNull(outCropBox);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox);
}
}
@@ -225,7 +233,7 @@
throwIfCropBoxNull(cropBox);
throwIfPageNotInDocument(pageIndex);
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox);
}
}
@@ -238,7 +246,7 @@
public boolean shouldScaleForPrinting() {
throwIfClosed();
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
return nativeScaleForPrinting(mNativeDocument);
}
}
@@ -255,7 +263,7 @@
try {
throwIfClosed();
- synchronized (PdfRenderer.sPdfiumLock) {
+ synchronized (sPdfiumLock) {
nativeWrite(mNativeDocument, output.getFd());
}
} finally {
@@ -287,7 +295,7 @@
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 4666963..0000000
--- 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 4e330da..e4f3e2d 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -427,7 +427,6 @@
"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 883f273..fb0cdb0 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_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 @@
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 cc1f961..0000000
--- 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 9b3477f..54496bf 100644
--- a/media/java/android/media/metrics/EditingEndedEvent.java
+++ b/media/java/android/media/metrics/EditingEndedEvent.java
@@ -199,7 +199,7 @@
/** 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 @@
}
/**
- * 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 @@
}
/**
- * 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 63dd3cc..338697f 100644
--- a/media/java/android/media/metrics/MediaItemInfo.java
+++ b/media/java/android/media/metrics/MediaItemInfo.java
@@ -92,7 +92,7 @@
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 @@
/** 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 @@
/** 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 6766afc..b5951e8 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.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 @@
}
// 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 @@
// 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 @@
}
}
+ 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 d949396..621ddf7 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 @@
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 abac27f..23ba8d0 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 14fda5e..efbd59f 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 @@
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 @@
/** 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 @@
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 94cc7e9..f2b8482 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 @@
// 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 74ff78e..e8c59f4 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 @@
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 5ee94ba..82b7e14 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 @@
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 0afdefa..5614f3a 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 @@
}
@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 668b143..ca5ea3b 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 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 @@
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 @@
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 @@
@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 50d1547..e10d1cb 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 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 @@
"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 @@
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 @@
.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 90c5c62..4045630 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 @@
@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 @@
@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 936aa8b..91da88e 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 @@
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 3f3de00..fa669fc 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 @@
@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 25a0bc4..1a3cb87 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.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 @@
View mDrawerVibrate;
View mDrawerMute;
View mDrawerNormal;
+ ViewGroup mDialogRowsView;
CaptionsToggleImageButton mODICaptionsIcon;
private TestableLooper mTestableLooper;
@@ -222,6 +224,8 @@
}
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 @@
}
@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 b62b3a2..353d970 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.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 @@
@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 c134a4c..d8a94d8 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 @@
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);
-
- return ret;
+ if (entries == null || entries.isEmpty()) {
+ throw new RuntimeException("A valid set of key/value pairs are required that "
+ + "are supported by the extension.");
}
+
+ 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 1ca3923..d5863a7 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 @@
// 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 8cb5cef..f97f6d2 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.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -151,7 +152,9 @@
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 @@
}
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 d751186..53ae60b 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 @@
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 @@
// 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 @@
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 @@
pkg = info.component.getPackageName();
}
if (lifetimeExtensionRefactor()) {
- packageImportance = mActivityManager.getPackageImportance(pkg);
+ packageImportance = getPackageImportanceWithIdentity(pkg);
} else {
packageImportance = IMPORTANCE_NONE;
}
@@ -5348,7 +5347,7 @@
final int packageImportance;
try {
if (lifetimeExtensionRefactor()) {
- packageImportance = mActivityManager.getPackageImportance(pkg);
+ packageImportance = getPackageImportanceWithIdentity(pkg);
} else {
packageImportance = IMPORTANCE_NONE;
}
@@ -7609,14 +7608,9 @@
}
}
- // 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 @@
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 @@
}
}
+ @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 6ca4da2..4cf2066 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 0219645..03822aa 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 @@
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 b3a8b78..c36df8d 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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 f2510de..c5c51b5 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 @@
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 65d01efc..cfd04950 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 @@
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 @@
.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 @@
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 @@
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 @@
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 @@
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 @@
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 445295a..52fdfda 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 @@
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 49df396..09f5eda 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 @@
|| 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 57b8632..807774f 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 @@
}
@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 @@
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 @@
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 31d6fa3..67c528c 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 @@
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 @@
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 d5eeaa7..6132ee3 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 @@
startActivityInner(starter, targetRecord, sourceRecord, null /* options */,
null /* inTask */, null /* inTaskFragment */);
verify(sourceRecord).sendResult(anyInt(), any(), anyInt(), eq(RESULT_CANCELED), any(),
- any());
+ any(), any());
}
@Test