summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChiawei Wang <chiaweiwang@google.com>2019-11-14 03:21:39 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-11-14 03:21:39 +0000
commit532431d1b2863b1650892ab4d99a4d736ef71830 (patch)
tree8b93722737159e616e763cea15996c4224f98039
parent11f3c8ac97621f46db1f4f10592ba309757602e2 (diff)
parent02202d109f2b5499b9dc8cd7c112c2b40aea9d50 (diff)
Merge "Add ability to make task snapshots store in RGB565"
-rw-r--r--core/java/android/view/SurfaceControl.java26
-rw-r--r--core/jni/android_view_SurfaceControl.cpp9
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java23
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotLoader.java18
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotPersister.java12
7 files changed, 77 insertions, 15 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b815c641ff25..3251127397b6 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -90,7 +90,8 @@ public final class SurfaceControl implements Parcelable {
Rect sourceCrop, int width, int height, boolean useIdentityTransform, int rotation,
boolean captureSecureLayers);
private static native ScreenshotGraphicBuffer nativeCaptureLayers(IBinder displayToken,
- long layerObject, Rect sourceCrop, float frameScale, long[] excludeLayerObjects);
+ long layerObject, Rect sourceCrop, float frameScale, long[] excludeLayerObjects,
+ int format);
private static native long nativeMirrorSurface(long mirrorOfObject);
private static native long nativeCreateTransaction();
private static native long nativeGetNativeTransactionFinalizer();
@@ -1869,8 +1870,27 @@ public final class SurfaceControl implements Parcelable {
*/
public static ScreenshotGraphicBuffer captureLayers(SurfaceControl layer, Rect sourceCrop,
float frameScale) {
+ return captureLayers(layer, sourceCrop, frameScale, PixelFormat.RGBA_8888);
+ }
+
+ /**
+ * Captures a layer and its children and returns a {@link GraphicBuffer} 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.
+ * @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 GraphicBuffer that contains the layer capture.
+ * @hide
+ */
+ public static ScreenshotGraphicBuffer captureLayers(SurfaceControl layer, Rect sourceCrop,
+ float frameScale, int format) {
final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
- return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale, null);
+ return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale, null,
+ format);
}
/**
@@ -1885,7 +1905,7 @@ public final class SurfaceControl implements Parcelable {
nativeExcludeObjects[i] = exclude[i].mNativeObject;
}
return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale,
- nativeExcludeObjects);
+ nativeExcludeObjects, PixelFormat.RGBA_8888);
}
/**
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c807e90d5ad4..f8a2744fdcb0 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -274,7 +274,7 @@ static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTokenObj,
jlong layerObject, jobject sourceCropObj, jfloat frameScale,
- jlongArray excludeObjectArray) {
+ jlongArray excludeObjectArray, jint format) {
auto layer = reinterpret_cast<SurfaceControl *>(layerObject);
if (layer == NULL) {
@@ -311,8 +311,9 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTok
dataspace = pickDataspaceFromColorMode(colorMode);
}
status_t res = ScreenshotClient::captureChildLayers(layer->getHandle(), dataspace,
- ui::PixelFormat::RGBA_8888, sourceCrop,
- excludeHandles, frameScale, &buffer);
+ static_cast<ui::PixelFormat>(format),
+ sourceCrop, excludeHandles, frameScale,
+ &buffer);
if (res != NO_ERROR) {
return NULL;
}
@@ -1386,7 +1387,7 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeScreenshot },
{"nativeCaptureLayers",
"(Landroid/os/IBinder;JLandroid/graphics/Rect;"
- "F[J)"
+ "F[JI)"
"Landroid/view/SurfaceControl$ScreenshotGraphicBuffer;",
(void*)nativeCaptureLayers },
{"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V",
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index efa42e5735e1..cb0b5993c420 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2652,6 +2652,9 @@
<!-- The amount to scale fullscreen snapshots for Overview and snapshot starting windows. -->
<item name="config_fullTaskSnapshotScale" format="float" type="dimen">1.0</item>
+ <!-- Feature flag to store TaskSnapshot in 16 bit pixel format to save memory. -->
+ <bool name="config_use16BitTaskSnapshotPixelFormat">false</bool>
+
<!-- Determines whether recent tasks are provided to the user. Default device has recents
property. If this is false, then the following recents config flags are ignored. -->
<bool name="config_hasRecents">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 91a8ba4ca3d2..28809daeaad8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -356,6 +356,7 @@
<java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/>
<java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
<java-symbol type="dimen" name="config_fullTaskSnapshotScale" />
+ <java-symbol type="bool" name="config_use16BitTaskSnapshotPixelFormat" />
<java-symbol type="bool" name="config_lowRamTaskSnapshotsAndRecents" />
<java-symbol type="bool" name="config_hasRecents" />
<java-symbol type="string" name="config_recentsComponentName" />
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 0d4ec652f3bb..35f61a88522b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+
import static com.android.server.wm.TaskSnapshotPersister.DISABLE_FULL_SIZED_BITMAPS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -248,6 +250,12 @@ class TaskSnapshotController {
@Nullable
SurfaceControl.ScreenshotGraphicBuffer createTaskSnapshot(@NonNull Task task,
float scaleFraction) {
+ return createTaskSnapshot(task, scaleFraction, PixelFormat.RGBA_8888);
+ }
+
+ @Nullable
+ SurfaceControl.ScreenshotGraphicBuffer createTaskSnapshot(@NonNull Task task,
+ float scaleFraction, int pixelFormat) {
if (task.getSurfaceControl() == null) {
if (DEBUG_SCREENSHOT) {
Slog.w(TAG_WM, "Failed to take screenshot. No surface control for " + task);
@@ -258,7 +266,7 @@ class TaskSnapshotController {
mTmpRect.offsetTo(0, 0);
final SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer =
SurfaceControl.captureLayers(
- task.getSurfaceControl(), mTmpRect, scaleFraction);
+ task.getSurfaceControl(), mTmpRect, scaleFraction, pixelFormat);
final GraphicBuffer buffer = screenshotBuffer != null ? screenshotBuffer.getGraphicBuffer()
: null;
if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) {
@@ -299,8 +307,14 @@ class TaskSnapshotController {
Slog.w(TAG_WM, "Failed to take screenshot. No main window for " + task);
return null;
}
+ final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
+ final boolean isShowWallpaper = (mainWindow.getAttrs().flags & FLAG_SHOW_WALLPAPER) != 0;
+ final int pixelFormat = mPersister.use16BitFormat() && activity.fillsParent()
+ && !(isWindowTranslucent && isShowWallpaper)
+ ? PixelFormat.RGB_565
+ : PixelFormat.RGBA_8888;
final SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer =
- createTaskSnapshot(task, scaleFraction);
+ createTaskSnapshot(task, scaleFraction, pixelFormat);
if (screenshotBuffer == null) {
if (DEBUG_SCREENSHOT) {
@@ -308,7 +322,8 @@ class TaskSnapshotController {
}
return null;
}
- final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
+ final boolean isTranslucent = PixelFormat.formatHasAlpha(pixelFormat)
+ && (!activity.fillsParent() || isWindowTranslucent);
return new TaskSnapshot(
System.currentTimeMillis() /* id */,
activity.mActivityComponent, screenshotBuffer.getGraphicBuffer(),
@@ -316,7 +331,7 @@ class TaskSnapshotController {
activity.getTask().getConfiguration().orientation,
getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
- !activity.fillsParent() || isWindowTranslucent);
+ isTranslucent);
}
private boolean shouldDisableSnapshots() {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 696e1c3a2602..22c1ea59d176 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -75,25 +75,35 @@ class TaskSnapshotLoader {
final byte[] bytes = Files.readAllBytes(protoFile.toPath());
final TaskSnapshotProto proto = TaskSnapshotProto.parseFrom(bytes);
final Options options = new Options();
- options.inPreferredConfig = Config.HARDWARE;
+ options.inPreferredConfig = mPersister.use16BitFormat() && !proto.isTranslucent
+ ? Config.RGB_565
+ : Config.ARGB_8888;
final Bitmap bitmap = BitmapFactory.decodeFile(bitmapFile.getPath(), options);
if (bitmap == null) {
Slog.w(TAG, "Failed to load bitmap: " + bitmapFile.getPath());
return null;
}
- final GraphicBuffer buffer = bitmap.createGraphicBufferHandle();
+
+ final Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
+ bitmap.recycle();
+ if (hwBitmap == null) {
+ Slog.w(TAG, "Failed to create hardware bitmap: " + bitmapFile.getPath());
+ return null;
+ }
+ final GraphicBuffer buffer = hwBitmap.createGraphicBufferHandle();
if (buffer == null) {
Slog.w(TAG, "Failed to retrieve gralloc buffer for bitmap: "
+ bitmapFile.getPath());
return null;
}
+
final ComponentName topActivityComponent = ComponentName.unflattenFromString(
proto.topActivityComponent);
// For legacy snapshots, restore the scale based on the reduced resolution state
final float legacyScale = reducedResolution ? mPersister.getReducedScale() : 1f;
final float scale = Float.compare(proto.scale, 0f) != 0 ? proto.scale : legacyScale;
- return new TaskSnapshot(proto.id, topActivityComponent, buffer, bitmap.getColorSpace(),
- proto.orientation,
+ return new TaskSnapshot(proto.id, topActivityComponent, buffer,
+ hwBitmap.getColorSpace(), proto.orientation,
new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
reducedResolution, scale, proto.isRealSnapshot, proto.windowingMode,
proto.systemUiVisibility, proto.isTranslucent);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index a156f5c240a8..59155907823b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -74,6 +74,7 @@ class TaskSnapshotPersister {
private final Object mLock = new Object();
private final DirectoryResolver mDirectoryResolver;
private final float mReducedScale;
+ private final boolean mUse16BitFormat;
/**
* The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was
@@ -92,6 +93,8 @@ class TaskSnapshotPersister {
mReducedScale = ActivityManager.isLowRamDeviceStatic()
? LOW_RAM_REDUCED_SCALE : REDUCED_SCALE;
}
+ mUse16BitFormat = service.mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_use16BitTaskSnapshotPixelFormat);
}
/**
@@ -164,6 +167,15 @@ class TaskSnapshotPersister {
return mReducedScale;
}
+ /**
+ * Return if task snapshots are stored in 16 bit pixel format.
+ *
+ * @return true if task snapshots are stored in 16 bit pixel format.
+ */
+ boolean use16BitFormat() {
+ return mUse16BitFormat;
+ }
+
@TestApi
void waitForQueueEmpty() {
while (true) {