Merge changes from topic "cherrypick-bt-apm-notification-6f5u3o536b-tm-mainline-prod"
* changes:
[automerged blank] Use message ID from proto for BT APM notification 2p: 47d70626de
Use message ID from proto for BT APM notification Bug: 249590939 Bug: 239983569 Test: atest ServiceBluetoothTests
diff --git a/core/api/current.txt b/core/api/current.txt
index c7ca0cd..e30761f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -22438,6 +22438,7 @@
field public static final String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
field public static final String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
field public static final String MIMETYPE_IMAGE_ANDROID_HEIC = "image/vnd.android.heic";
+ field public static final String MIMETYPE_IMAGE_AVIF = "image/avif";
field public static final String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
field public static final String MIMETYPE_TEXT_CEA_708 = "text/cea-708";
field public static final String MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 8b3451e..92088e9 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -65,6 +65,7 @@
import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.Dialog;
+import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
@@ -546,6 +547,20 @@
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
public static final long FINISH_INPUT_NO_FALLBACK_CONNECTION = 156215187L; // This is a bug id.
+ /**
+ * Disallow IMEs to override {@link InputMethodService#onCreateInputMethodSessionInterface()}
+ * method.
+ *
+ * <p>If IMEs targeting on Android U and beyond override the
+ * {@link InputMethodService#onCreateInputMethodSessionInterface()}, an {@link LinkageError}
+ * would be thrown.</p>
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ private static final long DISALLOW_INPUT_METHOD_INTERFACE_OVERRIDE = 148086656L;
+
LayoutInflater mInflater;
TypedArray mThemeAttrs;
@UnsupportedAppUsage
@@ -1527,6 +1542,11 @@
}
@Override public void onCreate() {
+ if (methodIsOverridden("onCreateInputMethodSessionInterface")
+ && CompatChanges.isChangeEnabled(DISALLOW_INPUT_METHOD_INTERFACE_OVERRIDE)) {
+ throw new LinkageError("InputMethodService#onCreateInputMethodSessionInterface()"
+ + " can no longer be overridden!");
+ }
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.onCreate");
mTheme = Resources.selectSystemTheme(mTheme,
getApplicationInfo().targetSdkVersion,
@@ -1764,6 +1784,9 @@
* {@link InputMethodService#onDisplayCompletions(CompletionInfo[])},
* {@link InputMethodService#onUpdateExtractedText(int, ExtractedText)},
* {@link InputMethodService#onUpdateSelection(int, int, int, int, int, int)} instead.
+ *
+ * <p>IMEs targeting on Android U and above cannot override this method, or an
+ * {@link LinkageError} would be thrown.</p>
*/
@Deprecated
@Override
@@ -4067,4 +4090,13 @@
final KeyEvent upEvent = createBackKeyEvent(KeyEvent.ACTION_UP, hasStartedTracking);
onKeyUp(KeyEvent.KEYCODE_BACK, upEvent);
}
+
+ private boolean methodIsOverridden(String methodName, Class<?>... parameterTypes) {
+ try {
+ return getClass().getMethod(methodName, parameterTypes).getDeclaringClass()
+ != InputMethodService.class;
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Method must exist.", e);
+ }
+ }
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index b2a26fa..067946e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -67,6 +67,7 @@
import android.view.displayhash.DisplayHash;
import android.view.displayhash.VerifiedDisplayHash;
import android.window.ITaskFpsCallback;
+import android.window.ScreenCapture;
/**
* System private interface to the window manager.
@@ -968,4 +969,11 @@
* treatment.
*/
boolean isLetterboxBackgroundMultiColored();
+
+ /**
+ * Captures the entire display specified by the displayId using the args provided. If the args
+ * are null or if the sourceCrop is invalid or null, the entire display bounds will be captured.
+ */
+ oneway void captureDisplay(int displayId, in @nullable ScreenCapture.CaptureArgs captureArgs,
+ in ScreenCapture.ScreenCaptureListener listener);
}
diff --git a/core/java/android/window/ScreenCapture.aidl b/core/java/android/window/ScreenCapture.aidl
new file mode 100644
index 0000000..267a7c6
--- /dev/null
+++ b/core/java/android/window/ScreenCapture.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+/** @hide */
+parcelable ScreenCapture.CaptureArgs;
+
+/** @hide */
+parcelable ScreenCapture.ScreenshotHardwareBuffer;
+
+/** @hide */
+parcelable ScreenCapture.ScreenCaptureListener;
\ No newline at end of file
diff --git a/core/java/android/window/ScreenCapture.java b/core/java/android/window/ScreenCapture.java
index 887d027..8a7efb9 100644
--- a/core/java/android/window/ScreenCapture.java
+++ b/core/java/android/window/ScreenCapture.java
@@ -24,11 +24,17 @@
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.Log;
+import android.util.Pair;
import android.view.SurfaceControl;
+import libcore.util.NativeAllocationRegistry;
+
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
/**
* Handles display and layer captures for the system.
@@ -37,20 +43,26 @@
*/
public class ScreenCapture {
private static final String TAG = "ScreenCapture";
+ private static final int SCREENSHOT_WAIT_TIME_S = 1;
private static native int nativeCaptureDisplay(DisplayCaptureArgs captureArgs,
- ScreenCaptureListener captureListener);
+ long captureListener);
private static native int nativeCaptureLayers(LayerCaptureArgs captureArgs,
- ScreenCaptureListener captureListener);
+ long captureListener);
+ private static native long nativeCreateScreenCaptureListener(
+ Consumer<ScreenshotHardwareBuffer> consumer);
+ private static native void nativeWriteListenerToParcel(long nativeObject, Parcel out);
+ private static native long nativeReadListenerFromParcel(Parcel in);
+ private static native long getNativeListenerFinalizer();
/**
- * @param captureArgs Arguments about how to take the screenshot
+ * @param captureArgs Arguments about how to take the screenshot
* @param captureListener A listener to receive the screenshot callback
* @hide
*/
public static int captureDisplay(@NonNull DisplayCaptureArgs captureArgs,
@NonNull ScreenCaptureListener captureListener) {
- return nativeCaptureDisplay(captureArgs, captureListener);
+ return nativeCaptureDisplay(captureArgs, captureListener.mNativeObject);
}
/**
@@ -61,28 +73,29 @@
*/
public static ScreenshotHardwareBuffer captureDisplay(
DisplayCaptureArgs captureArgs) {
- SyncScreenCaptureListener
- screenCaptureListener = new SyncScreenCaptureListener();
-
- int status = captureDisplay(captureArgs, screenCaptureListener);
+ Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture = createSyncCaptureListener();
+ int status = captureDisplay(captureArgs, syncScreenCapture.first);
if (status != 0) {
return null;
}
- return screenCaptureListener.waitForScreenshot();
+ try {
+ return syncScreenCapture.second.get();
+ } catch (Exception e) {
+ return null;
+ }
}
/**
* Captures a layer and its children and returns a {@link HardwareBuffer} with the content.
*
- * @param layer The root layer to capture.
- * @param sourceCrop The portion of the root surface to capture; caller may pass in 'new
- * Rect()' or null if no cropping is desired. If the root layer does not
- * have a buffer or a crop set, then a non-empty source crop must be
- * specified.
- * @param frameScale The desired scale of the returned buffer; the raw
- * screen will be scaled up/down.
- *
+ * @param layer The root layer to capture.
+ * @param sourceCrop The portion of the root surface to capture; caller may pass in 'new
+ * Rect()' or null if no cropping is desired. If the root layer does not
+ * have a buffer or a crop set, then a non-empty source crop must be
+ * specified.
+ * @param frameScale The desired scale of the returned buffer; the raw screen will be scaled
+ * up/down.
* @return Returns a HardwareBuffer that contains the layer capture.
* @hide
*/
@@ -94,15 +107,14 @@
/**
* Captures a layer and its children and returns a {@link HardwareBuffer} with the content.
*
- * @param layer The root layer to capture.
- * @param sourceCrop The portion of the root surface to capture; caller may pass in 'new
- * Rect()' or null if no cropping is desired. If the root layer does not
- * have a buffer or a crop set, then a non-empty source crop must be
- * specified.
- * @param frameScale The desired scale of the returned buffer; the raw
- * screen will be scaled up/down.
- * @param format The desired pixel format of the returned buffer.
- *
+ * @param layer The root layer to capture.
+ * @param sourceCrop The portion of the root surface to capture; caller may pass in 'new
+ * Rect()' or null if no cropping is desired. If the root layer does not
+ * have a buffer or a crop set, then a non-empty source crop must be
+ * specified.
+ * @param frameScale The desired scale of the returned buffer; the raw screen will be scaled
+ * up/down.
+ * @param format The desired pixel format of the returned buffer.
* @return Returns a HardwareBuffer that contains the layer capture.
* @hide
*/
@@ -120,21 +132,24 @@
/**
* @hide
*/
- public static ScreenshotHardwareBuffer captureLayers(
- LayerCaptureArgs captureArgs) {
- SyncScreenCaptureListener screenCaptureListener = new SyncScreenCaptureListener();
-
- int status = captureLayers(captureArgs, screenCaptureListener);
+ public static ScreenshotHardwareBuffer captureLayers(LayerCaptureArgs captureArgs) {
+ Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture = createSyncCaptureListener();
+ int status = captureLayers(captureArgs, syncScreenCapture.first);
if (status != 0) {
return null;
}
- return screenCaptureListener.waitForScreenshot();
+ try {
+ return syncScreenCapture.second.get();
+ } catch (Exception e) {
+ return null;
+ }
}
/**
* Like {@link #captureLayers(SurfaceControl, Rect, float, int)} but with an array of layer
* handles to exclude.
+ *
* @hide
*/
public static ScreenshotHardwareBuffer captureLayersExcluding(SurfaceControl layer,
@@ -150,24 +165,13 @@
}
/**
- * @param captureArgs Arguments about how to take the screenshot
+ * @param captureArgs Arguments about how to take the screenshot
* @param captureListener A listener to receive the screenshot callback
* @hide
*/
public static int captureLayers(@NonNull LayerCaptureArgs captureArgs,
@NonNull ScreenCaptureListener captureListener) {
- return nativeCaptureLayers(captureArgs, captureListener);
- }
-
- /**
- * @hide
- */
- public interface ScreenCaptureListener {
- /**
- * The callback invoked when the screen capture is complete.
- * @param hardwareBuffer Data containing info about the screen capture.
- */
- void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer);
+ return nativeCaptureLayers(captureArgs, captureListener.mNativeObject);
}
/**
@@ -190,15 +194,16 @@
mContainsHdrLayers = containsHdrLayers;
}
- /**
- * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object.
- * @param hardwareBuffer The existing HardwareBuffer object
- * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
- * @param containsSecureLayers Indicates whether this graphic buffer contains captured
- * contents of secure layers, in which case the screenshot
- * should not be persisted.
- * @param containsHdrLayers Indicates whether this graphic buffer contains HDR content.
- */
+ /**
+ * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object.
+ *
+ * @param hardwareBuffer The existing HardwareBuffer object
+ * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
+ * @param containsSecureLayers Indicates whether this graphic buffer contains captured
+ * contents of secure layers, in which case the screenshot
+ * should not be persisted.
+ * @param containsHdrLayers Indicates whether this graphic buffer contains HDR content.
+ */
private static ScreenshotHardwareBuffer createFromNative(HardwareBuffer hardwareBuffer,
int namedColorSpace, boolean containsSecureLayers, boolean containsHdrLayers) {
ColorSpace colorSpace = ColorSpace.get(ColorSpace.Named.values()[namedColorSpace]);
@@ -220,6 +225,7 @@
public boolean containsSecureLayers() {
return mContainsSecureLayers;
}
+
/**
* Returns whether the screenshot contains at least one HDR layer.
* This information may be useful for informing the display whether this screenshot
@@ -234,7 +240,7 @@
* Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap
* into
* a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
- *
+ * <p>
* CAVEAT: This can be extremely slow; avoid use unless absolutely necessary; prefer to
* directly
* use the {@link HardwareBuffer} directly.
@@ -250,44 +256,23 @@
}
}
- private static class SyncScreenCaptureListener implements ScreenCaptureListener {
- private static final int SCREENSHOT_WAIT_TIME_S = 1;
- private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
- private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
-
- @Override
- public void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) {
- mScreenshotHardwareBuffer = hardwareBuffer;
- mCountDownLatch.countDown();
- }
-
- private ScreenshotHardwareBuffer waitForScreenshot() {
- try {
- mCountDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
- } catch (Exception e) {
- Log.e(TAG, "Failed to wait for screen capture result", e);
- }
-
- return mScreenshotHardwareBuffer;
- }
- }
-
/**
* A common arguments class used for various screenshot requests. This contains arguments that
* are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
+ *
* @hide
*/
- private abstract static class CaptureArgs {
- private final int mPixelFormat;
- private final Rect mSourceCrop = new Rect();
- private final float mFrameScaleX;
- private final float mFrameScaleY;
- private final boolean mCaptureSecureLayers;
- private final boolean mAllowProtected;
- private final long mUid;
- private final boolean mGrayscale;
+ public static class CaptureArgs implements Parcelable {
+ public final int mPixelFormat;
+ public final Rect mSourceCrop = new Rect();
+ public final float mFrameScaleX;
+ public final float mFrameScaleY;
+ public final boolean mCaptureSecureLayers;
+ public final boolean mAllowProtected;
+ public final long mUid;
+ public final boolean mGrayscale;
- private CaptureArgs(Builder<? extends Builder<?>> builder) {
+ private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) {
mPixelFormat = builder.mPixelFormat;
mSourceCrop.set(builder.mSourceCrop);
mFrameScaleX = builder.mFrameScaleX;
@@ -298,12 +283,23 @@
mGrayscale = builder.mGrayscale;
}
+ private CaptureArgs(Parcel in) {
+ mPixelFormat = in.readInt();
+ mSourceCrop.readFromParcel(in);
+ mFrameScaleX = in.readFloat();
+ mFrameScaleY = in.readFloat();
+ mCaptureSecureLayers = in.readBoolean();
+ mAllowProtected = in.readBoolean();
+ mUid = in.readLong();
+ mGrayscale = in.readBoolean();
+ }
+
/**
* The Builder class used to construct {@link CaptureArgs}
*
- * @param <T> A builder that extends {@link Builder}
+ * @param <T> A builder that extends {@link CaptureArgs.Builder}
*/
- abstract static class Builder<T extends Builder<T>> {
+ public static class Builder<T extends CaptureArgs.Builder<T>> {
private int mPixelFormat = PixelFormat.RGBA_8888;
private final Rect mSourceCrop = new Rect();
private float mFrameScaleX = 1;
@@ -314,6 +310,14 @@
private boolean mGrayscale;
/**
+ * Construct a new {@link CaptureArgs} with the set parameters. The builder remains
+ * valid.
+ */
+ public CaptureArgs build() {
+ return new CaptureArgs(this);
+ }
+
+ /**
* The desired pixel format of the returned buffer.
*/
public T setPixelFormat(int pixelFormat) {
@@ -395,15 +399,47 @@
/**
* Each sub class should return itself to allow the builder to chain properly
*/
- abstract T getThis();
+ T getThis() {
+ return (T) this;
+ }
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mPixelFormat);
+ mSourceCrop.writeToParcel(dest, flags);
+ dest.writeFloat(mFrameScaleX);
+ dest.writeFloat(mFrameScaleY);
+ dest.writeBoolean(mCaptureSecureLayers);
+ dest.writeBoolean(mAllowProtected);
+ dest.writeLong(mUid);
+ dest.writeBoolean(mGrayscale);
+ }
+
+ public static final Parcelable.Creator<CaptureArgs> CREATOR =
+ new Parcelable.Creator<CaptureArgs>() {
+ @Override
+ public CaptureArgs createFromParcel(Parcel in) {
+ return new CaptureArgs(in);
+ }
+
+ @Override
+ public CaptureArgs[] newArray(int size) {
+ return new CaptureArgs[size];
+ }
+ };
}
/**
* The arguments class used to make display capture requests.
*
- * @see #nativeCaptureDisplay(DisplayCaptureArgs, ScreenCaptureListener)
* @hide
+ * @see #nativeCaptureDisplay(DisplayCaptureArgs, long)
*/
public static class DisplayCaptureArgs extends CaptureArgs {
private final IBinder mDisplayToken;
@@ -488,8 +524,8 @@
/**
* The arguments class used to make layer capture requests.
*
- * @see #nativeCaptureLayers(LayerCaptureArgs, ScreenCaptureListener)
* @hide
+ * @see #nativeCaptureLayers(LayerCaptureArgs, long)
*/
public static class LayerCaptureArgs extends CaptureArgs {
private final long mNativeLayer;
@@ -530,6 +566,17 @@
return new LayerCaptureArgs(this);
}
+ public Builder(SurfaceControl layer, CaptureArgs args) {
+ setLayer(layer);
+ setPixelFormat(args.mPixelFormat);
+ setSourceCrop(args.mSourceCrop);
+ setFrameScale(args.mFrameScaleX, args.mFrameScaleY);
+ setCaptureSecureLayers(args.mCaptureSecureLayers);
+ setAllowProtected(args.mAllowProtected);
+ setUid(args.mUid);
+ setGrayscale(args.mGrayscale);
+ }
+
public Builder(SurfaceControl layer) {
setLayer(layer);
}
@@ -542,7 +589,6 @@
return this;
}
-
/**
* An array of layer handles to exclude.
*/
@@ -564,8 +610,109 @@
Builder getThis() {
return this;
}
-
}
}
+ /**
+ * The object used to receive the results when invoking screen capture requests via
+ * {@link #captureDisplay(DisplayCaptureArgs, ScreenCaptureListener)} or
+ * {@link #captureLayers(LayerCaptureArgs, ScreenCaptureListener)}
+ *
+ * This listener can only be used for a single call to capture content call.
+ */
+ public static class ScreenCaptureListener implements Parcelable {
+ private final long mNativeObject;
+ private static final NativeAllocationRegistry sRegistry =
+ NativeAllocationRegistry.createMalloced(
+ ScreenCaptureListener.class.getClassLoader(), getNativeListenerFinalizer());
+
+ /**
+ * @param consumer The callback invoked when the screen capture is complete.
+ */
+ public ScreenCaptureListener(Consumer<ScreenshotHardwareBuffer> consumer) {
+ mNativeObject = nativeCreateScreenCaptureListener(consumer);
+ sRegistry.registerNativeAllocation(this, mNativeObject);
+ }
+
+ private ScreenCaptureListener(Parcel in) {
+ if (in.readBoolean()) {
+ mNativeObject = nativeReadListenerFromParcel(in);
+ sRegistry.registerNativeAllocation(this, mNativeObject);
+ } else {
+ mNativeObject = 0;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ if (mNativeObject == 0) {
+ dest.writeBoolean(false);
+ } else {
+ dest.writeBoolean(true);
+ nativeWriteListenerToParcel(mNativeObject, dest);
+ }
+ }
+
+ public static final Parcelable.Creator<ScreenCaptureListener> CREATOR =
+ new Parcelable.Creator<ScreenCaptureListener>() {
+ @Override
+ public ScreenCaptureListener createFromParcel(Parcel in) {
+ return new ScreenCaptureListener(in);
+ }
+
+ @Override
+ public ScreenCaptureListener[] newArray(int size) {
+ return new ScreenCaptureListener[0];
+ }
+ };
+ }
+
+ /**
+ * A helper method to handle the async screencapture callbacks synchronously. This should only
+ * be used if the screencapture caller doesn't care that it blocks waiting for a screenshot.
+ *
+ * @return a Pair that holds the {@link ScreenCaptureListener} that should be used for capture
+ * calls into SurfaceFlinger and a {@link ScreenshotSync} object to retrieve the results.
+ */
+ public static Pair<ScreenCaptureListener, ScreenshotSync> createSyncCaptureListener() {
+ final ScreenshotSync screenshotSync = new ScreenshotSync();
+ final ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener(
+ screenshotSync::setScreenshotHardwareBuffer);
+ return new Pair<>(screenCaptureListener, screenshotSync);
+ }
+
+ /**
+ * Helper class to synchronously get the {@link ScreenshotHardwareBuffer} when calling
+ * {@link #captureLayers(LayerCaptureArgs, ScreenCaptureListener)} or
+ * {@link #captureDisplay(DisplayCaptureArgs, ScreenCaptureListener)}
+ */
+ public static class ScreenshotSync {
+ private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+ private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
+
+ private void setScreenshotHardwareBuffer(
+ ScreenshotHardwareBuffer screenshotHardwareBuffer) {
+ mScreenshotHardwareBuffer = screenshotHardwareBuffer;
+ mCountDownLatch.countDown();
+ }
+
+ /**
+ * Get the {@link ScreenshotHardwareBuffer} synchronously. This can be null if the
+ * screenshot failed or if there was no callback in {@link #SCREENSHOT_WAIT_TIME_S} seconds.
+ */
+ public ScreenshotHardwareBuffer get() {
+ try {
+ mCountDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
+ return mScreenshotHardwareBuffer;
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to wait for screen capture result", e);
+ return null;
+ }
+ }
+ }
}
diff --git a/core/jni/android_window_ScreenCapture.cpp b/core/jni/android_window_ScreenCapture.cpp
index 3bada15..c1929c6 100644
--- a/core/jni/android_window_ScreenCapture.cpp
+++ b/core/jni/android_window_ScreenCapture.cpp
@@ -61,9 +61,8 @@
} gLayerCaptureArgsClassInfo;
static struct {
- jclass clazz;
- jmethodID onScreenCaptureComplete;
-} gScreenCaptureListenerClassInfo;
+ jmethodID accept;
+} gConsumerClassInfo;
static struct {
jclass clazz;
@@ -98,14 +97,14 @@
public:
explicit ScreenCaptureListenerWrapper(JNIEnv* env, jobject jobject) {
env->GetJavaVM(&mVm);
- mScreenCaptureListenerObject = env->NewGlobalRef(jobject);
- LOG_ALWAYS_FATAL_IF(!mScreenCaptureListenerObject, "Failed to make global ref");
+ mConsumerObject = env->NewGlobalRef(jobject);
+ LOG_ALWAYS_FATAL_IF(!mConsumerObject, "Failed to make global ref");
}
~ScreenCaptureListenerWrapper() {
- if (mScreenCaptureListenerObject) {
- getenv()->DeleteGlobalRef(mScreenCaptureListenerObject);
- mScreenCaptureListenerObject = nullptr;
+ if (mConsumerObject) {
+ getenv()->DeleteGlobalRef(mConsumerObject);
+ mConsumerObject = nullptr;
}
}
@@ -113,9 +112,8 @@
const gui::ScreenCaptureResults& captureResults) override {
JNIEnv* env = getenv();
if (!captureResults.fenceResult.ok() || captureResults.buffer == nullptr) {
- env->CallVoidMethod(mScreenCaptureListenerObject,
- gScreenCaptureListenerClassInfo.onScreenCaptureComplete, nullptr);
- checkAndClearException(env, "onScreenCaptureComplete");
+ env->CallVoidMethod(mConsumerObject, gConsumerClassInfo.accept, nullptr);
+ checkAndClearException(env, "accept");
return binder::Status::ok();
}
captureResults.fenceResult.value()->waitForever(LOG_TAG);
@@ -130,17 +128,15 @@
captureResults.capturedSecureLayers,
captureResults.capturedHdrLayers);
checkAndClearException(env, "builder");
- env->CallVoidMethod(mScreenCaptureListenerObject,
- gScreenCaptureListenerClassInfo.onScreenCaptureComplete,
- screenshotHardwareBuffer);
- checkAndClearException(env, "onScreenCaptureComplete");
+ env->CallVoidMethod(mConsumerObject, gConsumerClassInfo.accept, screenshotHardwareBuffer);
+ checkAndClearException(env, "accept");
env->DeleteLocalRef(jhardwareBuffer);
env->DeleteLocalRef(screenshotHardwareBuffer);
return binder::Status::ok();
}
private:
- jobject mScreenCaptureListenerObject;
+ jobject mConsumerObject;
JavaVM* mVm;
JNIEnv* getenv() {
@@ -194,7 +190,7 @@
}
static jint nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject,
- jobject screenCaptureListenerObject) {
+ jlong screenCaptureListenerObject) {
const DisplayCaptureArgs captureArgs =
displayCaptureArgsFromObject(env, displayCaptureArgsObject);
@@ -202,13 +198,13 @@
return BAD_VALUE;
}
- sp<IScreenCaptureListener> captureListener =
- sp<ScreenCaptureListenerWrapper>::make(env, screenCaptureListenerObject);
+ sp<gui::IScreenCaptureListener> captureListener =
+ reinterpret_cast<gui::IScreenCaptureListener*>(screenCaptureListenerObject);
return ScreenshotClient::captureDisplay(captureArgs, captureListener);
}
static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject,
- jobject screenCaptureListenerObject) {
+ jlong screenCaptureListenerObject) {
LayerCaptureArgs captureArgs;
getCaptureArgs(env, layerCaptureArgsObject, captureArgs);
SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
@@ -238,21 +234,70 @@
}
}
- sp<IScreenCaptureListener> captureListener =
- sp<ScreenCaptureListenerWrapper>::make(env, screenCaptureListenerObject);
+ sp<gui::IScreenCaptureListener> captureListener =
+ reinterpret_cast<gui::IScreenCaptureListener*>(screenCaptureListenerObject);
return ScreenshotClient::captureLayers(captureArgs, captureListener);
}
+static jlong nativeCreateScreenCaptureListener(JNIEnv* env, jclass clazz, jobject consumerObj) {
+ sp<gui::IScreenCaptureListener> listener =
+ sp<ScreenCaptureListenerWrapper>::make(env, consumerObj);
+ listener->incStrong((void*)nativeCreateScreenCaptureListener);
+ return reinterpret_cast<jlong>(listener.get());
+}
+
+static void nativeWriteListenerToParcel(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jobject parcelObj) {
+ Parcel* parcel = parcelForJavaObject(env, parcelObj);
+ if (parcel == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return;
+ }
+ ScreenCaptureListenerWrapper* const self =
+ reinterpret_cast<ScreenCaptureListenerWrapper*>(nativeObject);
+ if (self != nullptr) {
+ parcel->writeStrongBinder(IInterface::asBinder(self));
+ }
+}
+
+static jlong nativeReadListenerFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) {
+ Parcel* parcel = parcelForJavaObject(env, parcelObj);
+ if (parcel == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return 0;
+ }
+ sp<gui::IScreenCaptureListener> listener =
+ interface_cast<gui::IScreenCaptureListener>(parcel->readStrongBinder());
+ if (listener == nullptr) {
+ return 0;
+ }
+ listener->incStrong((void*)nativeCreateScreenCaptureListener);
+ return reinterpret_cast<jlong>(listener.get());
+}
+
+void destroyNativeListener(void* ptr) {
+ ScreenCaptureListenerWrapper* listener = reinterpret_cast<ScreenCaptureListenerWrapper*>(ptr);
+ listener->decStrong((void*)nativeCreateScreenCaptureListener);
+}
+
+static jlong getNativeListenerFinalizer(JNIEnv* env, jclass clazz) {
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeListener));
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod sScreenCaptureMethods[] = {
// clang-format off
- {"nativeCaptureDisplay",
- "(Landroid/window/ScreenCapture$DisplayCaptureArgs;Landroid/window/ScreenCapture$ScreenCaptureListener;)I",
+ {"nativeCaptureDisplay", "(Landroid/window/ScreenCapture$DisplayCaptureArgs;J)I",
(void*)nativeCaptureDisplay },
- {"nativeCaptureLayers",
- "(Landroid/window/ScreenCapture$LayerCaptureArgs;Landroid/window/ScreenCapture$ScreenCaptureListener;)I",
+ {"nativeCaptureLayers", "(Landroid/window/ScreenCapture$LayerCaptureArgs;J)I",
(void*)nativeCaptureLayers },
+ {"nativeCreateScreenCaptureListener", "(Ljava/util/function/Consumer;)J",
+ (void*)nativeCreateScreenCaptureListener },
+ {"nativeWriteListenerToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteListenerToParcel },
+ {"nativeReadListenerFromParcel", "(Landroid/os/Parcel;)J",
+ (void*)nativeReadListenerFromParcel },
+ {"getNativeListenerFinalizer", "()J", (void*)getNativeListenerFinalizer },
// clang-format on
};
@@ -293,12 +338,8 @@
gLayerCaptureArgsClassInfo.childrenOnly =
GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z");
- jclass screenCaptureListenerClazz =
- FindClassOrDie(env, "android/window/ScreenCapture$ScreenCaptureListener");
- gScreenCaptureListenerClassInfo.clazz = MakeGlobalRefOrDie(env, screenCaptureListenerClazz);
- gScreenCaptureListenerClassInfo.onScreenCaptureComplete =
- GetMethodIDOrDie(env, screenCaptureListenerClazz, "onScreenCaptureComplete",
- "(Landroid/window/ScreenCapture$ScreenshotHardwareBuffer;)V");
+ jclass consumer = FindClassOrDie(env, "java/util/function/Consumer");
+ gConsumerClassInfo.accept = GetMethodIDOrDie(env, consumer, "accept", "(Ljava/lang/Object;)V");
jclass screenshotGraphicsBufferClazz =
FindClassOrDie(env, "android/window/ScreenCapture$ScreenshotHardwareBuffer");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index c11c577..37a50b6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -188,14 +188,16 @@
@ShellMainThread Choreographer mainChoreographer,
ShellTaskOrganizer taskOrganizer,
DisplayController displayController,
- SyncTransactionQueue syncQueue) {
+ SyncTransactionQueue syncQueue,
+ @DynamicOverride DesktopModeController desktopModeController) {
return new CaptionWindowDecorViewModel(
context,
mainHandler,
mainChoreographer,
taskOrganizer,
displayController,
- syncQueue);
+ syncQueue,
+ desktopModeController);
}
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
index 9474cfe..99739c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
@@ -177,6 +177,25 @@
}
/**
+ * Turn desktop mode on or off
+ * @param active the desired state for desktop mode setting
+ */
+ public void setDesktopModeActive(boolean active) {
+ int value = active ? 1 : 0;
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.DESKTOP_MODE, value);
+ }
+
+ /**
+ * Returns the windowing mode of the display area with the specified displayId.
+ * @param displayId
+ * @return
+ */
+ public int getDisplayAreaWindowingMode(int displayId) {
+ return mRootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)
+ .configuration.windowConfiguration.getWindowingMode();
+ }
+
+ /**
* A {@link ContentObserver} for listening to changes to {@link Settings.System#DESKTOP_MODE}
*/
private final class SettingsObserver extends ContentObserver {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 8b36db920..9e49b51 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -37,6 +37,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
import com.android.wm.shell.transition.Transitions;
@@ -54,6 +55,7 @@
private final DisplayController mDisplayController;
private final SyncTransactionQueue mSyncQueue;
private FreeformTaskTransitionStarter mTransitionStarter;
+ private DesktopModeController mDesktopModeController;
public CaptionWindowDecorViewModel(
Context context,
@@ -61,7 +63,8 @@
Choreographer mainChoreographer,
ShellTaskOrganizer taskOrganizer,
DisplayController displayController,
- SyncTransactionQueue syncQueue) {
+ SyncTransactionQueue syncQueue,
+ DesktopModeController desktopModeController) {
mContext = context;
mMainHandler = mainHandler;
mMainChoreographer = mainChoreographer;
@@ -69,6 +72,7 @@
mTaskOrganizer = taskOrganizer;
mDisplayController = displayController;
mSyncQueue = syncQueue;
+ mDesktopModeController = desktopModeController;
}
@Override
@@ -211,8 +215,10 @@
}
private void handleEventForMove(MotionEvent e) {
- if (mTaskOrganizer.getRunningTaskInfo(mTaskId).getWindowingMode()
- == WINDOWING_MODE_FULLSCREEN) {
+ RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+ int windowingMode = mDesktopModeController
+ .getDisplayAreaWindowingMode(taskInfo.displayId);
+ if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
return;
}
switch (e.getActionMasked()) {
@@ -230,8 +236,14 @@
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
int dragPointerIdx = e.findPointerIndex(mDragPointerId);
+ int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId)
+ .stableInsets().top;
mDragResizeCallback.onDragResizeEnd(
e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
+ if (e.getRawY(dragPointerIdx) <= statusBarHeight
+ && windowingMode == WINDOWING_MODE_FREEFORM) {
+ mDesktopModeController.setDesktopModeActive(false);
+ }
break;
}
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 59c914f..03f02de 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -243,7 +243,9 @@
mContext->unpinImages();
for (size_t i = 0; i < mLayers.size(); i++) {
- mLayers[i]->apply();
+ if (mLayers[i]) {
+ mLayers[i]->apply();
+ }
}
mLayers.clear();
mContext->setContentDrawBounds(mContentDrawBounds);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index be9862b..49b314d 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -242,13 +242,14 @@
* To decode such an image, {@link MediaCodec} decoder for
* {@link #MIMETYPE_VIDEO_HEVC} shall be used. The client needs to form
* the correct {@link #MediaFormat} based on additional information in
- * the track format, and send it to {@link MediaCodec#configure}.
+ * the track format (shown in the next paragraph), and send it to
+ * {@link MediaCodec#configure}.
*
* The track's MediaFormat will come with {@link #KEY_WIDTH} and
* {@link #KEY_HEIGHT} keys, which describes the width and height
* of the image. If the image doesn't contain grid (i.e. none of
* {@link #KEY_TILE_WIDTH}, {@link #KEY_TILE_HEIGHT},
- * {@link #KEY_GRID_ROWS}, {@link #KEY_GRID_COLUMNS} are present}), the
+ * {@link #KEY_GRID_ROWS}, {@link #KEY_GRID_COLUMNS} are present), the
* track will contain a single sample of coded data for the entire image,
* and the image width and height should be used to set up the decoder.
*
@@ -266,6 +267,36 @@
public static final String MIMETYPE_IMAGE_ANDROID_HEIC = "image/vnd.android.heic";
/**
+ * MIME type for AVIF still image data encoded in AV1.
+ *
+ * To decode such an image, {@link MediaCodec} decoder for
+ * {@link #MIMETYPE_VIDEO_AV1} shall be used. The client needs to form
+ * the correct {@link #MediaFormat} based on additional information in
+ * the track format (shown in the next paragraph), and send it to
+ * {@link MediaCodec#configure}.
+ *
+ * The track's MediaFormat will come with {@link #KEY_WIDTH} and
+ * {@link #KEY_HEIGHT} keys, which describes the width and height
+ * of the image. If the image doesn't contain grid (i.e. none of
+ * {@link #KEY_TILE_WIDTH}, {@link #KEY_TILE_HEIGHT},
+ * {@link #KEY_GRID_ROWS}, {@link #KEY_GRID_COLUMNS} are present), the
+ * track will contain a single sample of coded data for the entire image,
+ * and the image width and height should be used to set up the decoder.
+ *
+ * If the image does come with grid, each sample from the track will
+ * contain one tile in the grid, of which the size is described by
+ * {@link #KEY_TILE_WIDTH} and {@link #KEY_TILE_HEIGHT}. This size
+ * (instead of {@link #KEY_WIDTH} and {@link #KEY_HEIGHT}) should be
+ * used to set up the decoder. The track contains {@link #KEY_GRID_ROWS}
+ * by {@link #KEY_GRID_COLUMNS} samples in row-major, top-row first,
+ * left-to-right order. The output image should be reconstructed by
+ * first tiling the decoding results of the tiles in the correct order,
+ * then trimming (before rotation is applied) on the bottom and right
+ * side, if the tiled area is larger than the image width and height.
+ */
+ public static final String MIMETYPE_IMAGE_AVIF = "image/avif";
+
+ /**
* MIME type for WebVTT subtitle data.
*/
public static final String MIMETYPE_TEXT_VTT = "text/vtt";
@@ -485,9 +516,11 @@
/**
* A key describing the width (in pixels) of each tile of the content in a
- * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
+ * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track.
+ * The associated value is an integer.
*
- * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
+ * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} on decoding
+ * instructions of such tracks.
*
* @see #KEY_TILE_HEIGHT
* @see #KEY_GRID_ROWS
@@ -497,9 +530,11 @@
/**
* A key describing the height (in pixels) of each tile of the content in a
- * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
+ * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track.
+ * The associated value is an integer.
*
- * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
+ * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} on decoding
+ * instructions of such tracks.
*
* @see #KEY_TILE_WIDTH
* @see #KEY_GRID_ROWS
@@ -509,9 +544,11 @@
/**
* A key describing the number of grid rows in the content in a
- * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
+ * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track.
+ * The associated value is an integer.
*
- * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
+ * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} on decoding
+ * instructions of such tracks.
*
* @see #KEY_TILE_WIDTH
* @see #KEY_TILE_HEIGHT
@@ -521,9 +558,11 @@
/**
* A key describing the number of grid columns in the content in a
- * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track. The associated value is an integer.
+ * {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track.
+ * The associated value is an integer.
*
- * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} on decoding instructions of such tracks.
+ * Refer to {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} on decoding
+ * instructions of such tracks.
*
* @see #KEY_TILE_WIDTH
* @see #KEY_TILE_HEIGHT
@@ -1350,9 +1389,9 @@
* selected in the absence of a specific user choice.
* This is currently used in two scenarios:
* 1) for subtitle tracks, when the user selected 'Default' for the captioning locale.
- * 2) for a {@link #MIMETYPE_IMAGE_ANDROID_HEIC} track, indicating the image is the
- * primary item in the file.
-
+ * 2) for a {@link #MIMETYPE_IMAGE_ANDROID_HEIC} / {@link #MIMETYPE_IMAGE_AVIF} track,
+ * indicating the image is the primary item in the file.
+ *
* The associated value is an integer, where non-0 means TRUE. This is an optional
* field; if not specified, DEFAULT is considered to be FALSE.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index f1e54e0..2cd564f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -149,32 +149,6 @@
}
}
}
-
- companion object {
- private const val SQUISHINESS_SCALE_START = 0.5
- private const val SQUISHINESS_SCALE_FACTOR = 0.5
- private fun getSquishinessScale(squishinessFraction: Float): Double {
- return SQUISHINESS_SCALE_START + SQUISHINESS_SCALE_FACTOR * squishinessFraction
- }
- }
-
- var squishinessFraction: Float = 1f
- set(value) {
- if (field == value) {
- return
- }
- field = value
-
- val scale = getSquishinessScale(field)
- for (mediaPlayer in MediaPlayerData.players()) {
- mediaPlayer.mediaViewHolder?.let {
- it.player.bottom = it.player.top + (scale * it.player.measuredHeight).toInt()
- } ?: mediaPlayer.recommendationViewHolder?.let {
- it.recommendations.bottom = it.recommendations.top +
- (scale * it.recommendations.measuredHeight).toInt()
- }
- }
- }
private val configListener = object : ConfigurationController.ConfigurationListener {
override fun onDensityOrFontScaleChanged() {
// System font changes should only happen when UMO is offscreen or a flicker may occur
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index f41b905..18bd6b7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -27,7 +27,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.media.MediaHostState;
@@ -76,14 +75,13 @@
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QS_PANEL) MediaHost mediaHost,
QSTileRevealController.Factory qsTileRevealControllerFactory,
- DumpManager dumpManager, MediaCarouselController mediaCarouselController,
- MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
+ DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
BrightnessSliderController.Factory brightnessSliderFactory,
FalsingManager falsingManager,
StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
- metricsLogger, uiEventLogger, qsLogger, dumpManager, mediaCarouselController);
+ metricsLogger, uiEventLogger, qsLogger, dumpManager);
mTunerService = tunerService;
mQsCustomizerController = qsCustomizerController;
mQsTileRevealControllerFactory = qsTileRevealControllerFactory;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index a5c60a4..ded466a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -32,7 +32,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Dumpable;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
@@ -71,7 +70,6 @@
private final UiEventLogger mUiEventLogger;
private final QSLogger mQSLogger;
private final DumpManager mDumpManager;
- private final MediaCarouselController mMediaCarouselController;
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
protected boolean mShouldUseSplitNotificationShade;
@@ -133,8 +131,7 @@
MetricsLogger metricsLogger,
UiEventLogger uiEventLogger,
QSLogger qsLogger,
- DumpManager dumpManager,
- MediaCarouselController mediaCarouselController
+ DumpManager dumpManager
) {
super(view);
mHost = host;
@@ -147,7 +144,6 @@
mDumpManager = dumpManager;
mShouldUseSplitNotificationShade =
LargeScreenUtils.shouldUseSplitNotificationShade(getResources());
- mMediaCarouselController = mediaCarouselController;
}
@Override
@@ -165,7 +161,6 @@
public void setSquishinessFraction(float squishinessFraction) {
mView.setSquishinessFraction(squishinessFraction);
- mMediaCarouselController.setSquishinessFraction(squishinessFraction);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 7ce0ad0..9739974 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -26,7 +26,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
@@ -56,10 +55,10 @@
@Named(QS_USING_COLLAPSED_LANDSCAPE_MEDIA)
Provider<Boolean> usingCollapsedLandscapeMediaProvider,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
- DumpManager dumpManager, MediaCarouselController mediaCarouselController
+ DumpManager dumpManager
) {
super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
- uiEventLogger, qsLogger, dumpManager, mediaCarouselController);
+ uiEventLogger, qsLogger, dumpManager);
mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
index e3e3b74..5ad3542 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
@@ -30,7 +30,6 @@
import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.util.animation.TransitionLayout
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
@@ -46,7 +45,6 @@
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@@ -73,10 +71,6 @@
@Mock lateinit var dumpManager: DumpManager
@Mock lateinit var logger: MediaUiEventLogger
@Mock lateinit var debugLogger: MediaCarouselControllerLogger
- @Mock lateinit var mediaViewHolder: MediaViewHolder
- @Mock lateinit var player: TransitionLayout
- @Mock lateinit var recommendationViewHolder: RecommendationViewHolder
- @Mock lateinit var recommendations: TransitionLayout
@Mock lateinit var mediaPlayer: MediaControlPanel
@Mock lateinit var mediaViewController: MediaViewController
@Mock lateinit var smartspaceMediaData: SmartspaceMediaData
@@ -282,46 +276,6 @@
verify(logger).logRecommendationRemoved(eq(packageName), eq(instanceId!!))
}
- @Test
- fun testSetSquishinessFractionForMedia_setPlayerBottom() {
- whenever(panel.mediaViewHolder).thenReturn(mediaViewHolder)
- whenever(mediaViewHolder.player).thenReturn(player)
- whenever(player.measuredHeight).thenReturn(100)
-
- val playingLocal = Triple("playing local",
- DATA.copy(active = true, isPlaying = true,
- playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false),
- 4500L)
- MediaPlayerData.addMediaPlayer(playingLocal.first, playingLocal.second, panel, clock,
- false, debugLogger)
-
- mediaCarouselController.squishinessFraction = 0.0f
- verify(player).bottom = 50
- verifyNoMoreInteractions(recommendationViewHolder)
-
- mediaCarouselController.squishinessFraction = 0.5f
- verify(player).bottom = 75
- verifyNoMoreInteractions(recommendationViewHolder)
- }
-
- @Test
- fun testSetSquishinessFractionForRecommendation_setPlayerBottom() {
- whenever(panel.recommendationViewHolder).thenReturn(recommendationViewHolder)
- whenever(recommendationViewHolder.recommendations).thenReturn(recommendations)
- whenever(recommendations.measuredHeight).thenReturn(100)
-
- MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, panel,
- false, clock)
-
- mediaCarouselController.squishinessFraction = 0.0f
- verifyNoMoreInteractions(mediaViewHolder)
- verify(recommendationViewHolder.recommendations).bottom = 50
-
- mediaCarouselController.squishinessFraction = 0.5f
- verifyNoMoreInteractions(mediaViewHolder)
- verify(recommendationViewHolder.recommendations).bottom = 75
- }
-
fun testMediaLoaded_ScrollToActivePlayer() {
listener.value.onMediaDataLoaded("playing local",
null,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index cbe1186..3cad2a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -44,7 +44,6 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
@@ -87,7 +86,6 @@
@Mock
private QSLogger mQSLogger;
private DumpManager mDumpManager = new DumpManager();
- private MediaCarouselController mMediaCarouselController;
@Mock
QSTileImpl mQSTile;
@Mock
@@ -110,9 +108,9 @@
protected TestableQSPanelControllerBase(QSPanel view, QSTileHost host,
QSCustomizerController qsCustomizerController, MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
- DumpManager dumpManager, MediaCarouselController mediaCarouselController) {
+ DumpManager dumpManager) {
super(view, host, qsCustomizerController, true, mediaHost, metricsLogger, uiEventLogger,
- qsLogger, dumpManager, mediaCarouselController);
+ qsLogger, dumpManager);
}
@Override
@@ -146,7 +144,7 @@
mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
mQSCustomizerController, mMediaHost,
- mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
+ mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
mController.init();
reset(mQSTileRevealController);
@@ -158,7 +156,7 @@
QSPanelControllerBase<QSPanel> controller = new TestableQSPanelControllerBase(mQSPanel,
mQSTileHost, mQSCustomizerController, mMediaHost,
- mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController) {
+ mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager) {
@Override
protected QSTileRevealController createTileRevealController() {
return mQSTileRevealController;
@@ -253,7 +251,7 @@
when(mQSPanel.getDumpableTag()).thenReturn("QSPanelLandscape");
mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
mQSCustomizerController, mMediaHost,
- mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
+ mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
mController.init();
assertThat(mController.shouldUseHorizontalLayout()).isTrue();
@@ -262,7 +260,7 @@
when(mQSPanel.getDumpableTag()).thenReturn("QSPanelPortrait");
mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
mQSCustomizerController, mMediaHost,
- mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager, mMediaCarouselController);
+ mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
mController.init();
assertThat(mController.shouldUseHorizontalLayout()).isFalse();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index 98d499a..5eb9a98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -6,7 +6,6 @@
import com.android.internal.logging.UiEventLogger
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.media.MediaCarouselController
import com.android.systemui.media.MediaHost
import com.android.systemui.media.MediaHostState
import com.android.systemui.plugins.FalsingManager
@@ -41,7 +40,6 @@
@Mock private lateinit var qsCustomizerController: QSCustomizerController
@Mock private lateinit var qsTileRevealControllerFactory: QSTileRevealController.Factory
@Mock private lateinit var dumpManager: DumpManager
- @Mock private lateinit var mediaCarouselController: MediaCarouselController
@Mock private lateinit var metricsLogger: MetricsLogger
@Mock private lateinit var uiEventLogger: UiEventLogger
@Mock private lateinit var qsLogger: QSLogger
@@ -78,7 +76,6 @@
mediaHost,
qsTileRevealControllerFactory,
dumpManager,
- mediaCarouselController,
metricsLogger,
uiEventLogger,
qsLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 4af5b90..6af8e49 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -23,7 +23,6 @@
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.media.MediaCarouselController
import com.android.systemui.media.MediaHost
import com.android.systemui.media.MediaHostState
import com.android.systemui.plugins.qs.QSTile
@@ -60,7 +59,6 @@
@Mock private lateinit var tileLayout: TileLayout
@Mock private lateinit var tileView: QSTileView
@Captor private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener>
- @Mock private lateinit var mediaCarouselController: MediaCarouselController
private val uiEventLogger = UiEventLoggerFake()
private val dumpManager = DumpManager()
@@ -90,8 +88,7 @@
metricsLogger,
uiEventLogger,
qsLogger,
- dumpManager,
- mediaCarouselController)
+ dumpManager)
controller.init()
}
@@ -158,8 +155,7 @@
metricsLogger: MetricsLogger,
uiEventLogger: UiEventLoggerFake,
qsLogger: QSLogger,
- dumpManager: DumpManager,
- mediaCarouselController: MediaCarouselController
+ dumpManager: DumpManager
) :
QuickQSPanelController(
view,
@@ -171,8 +167,7 @@
metricsLogger,
uiEventLogger,
qsLogger,
- dumpManager,
- mediaCarouselController) {
+ dumpManager) {
private var rotation = RotationUtils.ROTATION_NONE
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index c47ea9c..6ace404 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -275,10 +275,9 @@
EditText editText = view.findViewById(R.id.remote_input_text);
editText.setText(TEST_REPLY);
ClipDescription description = new ClipDescription("", new String[] {"image/png"});
- // We need to use an (arbitrary) real resource here so that an actual image gets attached.
+ // We need to use an (arbitrary) real resource here so that an actual image gets attached
ClipData clip = new ClipData(description, new ClipData.Item(
- Uri.parse("android.resource://com.android.systemui/"
- + R.drawable.default_thumbnail)));
+ Uri.parse("android.resource://android/" + android.R.drawable.btn_default)));
ContentInfo payload =
new ContentInfo.Builder(clip, SOURCE_CLIPBOARD).build();
view.setAttachment(payload);
diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java
index 7369e8f..4c15308 100644
--- a/services/core/java/com/android/server/am/ProcessProfileRecord.java
+++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java
@@ -17,7 +17,6 @@
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
-import static android.app.ActivityManager.processStateAmToProto;
import android.annotation.IntDef;
import android.app.IApplicationThread;
@@ -318,12 +317,6 @@
origBase.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), SystemClock.uptimeMillis(),
pkgList.getPackageListLocked());
- pkgList.forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- mApp.uid, mApp.processName, pkgName,
- processStateAmToProto(ProcessStats.STATE_NOTHING),
- holder.appVersion)
- );
}
origBase.makeInactive();
}
@@ -362,12 +355,6 @@
origBase.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), SystemClock.uptimeMillis(),
pkgList.getPackageListLocked());
- pkgList.forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- mApp.uid, mApp.processName, pkgName,
- processStateAmToProto(ProcessStats.STATE_NOTHING),
- holder.appVersion)
- );
}
origBase.makeInactive();
setBaseProcessTracker(null);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 07b6fcd..482e6a7 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -54,7 +54,6 @@
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.Zygote;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.server.wm.WindowProcessController;
import com.android.server.wm.WindowProcessListener;
@@ -1212,12 +1211,6 @@
long now = SystemClock.uptimeMillis();
baseProcessTracker.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), now, mPkgList.getPackageListLocked());
- mPkgList.forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- uid, processName, pkgName,
- ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING),
- holder.appVersion)
- );
if (numOfPkgs != 1) {
mPkgList.forEachPackageProcessStats(holder -> {
if (holder.state != null && holder.state != baseProcessTracker) {
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index ef13778..d2ef479 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -35,7 +35,6 @@
import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.server.am.PlatformCompatCache.CachedCompatChangeId;
import java.io.PrintWriter;
@@ -599,12 +598,6 @@
@GuardedBy({"mService", "mProcLock"})
void setReportedProcState(int repProcState) {
mRepProcState = repProcState;
- mApp.getPkgList().forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- mApp.uid, mApp.processName, pkgName,
- ActivityManager.processStateAmToProto(mRepProcState),
- holder.appVersion)
- );
mApp.getWindowProcessController().setReportedProcState(repProcState);
}
@@ -620,12 +613,6 @@
mRepProcState = newState;
setCurProcState(newState);
setCurRawProcState(newState);
- mApp.getPkgList().forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- mApp.uid, mApp.processName, pkgName,
- ActivityManager.processStateAmToProto(mRepProcState),
- holder.appVersion)
- );
}
}
}
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 2b8a196..cd074c0 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -385,6 +385,11 @@
} else if (snapshot.isInstantApp(options.getPackageName(), UserHandle.getCallingUserId())) {
return false;
}
+ var pkg = snapshot.getPackage(options.getPackageName());
+ if (pkg != null && pkg.isApex()) {
+ // skip APEX
+ return true;
+ }
if (options.isDexoptOnlySecondaryDex()) {
return mPm.getDexManager().dexoptSecondaryDex(options);
@@ -427,6 +432,10 @@
// Package could not be found. Report failure.
return PackageDexOptimizer.DEX_OPT_FAILED;
}
+ if (p.isApex()) {
+ // APEX needs no dexopt
+ return PackageDexOptimizer.DEX_OPT_SKIPPED;
+ }
mPm.getPackageUsage().maybeWriteAsync(mPm.mSettings.getPackagesLocked());
mPm.mCompilerStats.maybeWriteAsync();
}
@@ -498,6 +507,9 @@
if (packageState == null || pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
+ if (pkg.isApex()) {
+ throw new IllegalArgumentException("Can't dexopt APEX package: " + packageName);
+ }
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
diff --git a/services/core/java/com/android/server/pm/InstallSource.java b/services/core/java/com/android/server/pm/InstallSource.java
index 404285c..e5f7f71 100644
--- a/services/core/java/com/android/server/pm/InstallSource.java
+++ b/services/core/java/com/android/server/pm/InstallSource.java
@@ -131,7 +131,8 @@
@Nullable PackageSignatures initiatingPackageSignatures) {
if (initiatingPackageName == null && originatingPackageName == null
&& installerPackageName == null && initiatingPackageSignatures == null
- && !isInitiatingPackageUninstalled) {
+ && !isInitiatingPackageUninstalled
+ && packageSource == PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED) {
return isOrphaned ? EMPTY_ORPHANED : EMPTY;
}
return new InstallSource(initiatingPackageName, originatingPackageName,
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 3fb4066..178d0ea 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -189,6 +189,11 @@
return false;
}
+ // We do not dexopt APEX packages.
+ if (pkg.isApex()) {
+ return false;
+ }
+
// We do not dexopt unused packages.
// It's possible for this to be called before app hibernation service is ready due to
// an OTA dexopt. In this case, we ignore the hibernation check here. This is fine since
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d8d75ed..9ed77fc 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1354,10 +1354,6 @@
return true;
}
- void setAppTimeTracker(AppTimeTracker att) {
- appTimeTracker = att;
- }
-
/** Update the saved state of an activity. */
void setSavedState(@Nullable Bundle savedState) {
mIcicle = savedState;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 5bddae6..b473700 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -139,7 +139,6 @@
import com.android.internal.content.ReferrerIntent;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.am.ActivityManagerService;
@@ -1578,17 +1577,12 @@
if (rootTask.getWindowingMode() == WINDOWING_MODE_PINNED) {
removePinnedRootTaskInSurfaceTransaction(rootTask);
} else {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- ActivityTaskSupervisor::processRemoveTask, this, PooledLambda.__(Task.class));
- rootTask.forAllLeafTasks(c, true /* traverseTopToBottom */);
- c.recycle();
+ rootTask.forAllLeafTasks(task -> {
+ removeTask(task, true /* killProcess */, REMOVE_FROM_RECENTS, "remove-root-task");
+ }, true /* traverseTopToBottom */);
}
}
- private void processRemoveTask(Task task) {
- removeTask(task, true /* killProcess */, REMOVE_FROM_RECENTS, "remove-root-task");
- }
-
/**
* Removes the root task associated with the given {@param task}. If the {@param task} is the
* pinned task, then its child tasks are not explicitly removed when the root task is
@@ -2268,23 +2262,17 @@
}
void scheduleUpdateMultiWindowMode(Task task) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- ActivityTaskSupervisor::addToMultiWindowModeChangedList, this,
- PooledLambda.__(ActivityRecord.class));
- task.forAllActivities(c);
- c.recycle();
+ task.forAllActivities(r -> {
+ if (r.attachedToProcess()) {
+ mMultiWindowModeChangedActivities.add(r);
+ }
+ });
if (!mHandler.hasMessages(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG)) {
mHandler.sendEmptyMessage(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG);
}
}
- private void addToMultiWindowModeChangedList(ActivityRecord r) {
- if (r.attachedToProcess()) {
- mMultiWindowModeChangedActivities.add(r);
- }
- }
-
void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Task prevRootTask) {
final Task rootTask = task.getRootTask();
if ((prevRootTask == null || (prevRootTask != rootTask
@@ -2296,11 +2284,14 @@
}
void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Rect targetRootTaskBounds) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- ActivityTaskSupervisor::addToPipModeChangedList, this,
- PooledLambda.__(ActivityRecord.class));
- task.forAllActivities(c);
- c.recycle();
+ task.forAllActivities(r -> {
+ if (!r.attachedToProcess()) return;
+ mPipModeChangedActivities.add(r);
+ // If we are scheduling pip change, then remove this activity from multi-window
+ // change list as the processing of pip change will make sure multi-window changed
+ // message is processed in the right order relative to pip changed.
+ mMultiWindowModeChangedActivities.remove(r);
+ });
mPipModeChangedTargetRootTaskBounds = targetRootTaskBounds;
@@ -2309,16 +2300,6 @@
}
}
- private void addToPipModeChangedList(ActivityRecord r) {
- if (!r.attachedToProcess()) return;
-
- mPipModeChangedActivities.add(r);
- // If we are scheduling pip change, then remove this activity from multi-window
- // change list as the processing of pip change will make sure multi-window changed
- // message is processed in the right order relative to pip changed.
- mMultiWindowModeChangedActivities.remove(r);
- }
-
void wakeUp(String reason) {
mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_APPLICATION,
"android.server.am:TURN_ON:" + reason);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c6fe017..669cd5d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -241,7 +241,6 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.function.TriConsumer;
-import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -3075,18 +3074,13 @@
*/
boolean pointWithinAppWindow(int x, int y) {
final int[] targetWindowType = {-1};
- final PooledConsumer fn = PooledLambda.obtainConsumer((w, nonArg) -> {
- if (targetWindowType[0] != -1) {
- return;
- }
-
+ forAllWindows(w -> {
if (w.isOnScreen() && w.isVisible() && w.getFrame().contains(x, y)) {
targetWindowType[0] = w.mAttrs.type;
- return;
+ return true;
}
- }, PooledLambda.__(WindowState.class), mTmpRect);
- forAllWindows(fn, true /* traverseTopToBottom */);
- fn.recycle();
+ return false;
+ }, true /* traverseTopToBottom */);
return FIRST_APPLICATION_WINDOW <= targetWindowType[0]
&& targetWindowType[0] <= LAST_APPLICATION_WINDOW;
}
@@ -3112,11 +3106,7 @@
mTmpRect.setEmpty();
mTmpRect2.setEmpty();
- final PooledConsumer c = PooledLambda.obtainConsumer(
- DisplayContent::processTaskForTouchExcludeRegion, this,
- PooledLambda.__(Task.class), focusedTask, delta);
- forAllTasks(c);
- c.recycle();
+ forAllTasks(t -> { processTaskForTouchExcludeRegion(t, focusedTask, delta); });
// If we removed the focused task above, add it back and only leave its
// outside touch area in the exclusion. TapDetector is not interested in
@@ -6187,17 +6177,10 @@
/** Update and get all UIDs that are present on the display and have access to it. */
IntArray getPresentUIDs() {
mDisplayAccessUIDs.clear();
- final PooledConsumer c = PooledLambda.obtainConsumer(DisplayContent::addActivityUid,
- PooledLambda.__(ActivityRecord.class), mDisplayAccessUIDs);
- mDisplayContent.forAllActivities(c);
- c.recycle();
+ mDisplayContent.forAllActivities(r -> { mDisplayAccessUIDs.add(r.getUid()); });
return mDisplayAccessUIDs;
}
- private static void addActivityUid(ActivityRecord r, IntArray uids) {
- uids.add(r.getUid());
- }
-
@VisibleForTesting
boolean shouldDestroyContentOnRemove() {
return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 9e01f10..bffab7a 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -62,8 +62,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -403,11 +401,11 @@
final Task targetRootTask = mDisplayContent.getDefaultTaskDisplayArea()
.getRootTask(WINDOWING_MODE_UNDEFINED, targetActivityType);
if (targetRootTask != null) {
- final PooledConsumer c = PooledLambda.obtainConsumer((t, outList) ->
- { if (!outList.contains(t)) outList.add(t); }, PooledLambda.__(Task.class),
- visibleTasks);
- targetRootTask.forAllLeafTasks(c, true /* traverseTopToBottom */);
- c.recycle();
+ targetRootTask.forAllLeafTasks(t -> {
+ if (!visibleTasks.contains(t)) {
+ visibleTasks.add(t);
+ }
+ }, true /* traverseTopToBottom */);
}
final int taskCount = visibleTasks.size();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index ba834de..b2ec3f3 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3102,9 +3102,8 @@
}
void finishVoiceTask(IVoiceInteractionSession session) {
- forAllRootTasks(rootTask -> {
- rootTask.finishVoiceTask(session);
- });
+ final IBinder binder = session.asBinder();
+ forAllLeafTasks(t -> t.finishIfVoiceTask(binder), true /* traverseTopToBottom */);
}
/**
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 120fec0..a753b55 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -23,18 +23,16 @@
import android.os.UserHandle;
import android.util.ArraySet;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
-
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
+import java.util.function.Consumer;
/**
* Class for resolving the set of running tasks in the system.
*/
-class RunningTasks {
+class RunningTasks implements Consumer<Task> {
static final int FLAG_FILTER_ONLY_VISIBLE_RECENTS = 1;
static final int FLAG_ALLOWED = 1 << 1;
@@ -61,7 +59,7 @@
private boolean mKeepIntentExtra;
void getTasks(int maxNum, List<RunningTaskInfo> list, int flags, RecentTasks recentTasks,
- WindowContainer root, int callingUid, ArraySet<Integer> profileIds) {
+ WindowContainer<?> root, int callingUid, ArraySet<Integer> profileIds) {
// Return early if there are no tasks to fetch
if (maxNum <= 0) {
return;
@@ -79,10 +77,7 @@
mRecentTasks = recentTasks;
mKeepIntentExtra = (flags & FLAG_KEEP_INTENT_EXTRA) == FLAG_KEEP_INTENT_EXTRA;
- final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
- PooledLambda.__(Task.class));
- root.forAllLeafTasks(c, false);
- c.recycle();
+ root.forAllLeafTasks(this, false /* traverseTopToBottom */);
// Take the first {@param maxNum} tasks and create running task infos for them
final Iterator<Task> iter = mTmpSortedSet.iterator();
@@ -97,7 +92,8 @@
}
}
- private void processTask(Task task) {
+ @Override
+ public void accept(Task task) {
if (task.getTopNonFinishingActivity() == null) {
// Skip if there are no activities in the task
return;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1508870..63c6c35 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -196,7 +196,6 @@
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.XmlUtils;
-import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.Watchdog;
@@ -1188,11 +1187,7 @@
if (oldParent != null) {
final Task oldParentTask = oldParent.asTask();
if (oldParentTask != null) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- Task::cleanUpActivityReferences, oldParentTask,
- PooledLambda.__(ActivityRecord.class));
- forAllActivities(c);
- c.recycle();
+ forAllActivities(oldParentTask::cleanUpActivityReferences);
}
if (oldParent.inPinnedWindowingMode()
@@ -2371,10 +2366,7 @@
int getDescendantTaskCount() {
final int[] currentCount = {0};
- final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
- PooledLambda.__(Task.class), currentCount);
- forAllLeafTasks(c, false /* traverseTopToBottom */);
- c.recycle();
+ forAllLeafTasks(t -> currentCount[0]++, false /* traverseTopToBottom */);
return currentCount[0];
}
@@ -2783,10 +2775,7 @@
&& displayContent.mDividerControllerLocked.isResizing();
if (inFreeformWindowingMode()) {
boolean[] foundTop = { false };
- final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
- PooledLambda.__(ActivityRecord.class), out, foundTop);
- forAllActivities(c);
- c.recycle();
+ forAllActivities(a -> { getMaxVisibleBounds(a, out, foundTop); });
if (foundTop[0]) {
return;
}
@@ -4349,14 +4338,6 @@
}
}
-
- void setActivityWindowingMode(int windowingMode) {
- PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode,
- PooledLambda.__(ActivityRecord.class), windowingMode);
- forAllActivities(c);
- c.recycle();
- }
-
/**
* Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
* @return Whether the force hidden state changed
@@ -5209,26 +5190,19 @@
return finishedTask;
}
- void finishVoiceTask(IVoiceInteractionSession session) {
- final PooledConsumer c = PooledLambda.obtainConsumer(Task::finishIfVoiceTask,
- PooledLambda.__(Task.class), session.asBinder());
- forAllLeafTasks(c, true /* traverseTopToBottom */);
- c.recycle();
- }
-
- private static void finishIfVoiceTask(Task tr, IBinder binder) {
- if (tr.voiceSession != null && tr.voiceSession.asBinder() == binder) {
- tr.forAllActivities((r) -> {
+ void finishIfVoiceTask(IBinder binder) {
+ if (voiceSession != null && voiceSession.asBinder() == binder) {
+ forAllActivities((r) -> {
if (r.finishing) return;
r.finishIfPossible("finish-voice", false /* oomAdj */);
- tr.mAtmService.updateOomAdj();
+ mAtmService.updateOomAdj();
});
} else {
// Check if any of the activities are using voice
final PooledPredicate f = PooledLambda.obtainPredicate(
Task::finishIfVoiceActivity, PooledLambda.__(ActivityRecord.class),
binder);
- tr.forAllActivities(f);
+ forAllActivities(f);
f.recycle();
}
}
@@ -5447,10 +5421,7 @@
if (timeTracker != null) {
// The caller wants a time tracker associated with this task.
- final PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setAppTimeTracker,
- PooledLambda.__(ActivityRecord.class), timeTracker);
- tr.forAllActivities(c);
- c.recycle();
+ tr.forAllActivities(a -> { a.appTimeTracker = timeTracker; });
}
try {
@@ -5621,11 +5592,11 @@
try {
// TODO: Why not just set this on the root task directly vs. on each tasks?
// Update override configurations of all tasks in the root task.
- final PooledConsumer c = PooledLambda.obtainConsumer(
- Task::processTaskResizeBounds, PooledLambda.__(Task.class),
- displayedBounds);
- forAllTasks(c, true /* traverseTopToBottom */);
- c.recycle();
+ forAllTasks(task -> {
+ if (task.isResizeable()) {
+ task.setBounds(displayedBounds);
+ }
+ }, true /* traverseTopToBottom */);
if (!deferResume) {
ensureVisibleActivitiesConfiguration(topRunningActivity(), preserveWindows);
@@ -5636,12 +5607,6 @@
}
}
- private static void processTaskResizeBounds(Task task, Rect displayedBounds) {
- if (!task.isResizeable()) return;
-
- task.setBounds(displayedBounds);
- }
-
boolean willActivityBeVisible(IBinder token) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r == null) {
@@ -5727,22 +5692,15 @@
// All activities that came from the package must be
// restarted as if there was a config change.
- PooledConsumer c = PooledLambda.obtainConsumer(Task::restartPackage,
- PooledLambda.__(ActivityRecord.class), starting, packageName);
- forAllActivities(c);
- c.recycle();
-
- return starting;
- }
-
- private static void restartPackage(
- ActivityRecord r, ActivityRecord starting, String packageName) {
- if (r.info.packageName.equals(packageName)) {
+ forAllActivities(r -> {
+ if (!r.info.packageName.equals(packageName)) return;
r.forceNewConfig = true;
if (starting != null && r == starting && r.mVisibleRequested) {
r.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
}
- }
+ });
+
+ return starting;
}
Task reuseOrCreateTask(ActivityInfo info, Intent intent, boolean toTop) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 90e3c51..29ab562 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -309,8 +309,6 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.LatencyTracker;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.view.WindowManagerPolicyThread;
import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
@@ -475,10 +473,7 @@
public void onVrStateChanged(boolean enabled) {
synchronized (mGlobalLock) {
mVrModeEnabled = enabled;
- final PooledConsumer c = PooledLambda.obtainConsumer(
- DisplayPolicy::onVrStateChangedLw, PooledLambda.__(), enabled);
- mRoot.forAllDisplayPolicies(c);
- c.recycle();
+ mRoot.forAllDisplayPolicies(p -> p.onVrStateChangedLw(enabled));
}
}
};
@@ -900,11 +895,8 @@
}
mPointerLocationEnabled = enablePointerLocation;
synchronized (mGlobalLock) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- DisplayPolicy::setPointerLocationEnabled, PooledLambda.__(),
- mPointerLocationEnabled);
- mRoot.forAllDisplayPolicies(c);
- c.recycle();
+ mRoot.forAllDisplayPolicies(
+ p -> p.setPointerLocationEnabled(mPointerLocationEnabled));
}
}
@@ -3139,10 +3131,7 @@
@Override
public void onPowerKeyDown(boolean isScreenOn) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- DisplayPolicy::onPowerKeyDown, PooledLambda.__(), isScreenOn);
- mRoot.forAllDisplayPolicies(c);
- c.recycle();
+ mRoot.forAllDisplayPolicies(p -> p.onPowerKeyDown(isScreenOn));
}
@Override
@@ -8391,10 +8380,7 @@
void onLockTaskStateChanged(int lockTaskState) {
// TODO: pass in displayId to determine which display the lock task state changed
synchronized (mGlobalLock) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- DisplayPolicy::onLockTaskStateChangedLw, PooledLambda.__(), lockTaskState);
- mRoot.forAllDisplayPolicies(c);
- c.recycle();
+ mRoot.forAllDisplayPolicies(p -> p.onLockTaskStateChangedLw(lockTaskState));
}
}
@@ -9286,4 +9272,46 @@
"Unexpected letterbox background type: " + letterboxBackgroundType);
}
}
+
+ @Override
+ public void captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs,
+ ScreenCapture.ScreenCaptureListener listener) {
+ Slog.d(TAG, "captureDisplay");
+ if (!checkCallingPermission(READ_FRAME_BUFFER, "captureDisplay()")) {
+ throw new SecurityException("Requires READ_FRAME_BUFFER permission");
+ }
+
+ ScreenCapture.captureLayers(getCaptureArgs(displayId, captureArgs), listener);
+ }
+
+ @VisibleForTesting
+ ScreenCapture.LayerCaptureArgs getCaptureArgs(int displayId,
+ @Nullable ScreenCapture.CaptureArgs captureArgs) {
+ final SurfaceControl displaySurfaceControl;
+ synchronized (mGlobalLock) {
+ DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ if (displayContent == null) {
+ throw new IllegalArgumentException("Trying to screenshot and invalid display: "
+ + displayId);
+ }
+
+ displaySurfaceControl = displayContent.getSurfaceControl();
+
+ if (captureArgs == null) {
+ captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
+ .build();
+ }
+
+ if (captureArgs.mSourceCrop.isEmpty()) {
+ displayContent.getBounds(mTmpRect);
+ mTmpRect.offsetTo(0, 0);
+ } else {
+ mTmpRect.set(captureArgs.mSourceCrop);
+ }
+ }
+
+ return new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl, captureArgs)
+ .setSourceCrop(mTmpRect)
+ .build();
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 2e1477d..e2f833c 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -91,8 +91,6 @@
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.pm.LauncherAppsService.LauncherAppsServiceInternal;
@@ -482,7 +480,7 @@
}
final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
final int hopSize = hops.size();
- ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
+ final ArraySet<WindowContainer<?>> haveConfigChanges = new ArraySet<>();
Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
t.getChanges().entrySet().iterator();
while (entries.hasNext()) {
@@ -592,16 +590,10 @@
mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
} else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
- final PooledConsumer f = PooledLambda.obtainConsumer(
- ActivityRecord::ensureActivityConfiguration,
- PooledLambda.__(ActivityRecord.class), 0,
- true /* preserveWindow */);
- try {
- for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
- haveConfigChanges.valueAt(i).forAllActivities(f);
- }
- } finally {
- f.recycle();
+ for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
+ haveConfigChanges.valueAt(i).forAllActivities(r -> {
+ r.ensureActivityConfiguration(0, PRESERVE_WINDOWS);
+ });
}
}
@@ -716,7 +708,7 @@
final int childWindowingMode = c.getActivityWindowingMode();
if (childWindowingMode > -1) {
- tr.setActivityWindowingMode(childWindowingMode);
+ tr.forAllActivities(a -> { a.setWindowingMode(childWindowingMode); });
}
if (t != null) {
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index 2918365..107bbe1 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -79,7 +79,10 @@
<activity android:name="com.android.server.wm.ActivityOptionsTest$MainActivity"
android:turnScreenOn="true"
android:showWhenLocked="true" />
- <activity android:name="com.android.server.wm.ScreenshotTests$ScreenshotActivity" />
+ <activity android:name="com.android.server.wm.ScreenshotTests$ScreenshotActivity"
+ android:theme="@style/WhiteBackgroundTheme"
+ android:turnScreenOn="true"
+ android:showWhenLocked="true"/>
<activity android:name="android.view.cts.surfacevalidator.CapturedActivity"/>
<service android:name="android.view.cts.surfacevalidator.LocalMediaProjectionService"
diff --git a/services/tests/wmtests/res/values/styles.xml b/services/tests/wmtests/res/values/styles.xml
new file mode 100644
index 0000000..6857ff99
--- /dev/null
+++ b/services/tests/wmtests/res/values/styles.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <style name="WhiteBackgroundTheme" parent="@android:style/Theme.DeviceDefault">
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowFullscreen">true</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
+ </style>
+</resources>
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index adf694c..170b388 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1532,7 +1532,7 @@
@Override
void getTasks(int maxNum, List<RunningTaskInfo> list, int flags, RecentTasks recentTasks,
- WindowContainer root, int callingUid, ArraySet<Integer> profileIds) {
+ WindowContainer<?> root, int callingUid, ArraySet<Integer> profileIds) {
mLastAllowed = (flags & FLAG_ALLOWED) == FLAG_ALLOWED;
super.getTasks(maxNum, list, flags, recentTasks, root, callingUid, profileIds);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
index 0b58428..736f8f7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
@@ -16,6 +16,10 @@
package com.android.server.wm;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.statusBars;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertNotNull;
@@ -23,20 +27,33 @@
import android.app.Activity;
import android.app.Instrumentation;
+import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
+import android.graphics.Insets;
import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.DataSpace;
+import android.hardware.HardwareBuffer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.ServiceManager;
import android.platform.test.annotations.Presubmit;
+import android.util.Pair;
+import android.view.IWindowManager;
import android.view.PointerIcon;
import android.view.SurfaceControl;
-import android.view.WindowManager;
+import android.view.cts.surfacevalidator.BitmapPixelChecker;
+import android.view.cts.surfacevalidator.PixelColor;
+import android.view.cts.surfacevalidator.SaveBitmapHelper;
import android.window.ScreenCapture;
+import android.window.ScreenCapture.ScreenCaptureListener;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
+import android.window.ScreenCapture.ScreenshotSync;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
@@ -45,6 +62,7 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestName;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -60,6 +78,8 @@
private static final int BUFFER_HEIGHT = 100;
private final Instrumentation mInstrumentation = getInstrumentation();
+ @Rule
+ public TestName mTestName = new TestName();
@Rule
public ActivityTestRule<ScreenshotActivity> mActivityRule =
@@ -95,8 +115,8 @@
buffer.unlockCanvasAndPost(canvas);
t.show(secureSC)
- .setBuffer(secureSC, buffer)
- .setColorSpace(secureSC, ColorSpace.get(ColorSpace.Named.SRGB))
+ .setBuffer(secureSC, HardwareBuffer.createFromGraphicBuffer(buffer))
+ .setDataSpace(secureSC, DataSpace.DATASPACE_SRGB)
.apply(true);
ScreenCapture.LayerCaptureArgs args = new ScreenCapture.LayerCaptureArgs.Builder(secureSC)
@@ -112,15 +132,70 @@
Bitmap swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false);
screenshot.recycle();
- int numMatchingPixels = PixelChecker.getNumMatchingPixels(swBitmap,
- new PixelColor(PixelColor.RED));
- long sizeOfBitmap = swBitmap.getWidth() * swBitmap.getHeight();
+ BitmapPixelChecker bitmapPixelChecker = new BitmapPixelChecker(PixelColor.RED);
+ Rect bounds = new Rect(0, 0, swBitmap.getWidth(), swBitmap.getHeight());
+ int numMatchingPixels = bitmapPixelChecker.getNumMatchingPixels(swBitmap, bounds);
+ int sizeOfBitmap = bounds.width() * bounds.height();
boolean success = numMatchingPixels == sizeOfBitmap;
swBitmap.recycle();
assertTrue(success);
}
+ @Test
+ public void testCaptureDisplay() throws Exception {
+ IWindowManager windowManager = IWindowManager.Stub.asInterface(
+ ServiceManager.getService(Context.WINDOW_SERVICE));
+ SurfaceControl sc = new SurfaceControl.Builder()
+ .setName("Layer")
+ .setCallsite("testCaptureDisplay")
+ .build();
+
+ SurfaceControl.Transaction t = mActivity.addChildSc(sc);
+ mInstrumentation.waitForIdleSync();
+
+ GraphicBuffer buffer = GraphicBuffer.create(BUFFER_WIDTH, BUFFER_HEIGHT,
+ PixelFormat.RGBA_8888,
+ GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
+ | GraphicBuffer.USAGE_SW_WRITE_RARELY);
+
+ Canvas canvas = buffer.lockCanvas();
+ canvas.drawColor(Color.RED);
+ buffer.unlockCanvasAndPost(canvas);
+
+ Point point = mActivity.getPositionBelowStatusBar();
+ t.show(sc)
+ .setBuffer(sc, HardwareBuffer.createFromGraphicBuffer(buffer))
+ .setDataSpace(sc, DataSpace.DATASPACE_SRGB)
+ .setPosition(sc, point.x, point.y)
+ .apply(true);
+
+ Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture =
+ ScreenCapture.createSyncCaptureListener();
+ windowManager.captureDisplay(DEFAULT_DISPLAY, null, syncScreenCapture.first);
+ ScreenshotHardwareBuffer hardwareBuffer = syncScreenCapture.second.get();
+ assertNotNull(hardwareBuffer);
+
+ Bitmap screenshot = hardwareBuffer.asBitmap();
+ assertNotNull(screenshot);
+
+ Bitmap swBitmap = screenshot.copy(Bitmap.Config.ARGB_8888, false);
+ screenshot.recycle();
+
+ BitmapPixelChecker bitmapPixelChecker = new BitmapPixelChecker(PixelColor.RED);
+ Rect bounds = new Rect(point.x, point.y, BUFFER_WIDTH + point.x, BUFFER_HEIGHT + point.y);
+ int numMatchingPixels = bitmapPixelChecker.getNumMatchingPixels(swBitmap, bounds);
+ int pixelMatchSize = bounds.width() * bounds.height();
+ boolean success = numMatchingPixels == pixelMatchSize;
+
+ if (!success) {
+ SaveBitmapHelper.saveBitmap(swBitmap, getClass(), mTestName, "failedImage");
+ }
+ swBitmap.recycle();
+ assertTrue("numMatchingPixels=" + numMatchingPixels + " pixelMatchSize=" + pixelMatchSize,
+ success);
+ }
+
public static class ScreenshotActivity extends Activity {
private static final long WAIT_TIMEOUT_S = 5;
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -130,7 +205,6 @@
super.onCreate(savedInstanceState);
getWindow().getDecorView().setPointerIcon(
PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL));
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
SurfaceControl.Transaction addChildSc(SurfaceControl surfaceControl) {
@@ -148,88 +222,14 @@
}
return t;
}
- }
- public abstract static class PixelChecker {
- static int getNumMatchingPixels(Bitmap bitmap, PixelColor pixelColor) {
- int numMatchingPixels = 0;
- for (int x = 0; x < bitmap.getWidth(); x++) {
- for (int y = 0; y < bitmap.getHeight(); y++) {
- int color = bitmap.getPixel(x, y);
- if (matchesColor(pixelColor, color)) {
- numMatchingPixels++;
- }
- }
- }
- return numMatchingPixels;
- }
+ public Point getPositionBelowStatusBar() {
+ Insets statusBarInsets = getWindow()
+ .getDecorView()
+ .getRootWindowInsets()
+ .getInsets(statusBars() | displayCutout());
- static boolean matchesColor(PixelColor expectedColor, int color) {
- final float red = Color.red(color);
- final float green = Color.green(color);
- final float blue = Color.blue(color);
- final float alpha = Color.alpha(color);
-
- return alpha <= expectedColor.mMaxAlpha
- && alpha >= expectedColor.mMinAlpha
- && red <= expectedColor.mMaxRed
- && red >= expectedColor.mMinRed
- && green <= expectedColor.mMaxGreen
- && green >= expectedColor.mMinGreen
- && blue <= expectedColor.mMaxBlue
- && blue >= expectedColor.mMinBlue;
- }
- }
-
- public static class PixelColor {
- public static final int BLACK = 0xFF000000;
- public static final int RED = 0xFF0000FF;
- public static final int GREEN = 0xFF00FF00;
- public static final int BLUE = 0xFFFF0000;
- public static final int YELLOW = 0xFF00FFFF;
- public static final int MAGENTA = 0xFFFF00FF;
- public static final int WHITE = 0xFFFFFFFF;
-
- public static final int TRANSPARENT_RED = 0x7F0000FF;
- public static final int TRANSPARENT_BLUE = 0x7FFF0000;
- public static final int TRANSPARENT = 0x00000000;
-
- // Default to black
- public short mMinAlpha;
- public short mMaxAlpha;
- public short mMinRed;
- public short mMaxRed;
- public short mMinBlue;
- public short mMaxBlue;
- public short mMinGreen;
- public short mMaxGreen;
-
- public PixelColor(int color) {
- short alpha = (short) ((color >> 24) & 0xFF);
- short blue = (short) ((color >> 16) & 0xFF);
- short green = (short) ((color >> 8) & 0xFF);
- short red = (short) (color & 0xFF);
-
- mMinAlpha = (short) getMinValue(alpha);
- mMaxAlpha = (short) getMaxValue(alpha);
- mMinRed = (short) getMinValue(red);
- mMaxRed = (short) getMaxValue(red);
- mMinBlue = (short) getMinValue(blue);
- mMaxBlue = (short) getMaxValue(blue);
- mMinGreen = (short) getMinValue(green);
- mMaxGreen = (short) getMaxValue(green);
- }
-
- public PixelColor() {
- this(BLACK);
- }
-
- private int getMinValue(short color) {
- return Math.max(color - 4, 0);
- }
-
- private int getMaxValue(short color) {
- return Math.min(color + 4, 0xFF);
+ return new Point(statusBarInsets.left, statusBarInsets.top);
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 46b4b76..8b63904 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -41,6 +41,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
@@ -68,6 +69,7 @@
import android.view.View;
import android.view.WindowManager;
import android.window.ClientWindowFrames;
+import android.window.ScreenCapture;
import android.window.WindowContainerToken;
import androidx.test.filters.SmallTest;
@@ -423,6 +425,45 @@
LETTERBOX_BACKGROUND_SOLID_COLOR)).isFalse();
}
+ @Test
+ public void testCaptureDisplay() {
+ Rect displayBounds = new Rect(0, 0, 100, 200);
+ spyOn(mDisplayContent);
+ when(mDisplayContent.getBounds()).thenReturn(displayBounds);
+
+ // Null captureArgs
+ ScreenCapture.LayerCaptureArgs resultingArgs =
+ mWm.getCaptureArgs(DEFAULT_DISPLAY, null /* captureArgs */);
+ assertEquals(displayBounds, resultingArgs.mSourceCrop);
+
+ // Non null captureArgs, didn't set rect
+ ScreenCapture.CaptureArgs captureArgs = new ScreenCapture.CaptureArgs.Builder<>().build();
+ resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs);
+ assertEquals(displayBounds, resultingArgs.mSourceCrop);
+
+ // Non null captureArgs, invalid rect
+ captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
+ .setSourceCrop(new Rect(0, 0, -1, -1))
+ .build();
+ resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs);
+ assertEquals(displayBounds, resultingArgs.mSourceCrop);
+
+ // Non null captureArgs, null rect
+ captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
+ .setSourceCrop(null)
+ .build();
+ resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs);
+ assertEquals(displayBounds, resultingArgs.mSourceCrop);
+
+ // Non null captureArgs, valid rect
+ Rect validRect = new Rect(0, 0, 10, 50);
+ captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
+ .setSourceCrop(validRect)
+ .build();
+ resultingArgs = mWm.getCaptureArgs(DEFAULT_DISPLAY, captureArgs);
+ assertEquals(validRect, resultingArgs.mSourceCrop);
+ }
+
private void setupActivityWithLaunchCookie(IBinder launchCookie, WindowContainerToken wct) {
final WindowContainer.RemoteToken remoteToken = mock(WindowContainer.RemoteToken.class);
when(remoteToken.toWindowContainerToken()).thenReturn(wct);