From 3d87156bd0b03436673c116a1be7b8f0a288d947 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 19 Feb 2021 12:21:25 -0800 Subject: [PATCH] Add DisplayHashParams to specify how to generate display hash When generating a DisplayHash, each algorithm can have different requirements about how to capture the content. Instead of trying to adjust the buffer after the content is rendered, we can let SurfaceFlinger use the specified arguments to render the content. This can be done by getting the display hash params from ExtServices so they can be specified per algorithm. Then, system server will render the content using the specified values, ensuring a more efficient way to scale and grayscale the final buffer. Test: DisplayHash is grayscale and scaled. Bug: 155825630 Change-Id: I657e2f94219baaac9318500134a6cd82cd07af56 --- core/api/system-current.txt | 18 ++ .../displayhash/DisplayHashParams.aidl | 19 ++ .../displayhash/DisplayHashParams.java | 251 ++++++++++++++++++ .../displayhash/DisplayHasherService.java | 34 ++- .../displayhash/IDisplayHasherService.aidl | 7 + .../server/wm/DisplayHashController.java | 116 +++++--- .../server/wm/WindowManagerService.java | 35 +-- 7 files changed, 410 insertions(+), 70 deletions(-) create mode 100644 core/java/android/service/displayhash/DisplayHashParams.aidl create mode 100644 core/java/android/service/displayhash/DisplayHashParams.java diff --git a/core/api/system-current.txt b/core/api/system-current.txt index b0b2c6cdf0f71..cdd9f9bf7a651 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -9587,10 +9587,28 @@ package android.service.dataloader { package android.service.displayhash { + public final class DisplayHashParams implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public android.util.Size getBufferSize(); + method public boolean isBufferScaleWithFiltering(); + method public boolean isGrayscaleBuffer(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class DisplayHashParams.Builder { + ctor public DisplayHashParams.Builder(); + method @NonNull public android.service.displayhash.DisplayHashParams build(); + method @NonNull public android.service.displayhash.DisplayHashParams.Builder setBufferScaleWithFiltering(boolean); + method @NonNull public android.service.displayhash.DisplayHashParams.Builder setBufferSize(int, int); + method @NonNull public android.service.displayhash.DisplayHashParams.Builder setGrayscaleBuffer(boolean); + } + public abstract class DisplayHasherService extends android.app.Service { ctor public DisplayHasherService(); method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method @Nullable public abstract void onGenerateDisplayHash(@NonNull byte[], @NonNull android.hardware.HardwareBuffer, @NonNull android.graphics.Rect, @NonNull String, @NonNull android.view.displayhash.DisplayHashResultCallback); + method @NonNull public abstract java.util.Map onGetDisplayHashAlgorithms(); method @Nullable public abstract android.view.displayhash.VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[], @NonNull android.view.displayhash.DisplayHash); field public static final String SERVICE_INTERFACE = "android.service.displayhash.DisplayHasherService"; } diff --git a/core/java/android/service/displayhash/DisplayHashParams.aidl b/core/java/android/service/displayhash/DisplayHashParams.aidl new file mode 100644 index 0000000000000..90f9bf14a6306 --- /dev/null +++ b/core/java/android/service/displayhash/DisplayHashParams.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 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.service.displayhash; + +parcelable DisplayHashParams; diff --git a/core/java/android/service/displayhash/DisplayHashParams.java b/core/java/android/service/displayhash/DisplayHashParams.java new file mode 100644 index 0000000000000..6a176a338d2e6 --- /dev/null +++ b/core/java/android/service/displayhash/DisplayHashParams.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2021 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.service.displayhash; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.graphics.Rect; +import android.hardware.HardwareBuffer; +import android.os.Parcelable; +import android.util.Size; +import android.view.displayhash.DisplayHashResultCallback; + +import com.android.internal.util.DataClass; + +/** + * Information passed from the {@link DisplayHasherService} to system server about how to get the + * display data that will be used to generate the {@link android.view.displayhash.DisplayHash} + * + * @hide + */ +@SystemApi +@DataClass(genAidl = true, genToString = true, genParcelable = true, genHiddenConstructor = true) +public final class DisplayHashParams implements Parcelable { + /** + * The size to scale the buffer to so the hash algorithm can properly generate the hash. The + * buffer given to the {@link DisplayHasherService#onGenerateDisplayHash(byte[], HardwareBuffer, + * Rect, String, DisplayHashResultCallback)} will be stretched based on the value set here. + * If {@code null}, the buffer size will not be changed. + */ + @Nullable + private final Size mBufferSize; + + /** + * Whether the content captured will use filtering when scaling. + */ + private final boolean mBufferScaleWithFiltering; + + /** + * Whether the content will be captured in grayscale or color. + */ + private final boolean mGrayscaleBuffer; + + /** + * A builder for {@link DisplayHashParams} + */ + public static final class Builder { + @Nullable + private Size mBufferSize; + private boolean mBufferScaleWithFiltering; + private boolean mGrayscaleBuffer; + + /** + * Creates a new Builder. + */ + public Builder() { + } + + /** + * The size to scale the buffer to so the hash algorithm can properly generate the hash. + */ + @NonNull + public Builder setBufferSize(int w, int h) { + mBufferSize = new Size(w, h); + return this; + } + + /** + * Whether the content captured will use filtering when scaling. + */ + @NonNull + public Builder setBufferScaleWithFiltering(boolean value) { + mBufferScaleWithFiltering = value; + return this; + } + + /** + * Whether the content will be captured in grayscale or color. + */ + @NonNull + public Builder setGrayscaleBuffer(boolean value) { + mGrayscaleBuffer = value; + return this; + } + + /** Builds the instance. This builder should not be touched after calling this! */ + @NonNull + public DisplayHashParams build() { + return new DisplayHashParams(mBufferSize, mBufferScaleWithFiltering, mGrayscaleBuffer); + } + } + + + + // Code below generated by codegen v1.0.22. + // + // DO NOT MODIFY! + // CHECKSTYLE:OFF Generated code + // + // To regenerate run: + // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/displayhash/DisplayHashParams.java + // + // To exclude the generated code from IntelliJ auto-formatting enable (one-time): + // Settings > Editor > Code Style > Formatter Control + //@formatter:off + + + /** + * Creates a new DisplayHashParams. + * + * @param bufferSize + * The size to scale the buffer to so the hash algorithm can properly generate the hash. The + * buffer given to the {@link DisplayHasherService#onGenerateDisplayHash(byte[], HardwareBuffer, + * Rect, String, DisplayHashResultCallback)} will be stretched based on the value set here. + * If {@code null}, the buffer size will not be changed. + * @param bufferScaleWithFiltering + * Whether the content captured will use filtering when scaling. + * @param grayscaleBuffer + * Whether the content will be captured in grayscale or color. + * @hide + */ + @DataClass.Generated.Member + public DisplayHashParams( + @Nullable Size bufferSize, + boolean bufferScaleWithFiltering, + boolean grayscaleBuffer) { + this.mBufferSize = bufferSize; + this.mBufferScaleWithFiltering = bufferScaleWithFiltering; + this.mGrayscaleBuffer = grayscaleBuffer; + + // onConstructed(); // You can define this method to get a callback + } + + /** + * The size to scale the buffer to so the hash algorithm can properly generate the hash. The + * buffer given to the {@link DisplayHasherService#onGenerateDisplayHash(byte[], HardwareBuffer, + * Rect, String, DisplayHashResultCallback)} will be stretched based on the value set here. + * If {@code null}, the buffer size will not be changed. + */ + @DataClass.Generated.Member + public @Nullable Size getBufferSize() { + return mBufferSize; + } + + /** + * Whether the content captured will use filtering when scaling. + */ + @DataClass.Generated.Member + public boolean isBufferScaleWithFiltering() { + return mBufferScaleWithFiltering; + } + + /** + * Whether the content will be captured in grayscale or color. + */ + @DataClass.Generated.Member + public boolean isGrayscaleBuffer() { + return mGrayscaleBuffer; + } + + @Override + @DataClass.Generated.Member + public String toString() { + // You can override field toString logic by defining methods like: + // String fieldNameToString() { ... } + + return "DisplayHashParams { " + + "bufferSize = " + mBufferSize + ", " + + "bufferScaleWithFiltering = " + mBufferScaleWithFiltering + ", " + + "grayscaleBuffer = " + mGrayscaleBuffer + + " }"; + } + + @Override + @DataClass.Generated.Member + public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { + // You can override field parcelling by defining methods like: + // void parcelFieldName(Parcel dest, int flags) { ... } + + byte flg = 0; + if (mBufferScaleWithFiltering) flg |= 0x2; + if (mGrayscaleBuffer) flg |= 0x4; + if (mBufferSize != null) flg |= 0x1; + dest.writeByte(flg); + if (mBufferSize != null) dest.writeSize(mBufferSize); + } + + @Override + @DataClass.Generated.Member + public int describeContents() { return 0; } + + /** @hide */ + @SuppressWarnings({"unchecked", "RedundantCast"}) + @DataClass.Generated.Member + /* package-private */ DisplayHashParams(@NonNull android.os.Parcel in) { + // You can override field unparcelling by defining methods like: + // static FieldType unparcelFieldName(Parcel in) { ... } + + byte flg = in.readByte(); + boolean bufferScaleWithFiltering = (flg & 0x2) != 0; + boolean grayscaleBuffer = (flg & 0x4) != 0; + Size bufferSize = (flg & 0x1) == 0 ? null : (Size) in.readSize(); + + this.mBufferSize = bufferSize; + this.mBufferScaleWithFiltering = bufferScaleWithFiltering; + this.mGrayscaleBuffer = grayscaleBuffer; + + // onConstructed(); // You can define this method to get a callback + } + + @DataClass.Generated.Member + public static final @NonNull Parcelable.Creator CREATOR + = new Parcelable.Creator() { + @Override + public DisplayHashParams[] newArray(int size) { + return new DisplayHashParams[size]; + } + + @Override + public DisplayHashParams createFromParcel(@NonNull android.os.Parcel in) { + return new DisplayHashParams(in); + } + }; + + @DataClass.Generated( + time = 1615565493989L, + codegenVersion = "1.0.22", + sourceFile = "frameworks/base/core/java/android/service/displayhash/DisplayHashParams.java", + inputSignatures = "private final @android.annotation.Nullable android.util.Size mBufferSize\nprivate final boolean mBufferScaleWithFiltering\nprivate final boolean mGrayscaleBuffer\nclass DisplayHashParams extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.Nullable android.util.Size mBufferSize\nprivate boolean mBufferScaleWithFiltering\nprivate boolean mGrayscaleBuffer\npublic @android.annotation.NonNull android.service.displayhash.DisplayHashParams.Builder setBufferSize(int,int)\npublic @android.annotation.NonNull android.service.displayhash.DisplayHashParams.Builder setBufferScaleWithFiltering(boolean)\npublic @android.annotation.NonNull android.service.displayhash.DisplayHashParams.Builder setGrayscaleBuffer(boolean)\npublic @android.annotation.NonNull android.service.displayhash.DisplayHashParams build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genAidl=true, genToString=true, genParcelable=true, genHiddenConstructor=true)") + @Deprecated + private void __metadata() {} + + + //@formatter:on + // End of generated code + +} diff --git a/core/java/android/service/displayhash/DisplayHasherService.java b/core/java/android/service/displayhash/DisplayHasherService.java index 331dbe91f6c72..2105d848057e6 100644 --- a/core/java/android/service/displayhash/DisplayHasherService.java +++ b/core/java/android/service/displayhash/DisplayHasherService.java @@ -34,6 +34,8 @@ import android.view.displayhash.DisplayHash; import android.view.displayhash.DisplayHashResultCallback; import android.view.displayhash.VerifiedDisplayHash; +import java.util.Map; + /** * A service that handles generating and verify {@link DisplayHash}. * @@ -49,15 +51,6 @@ public abstract class DisplayHasherService extends Service { public static final String EXTRA_VERIFIED_DISPLAY_HASH = "android.service.displayhash.extra.VERIFIED_DISPLAY_HASH"; - /** - * Manifest metadata key for the resource string array containing the names of all hashing - * algorithms provided by the service. - * - * @hide - */ - public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = - "android.displayhash.available_algorithms"; - /** * The {@link Intent} action that must be declared as handled by a service in its manifest * for the system to recognize it as a DisplayHash providing service. @@ -96,7 +89,7 @@ public abstract class DisplayHasherService extends Service { * @param buffer The buffer for the content to generate the hash for. * @param bounds The size and position of the content in window space. * @param hashAlgorithm The String for the hashing algorithm to use based values in - * {@link #SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS)}. + * {@link #getDisplayHashAlgorithms(RemoteCallback)}. * @param callback The callback to invoke * {@link DisplayHashResultCallback#onDisplayHashResult(DisplayHash)} * if successfully generated a DisplayHash or {@link @@ -107,6 +100,12 @@ public abstract class DisplayHasherService extends Service { @NonNull HardwareBuffer buffer, @NonNull Rect bounds, @NonNull String hashAlgorithm, @NonNull DisplayHashResultCallback callback); + /** + * Returns a map of supported algorithms and their {@link DisplayHashParams} + */ + @NonNull + public abstract Map onGetDisplayHashAlgorithms(); + /** * Call to verify that the DisplayHash passed in was generated by the system. * @@ -132,6 +131,15 @@ public abstract class DisplayHasherService extends Service { callback.sendResult(data); } + private void getDisplayHashAlgorithms(RemoteCallback callback) { + Map displayHashParams = onGetDisplayHashAlgorithms(); + final Bundle data = new Bundle(); + for (Map.Entry entry : displayHashParams.entrySet()) { + data.putParcelable(entry.getKey(), entry.getValue()); + } + callback.sendResult(data); + } + private final class DisplayHasherServiceWrapper extends IDisplayHasherService.Stub { @Override public void generateDisplayHash(byte[] salt, HardwareBuffer buffer, Rect bounds, @@ -164,5 +172,11 @@ public abstract class DisplayHasherService extends Service { obtainMessage(DisplayHasherService::verifyDisplayHash, DisplayHasherService.this, salt, displayHash, callback)); } + + @Override + public void getDisplayHashAlgorithms(RemoteCallback callback) { + mHandler.sendMessage(obtainMessage(DisplayHasherService::getDisplayHashAlgorithms, + DisplayHasherService.this, callback)); + } } } diff --git a/core/java/android/service/displayhash/IDisplayHasherService.aidl b/core/java/android/service/displayhash/IDisplayHasherService.aidl index 236bc28c74c86..d9dcdcaf921e1 100644 --- a/core/java/android/service/displayhash/IDisplayHasherService.aidl +++ b/core/java/android/service/displayhash/IDisplayHasherService.aidl @@ -51,4 +51,11 @@ oneway interface IDisplayHasherService { * @param callback The callback invoked to send back the VerifiedDisplayHash. */ void verifyDisplayHash(in byte[] salt, in DisplayHash displayHash, in RemoteCallback callback); + + /** + * Call to get a map of supported algorithms and their {@link DisplayHashParams} + * + * @param callback The callback invoked to send back the map of algorithms to DisplayHashParams. + */ + void getDisplayHashAlgorithms(in RemoteCallback callback); } diff --git a/services/core/java/com/android/server/wm/DisplayHashController.java b/services/core/java/com/android/server/wm/DisplayHashController.java index 7e16c22ee15e0..1262dee68b74f 100644 --- a/services/core/java/com/android/server/wm/DisplayHashController.java +++ b/services/core/java/com/android/server/wm/DisplayHashController.java @@ -17,7 +17,9 @@ package com.android.server.wm; import static android.service.displayhash.DisplayHasherService.EXTRA_VERIFIED_DISPLAY_HASH; -import static android.service.displayhash.DisplayHasherService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS; +import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM; +import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN; +import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -32,7 +34,6 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.content.res.Resources; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.RectF; @@ -45,16 +46,21 @@ import android.os.Message; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; +import android.service.displayhash.DisplayHashParams; import android.service.displayhash.DisplayHasherService; import android.service.displayhash.IDisplayHasherService; +import android.util.Size; import android.util.Slog; import android.view.MagnificationSpec; +import android.view.SurfaceControl; import android.view.displayhash.DisplayHash; import android.view.displayhash.VerifiedDisplayHash; import com.android.internal.annotations.GuardedBy; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -78,12 +84,15 @@ public class DisplayHashController { private final Context mContext; /** - * Lock used for the cached {@link #mHashAlgorithms} array + * Lock used for the cached {@link #mDisplayHashAlgorithms} map */ - private final Object mHashAlgorithmsLock = new Object(); + private final Object mDisplayHashAlgorithmsLock = new Object(); - @GuardedBy("mHashingAlgorithmsLock") - private String[] mHashAlgorithms; + /** + * The cached map of display hash algorithms to the {@link DisplayHashParams} + */ + @GuardedBy("mDisplayHashAlgorithmsLock") + private Map mDisplayHashAlgorithms; private final Handler mHandler; @@ -104,34 +113,8 @@ public class DisplayHashController { } String[] getSupportedHashAlgorithms() { - // We have a separate lock for the hashing algorithm array since it doesn't need to make - // the request through the service connection. Instead, we have a lock to ensure we can - // properly cache the hashing algorithms array so we don't need to call into the - // ExtServices process for each request. - synchronized (mHashAlgorithmsLock) { - // Already have cached values - if (mHashAlgorithms != null) { - return mHashAlgorithms; - } - - final ServiceInfo serviceInfo = getServiceInfo(); - if (serviceInfo == null) return null; - - final PackageManager pm = mContext.getPackageManager(); - final Resources res; - try { - res = pm.getResourcesForApplication(serviceInfo.applicationInfo); - } catch (PackageManager.NameNotFoundException e) { - Slog.e(TAG, "Error getting application resources for " + serviceInfo, e); - return null; - } - - final int resourceId = serviceInfo.metaData.getInt( - SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS); - mHashAlgorithms = res.getStringArray(resourceId); - - return mHashAlgorithms; - } + Map displayHashAlgorithms = getDisplayHashAlgorithms(); + return displayHashAlgorithms.keySet().toArray(new String[0]); } @Nullable @@ -148,13 +131,76 @@ public class DisplayHashController { return results.getParcelable(EXTRA_VERIFIED_DISPLAY_HASH); } - void generateDisplayHash(HardwareBuffer buffer, Rect bounds, + private void generateDisplayHash(HardwareBuffer buffer, Rect bounds, String hashAlgorithm, RemoteCallback callback) { connectAndRun( service -> service.generateDisplayHash(mSalt, buffer, bounds, hashAlgorithm, callback)); } + void generateDisplayHash(SurfaceControl.LayerCaptureArgs.Builder args, + Rect boundsInWindow, String hashAlgorithm, RemoteCallback callback) { + final Map displayHashAlgorithmsMap = getDisplayHashAlgorithms(); + DisplayHashParams displayHashParams = displayHashAlgorithmsMap.get(hashAlgorithm); + if (displayHashParams == null) { + Slog.w(TAG, "Failed to generateDisplayHash. Invalid hashAlgorithm"); + sendDisplayHashError(callback, DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM); + return; + } + + Size size = displayHashParams.getBufferSize(); + if (size != null && (size.getWidth() > 0 || size.getHeight() > 0)) { + args.setFrameScale((float) size.getWidth() / boundsInWindow.width(), + (float) size.getHeight() / boundsInWindow.height()); + } + + args.setGrayscale(displayHashParams.isGrayscaleBuffer()); + + SurfaceControl.ScreenshotHardwareBuffer screenshotHardwareBuffer = + SurfaceControl.captureLayers(args.build()); + if (screenshotHardwareBuffer == null + || screenshotHardwareBuffer.getHardwareBuffer() == null) { + Slog.w(TAG, "Failed to generate DisplayHash. Couldn't capture content"); + sendDisplayHashError(callback, DISPLAY_HASH_ERROR_UNKNOWN); + return; + } + + generateDisplayHash(screenshotHardwareBuffer.getHardwareBuffer(), boundsInWindow, + hashAlgorithm, callback); + } + + private Map getDisplayHashAlgorithms() { + // We have a separate lock for the hashing params to ensure we can properly cache the + // hashing params so we don't need to call into the ExtServices process for each request. + synchronized (mDisplayHashAlgorithmsLock) { + if (mDisplayHashAlgorithms != null) { + return mDisplayHashAlgorithms; + } + + final SyncCommand syncCommand = new SyncCommand(); + Bundle results = syncCommand.run((service, remoteCallback) -> { + try { + service.getDisplayHashAlgorithms(remoteCallback); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to invoke getDisplayHashAlgorithms command", e); + } + }); + + mDisplayHashAlgorithms = new HashMap<>(results.size()); + for (String key : results.keySet()) { + mDisplayHashAlgorithms.put(key, results.getParcelable(key)); + } + + return mDisplayHashAlgorithms; + } + } + + void sendDisplayHashError(RemoteCallback callback, int errorCode) { + Bundle bundle = new Bundle(); + bundle.putInt(EXTRA_DISPLAY_HASH_ERROR_CODE, errorCode); + callback.sendResult(bundle); + } + /** * Calculate the bounds to generate the hash for. This takes into account window transform, * magnification, and display bounds. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 6f853c7955259..47d483227276e 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -84,8 +84,6 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID; import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW; import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN; -import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN; -import static android.view.displayhash.DisplayHashResultCallback.EXTRA_DISPLAY_HASH_ERROR_CODE; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT; @@ -8655,14 +8653,16 @@ public class WindowManagerService extends IWindowManager.Stub final WindowState win = windowForClientLocked(session, window, false); if (win == null) { Slog.w(TAG, "Failed to generate DisplayHash. Invalid window"); - sendDisplayHashError(callback, DISPLAY_HASH_ERROR_MISSING_WINDOW); + mDisplayHashController.sendDisplayHashError(callback, + DISPLAY_HASH_ERROR_MISSING_WINDOW); return; } DisplayContent displayContent = win.getDisplayContent(); if (displayContent == null) { Slog.w(TAG, "Failed to generate DisplayHash. Window is not on a display"); - sendDisplayHashError(callback, DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN); + mDisplayHashController.sendDisplayHashError(callback, + DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN); return; } @@ -8672,7 +8672,8 @@ public class WindowManagerService extends IWindowManager.Stub if (boundsInDisplay.isEmpty()) { Slog.w(TAG, "Failed to generate DisplayHash. Bounds are not on screen"); - sendDisplayHashError(callback, DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN); + mDisplayHashController.sendDisplayHashError(callback, + DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN); return; } } @@ -8682,23 +8683,13 @@ public class WindowManagerService extends IWindowManager.Stub // be covering it with the same uid. We want to make sure we include content that's // covering to ensure we get as close as possible to what the user sees final int uid = session.mUid; - SurfaceControl.LayerCaptureArgs args = + SurfaceControl.LayerCaptureArgs.Builder args = new SurfaceControl.LayerCaptureArgs.Builder(displaySurfaceControl) .setUid(uid) - .setSourceCrop(boundsInDisplay) - .build(); + .setSourceCrop(boundsInDisplay); - SurfaceControl.ScreenshotHardwareBuffer screenshotHardwareBuffer = - SurfaceControl.captureLayers(args); - if (screenshotHardwareBuffer == null - || screenshotHardwareBuffer.getHardwareBuffer() == null) { - Slog.w(TAG, "Failed to generate DisplayHash. Couldn't capture content"); - sendDisplayHashError(callback, DISPLAY_HASH_ERROR_UNKNOWN); - return; - } - - mDisplayHashController.generateDisplayHash(screenshotHardwareBuffer.getHardwareBuffer(), - boundsInWindow, hashAlgorithm, callback); + mDisplayHashController.generateDisplayHash(args, boundsInWindow, + hashAlgorithm, callback); } boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) { @@ -8716,10 +8707,4 @@ public class WindowManagerService extends IWindowManager.Stub return snapshot != null && snapshot.hasImeSurface(); } } - - private void sendDisplayHashError(RemoteCallback callback, int errorCode) { - Bundle bundle = new Bundle(); - bundle.putInt(EXTRA_DISPLAY_HASH_ERROR_CODE, errorCode); - callback.sendResult(bundle); - } }