diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 251b3c46e6815..faf3c55ec24eb 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -9629,10 +9629,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 b95674e511d50..f0dc7fe08c665 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; @@ -8633,14 +8631,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; } @@ -8650,7 +8650,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; } } @@ -8660,23 +8661,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) { @@ -8694,10 +8685,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); - } }