Loading core/api/current.txt +37 −0 Original line number Diff line number Diff line Loading @@ -10444,6 +10444,7 @@ package android.content { field public static final int CONTEXT_RESTRICTED = 4; // 0x4 field public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps"; field public static final String DEVICE_POLICY_SERVICE = "device_policy"; field public static final String DISPLAY_HASH_SERVICE = "display_hash"; field public static final String DISPLAY_SERVICE = "display"; field public static final String DOWNLOAD_SERVICE = "download"; field public static final String DROPBOX_SERVICE = "dropbox"; Loading Loading @@ -48235,6 +48236,7 @@ package android.view { method public android.view.View focusSearch(int); method public void forceHasOverlappingRendering(boolean); method public void forceLayout(); method @Nullable public void generateDisplayHash(@NonNull String, @Nullable android.graphics.Rect, @NonNull java.util.concurrent.Executor, @NonNull android.view.displayhash.DisplayHashResultCallback); method public static int generateViewId(); method public CharSequence getAccessibilityClassName(); method public android.view.View.AccessibilityDelegate getAccessibilityDelegate(); Loading Loading @@ -51190,6 +51192,41 @@ package android.view.contentcapture { } package android.view.displayhash { public final class DisplayHash implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.displayhash.DisplayHash> CREATOR; } public final class DisplayHashManager { method @NonNull public java.util.Set<java.lang.String> getSupportedHashAlgorithms(); method @Nullable public android.view.displayhash.VerifiedDisplayHash verifyDisplayHash(@NonNull android.view.displayhash.DisplayHash); } public interface DisplayHashResultCallback { method public void onDisplayHashError(int); method public void onDisplayHashResult(@NonNull android.view.displayhash.DisplayHash); field public static final int DISPLAY_HASH_ERROR_INVALID_BOUNDS = -2; // 0xfffffffe field public static final int DISPLAY_HASH_ERROR_MISSING_WINDOW = -3; // 0xfffffffd field public static final int DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN = -4; // 0xfffffffc field public static final int DISPLAY_HASH_ERROR_UNKNOWN = -1; // 0xffffffff } public final class VerifiedDisplayHash implements android.os.Parcelable { ctor public VerifiedDisplayHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[]); method public int describeContents(); method @NonNull public android.graphics.Rect getBoundsInWindow(); method @NonNull public String getHashAlgorithm(); method @NonNull public byte[] getImageHash(); method public long getTimeMillis(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.displayhash.VerifiedDisplayHash> CREATOR; } } package android.view.inputmethod { public class BaseInputConnection implements android.view.inputmethod.InputConnection { core/api/system-current.txt +27 −24 Original line number Diff line number Diff line Loading @@ -9984,6 +9984,18 @@ package android.service.dataloader { } package android.service.displayhash { 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 @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"; } } package android.service.euicc { public final class DownloadSubscriptionResult implements android.os.Parcelable { Loading Loading @@ -10344,30 +10356,6 @@ package android.service.rotationresolver { } package android.service.screenshot { public final class ScreenshotHash implements android.os.Parcelable { ctor public ScreenshotHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[], @NonNull byte[]); method public int describeContents(); method @NonNull public android.graphics.Rect getBoundsInWindow(); method @NonNull public String getHashingAlgorithm(); method @NonNull public byte[] getHmac(); method @NonNull public byte[] getImageHash(); method public long getScreenshotTimeMillis(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.service.screenshot.ScreenshotHash> CREATOR; } public abstract class ScreenshotHasherService extends android.app.Service { ctor public ScreenshotHasherService(); method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method @Nullable public abstract android.service.screenshot.ScreenshotHash onGenerateScreenshotHash(@NonNull byte[], @NonNull android.hardware.HardwareBuffer, @NonNull android.graphics.Rect, @NonNull String); method public abstract boolean onVerifyScreenshotHash(@NonNull byte[], @NonNull android.service.screenshot.ScreenshotHash); field public static final String SERVICE_INTERFACE = "android.service.screenshot.ScreenshotHasherService"; } } package android.service.search { public abstract class SearchUiService extends android.app.Service { Loading Loading @@ -14399,6 +14387,21 @@ package android.view.contentcapture { } package android.view.displayhash { public final class DisplayHash implements android.os.Parcelable { ctor public DisplayHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[], @NonNull byte[]); method public int describeContents(); method @NonNull public android.graphics.Rect getBoundsInWindow(); method @NonNull public String getHashAlgorithm(); method @NonNull public byte[] getHmac(); method @NonNull public byte[] getImageHash(); method public long getTimeMillis(); method public void writeToParcel(@NonNull android.os.Parcel, int); } } package android.view.translation { public final class UiTranslationManager { core/java/android/app/SystemServiceRegistry.java +8 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,7 @@ import android.view.autofill.AutofillManager; import android.view.autofill.IAutoFillManager; import android.view.contentcapture.ContentCaptureManager; import android.view.contentcapture.IContentCaptureManager; import android.view.displayhash.DisplayHashManager; import android.view.inputmethod.InputMethodManager; import android.view.textclassifier.TextClassificationManager; import android.view.textservice.TextServicesManager; Loading Loading @@ -1426,6 +1427,13 @@ public final class SystemServiceRegistry { } }); registerService(Context.DISPLAY_HASH_SERVICE, DisplayHashManager.class, new CachedServiceFetcher<DisplayHashManager>() { @Override public DisplayHashManager createService(ContextImpl ctx) { return new DisplayHashManager(); }}); sInitializing = true; try { // Note: the following functions need to be @SystemApis, once they become mainline Loading core/java/android/content/Context.java +8 −0 Original line number Diff line number Diff line Loading @@ -5490,6 +5490,14 @@ public abstract class Context { @SystemApi public static final String DOMAIN_VERIFICATION_SERVICE = "domain_verification"; /** * Use with {@link #getSystemService(String)} to access * {@link android.view.displayhash.DisplayHashManager} to handle display hashes. * * @see #getSystemService(String) */ public static final String DISPLAY_HASH_SERVICE = "display_hash"; /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. Loading core/java/android/service/screenshot/ScreenshotHasherService.java→core/java/android/service/displayhash/DisplayHasherService.java +168 −0 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package android.service.screenshot; package android.service.displayhash; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; Loading @@ -30,24 +30,24 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteCallback; import android.view.displayhash.DisplayHash; import android.view.displayhash.DisplayHashResultCallback; import android.view.displayhash.VerifiedDisplayHash; /** * A service that handles generating and verify {@link ScreenshotHash}. * A service that handles generating and verify {@link DisplayHash}. * * The service will generate a ScreenshotHash based on arguments passed in. Then later that * same ScreenshotHash can be verified to determine that it was created by the system. * The service will generate a DisplayHash based on arguments passed in. Then later that * same DisplayHash can be verified to determine that it was created by the system. * * @hide */ @SystemApi public abstract class ScreenshotHasherService extends Service { /** @hide **/ public static final String EXTRA_SCREENSHOT_HASH = "android.service.screenshot.extra.SCREENSHOT_HASH"; public abstract class DisplayHasherService extends Service { /** @hide **/ public static final String EXTRA_VERIFICATION_STATUS = "android.service.screenshot.extra.VERIFICATION_STATUS"; 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 Loading @@ -56,28 +56,28 @@ public abstract class ScreenshotHasherService extends Service { * @hide */ public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.screenshot.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 ScreenshotHash providing service. * for the system to recognize it as a DisplayHash providing service. * * @hide */ @SystemApi public static final String SERVICE_INTERFACE = "android.service.screenshot.ScreenshotHasherService"; "android.service.displayhash.DisplayHasherService"; private ScreenshotHasherServiceWrapper mWrapper; private DisplayHasherServiceWrapper mWrapper; private Handler mHandler; public ScreenshotHasherService() { public DisplayHasherService() { } @Override public void onCreate() { super.onCreate(); mWrapper = new ScreenshotHasherServiceWrapper(); mWrapper = new DisplayHasherServiceWrapper(); mHandler = new Handler(Looper.getMainLooper(), null, true); } Loading @@ -88,73 +88,81 @@ public abstract class ScreenshotHasherService extends Service { } /** * Generates the ScreenshotHash that can be used to validate that the system generated the * Generates the DisplayHash that can be used to validate that the system generated the * token. * * @param salt The salt to use when generating the hmac. This should be unique to the * caller so the token cannot be verified by any other process. * @param screenshot The screenshot buffer for the content. * @param bounds The size and position of the content being screenshot in the window. * @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)}. * @return A ScreenshotHash that can be used to validate information about the content. * Returns null when the arguments sent are invalid. * @param callback The callback to invoke * {@link DisplayHashResultCallback#onDisplayHashResult(DisplayHash)} * if successfully generated a DisplayHash or {@link * DisplayHashResultCallback#onDisplayHashError(int)} if failed. */ @Nullable public abstract ScreenshotHash onGenerateScreenshotHash(@NonNull byte[] salt, @NonNull HardwareBuffer screenshot, @NonNull Rect bounds, @NonNull String hashAlgorithm); public abstract void onGenerateDisplayHash(@NonNull byte[] salt, @NonNull HardwareBuffer buffer, @NonNull Rect bounds, @NonNull String hashAlgorithm, @NonNull DisplayHashResultCallback callback); /** * Call to verify that the ScreenshotHash passed in was generated by the system. * Call to verify that the DisplayHash passed in was generated by the system. * * @param salt The salt value to use when verifying the hmac. This should be the * same value that was passed to * {@link #onGenerateScreenshotHash(byte[], * HardwareBuffer, Rect, String)} to * {@link #onGenerateDisplayHash(byte[], * HardwareBuffer, Rect, String, DisplayHashResultCallback)} to * generate the token. * @param screenshotHash The token to verify that it was generated by the system. * @return true if the token can be verified that it was generated by the system. * @param displayHash The token to verify that it was generated by the system. * @return a {@link VerifiedDisplayHash} if the token was generated by the system or null * if the token cannot be verified. */ public abstract boolean onVerifyScreenshotHash(@NonNull byte[] salt, @NonNull ScreenshotHash screenshotHash); private void generateScreenshotHash(byte[] salt, HardwareBuffer screenshot, Rect bounds, String hashAlgorithm, RemoteCallback callback) { ScreenshotHash screenshotHash = onGenerateScreenshotHash(salt, screenshot, bounds, hashAlgorithm); final Bundle data = new Bundle(); data.putParcelable(EXTRA_SCREENSHOT_HASH, screenshotHash); callback.sendResult(data); } @Nullable public abstract VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[] salt, @NonNull DisplayHash displayHash); private void verifyScreenshotHash(byte[] salt, ScreenshotHash screenshotHash, private void verifyDisplayHash(byte[] salt, DisplayHash displayHash, RemoteCallback callback) { boolean verificationStatus = onVerifyScreenshotHash(salt, screenshotHash); VerifiedDisplayHash verifiedDisplayHash = onVerifyDisplayHash(salt, displayHash); final Bundle data = new Bundle(); data.putBoolean(EXTRA_VERIFICATION_STATUS, verificationStatus); data.putParcelable(EXTRA_VERIFIED_DISPLAY_HASH, verifiedDisplayHash); callback.sendResult(data); } private final class ScreenshotHasherServiceWrapper extends IScreenshotHasherService.Stub { private final class DisplayHasherServiceWrapper extends IDisplayHasherService.Stub { @Override public void generateScreenshotHash(byte[] salt, HardwareBuffer screenshot, Rect bounds, public void generateDisplayHash(byte[] salt, HardwareBuffer buffer, Rect bounds, String hashAlgorithm, RemoteCallback callback) { mHandler.sendMessage( obtainMessage(ScreenshotHasherService::generateScreenshotHash, ScreenshotHasherService.this, salt, screenshot, bounds, hashAlgorithm, callback)); obtainMessage(DisplayHasherService::onGenerateDisplayHash, DisplayHasherService.this, salt, buffer, bounds, hashAlgorithm, new DisplayHashResultCallback() { @Override public void onDisplayHashResult( @NonNull DisplayHash displayHash) { Bundle result = new Bundle(); result.putParcelable(EXTRA_DISPLAY_HASH, displayHash); callback.sendResult(result); } @Override public void onDisplayHashError(int errorCode) { Bundle result = new Bundle(); result.putInt(EXTRA_DISPLAY_HASH_ERROR_CODE, errorCode); callback.sendResult(result); } })); } @Override public void verifyScreenshotHash(byte[] salt, ScreenshotHash screenshotHash, public void verifyDisplayHash(byte[] salt, DisplayHash displayHash, RemoteCallback callback) { mHandler.sendMessage( obtainMessage(ScreenshotHasherService::verifyScreenshotHash, ScreenshotHasherService.this, salt, screenshotHash, callback)); obtainMessage(DisplayHasherService::verifyDisplayHash, DisplayHasherService.this, salt, displayHash, callback)); } } } Loading
core/api/current.txt +37 −0 Original line number Diff line number Diff line Loading @@ -10444,6 +10444,7 @@ package android.content { field public static final int CONTEXT_RESTRICTED = 4; // 0x4 field public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps"; field public static final String DEVICE_POLICY_SERVICE = "device_policy"; field public static final String DISPLAY_HASH_SERVICE = "display_hash"; field public static final String DISPLAY_SERVICE = "display"; field public static final String DOWNLOAD_SERVICE = "download"; field public static final String DROPBOX_SERVICE = "dropbox"; Loading Loading @@ -48235,6 +48236,7 @@ package android.view { method public android.view.View focusSearch(int); method public void forceHasOverlappingRendering(boolean); method public void forceLayout(); method @Nullable public void generateDisplayHash(@NonNull String, @Nullable android.graphics.Rect, @NonNull java.util.concurrent.Executor, @NonNull android.view.displayhash.DisplayHashResultCallback); method public static int generateViewId(); method public CharSequence getAccessibilityClassName(); method public android.view.View.AccessibilityDelegate getAccessibilityDelegate(); Loading Loading @@ -51190,6 +51192,41 @@ package android.view.contentcapture { } package android.view.displayhash { public final class DisplayHash implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.displayhash.DisplayHash> CREATOR; } public final class DisplayHashManager { method @NonNull public java.util.Set<java.lang.String> getSupportedHashAlgorithms(); method @Nullable public android.view.displayhash.VerifiedDisplayHash verifyDisplayHash(@NonNull android.view.displayhash.DisplayHash); } public interface DisplayHashResultCallback { method public void onDisplayHashError(int); method public void onDisplayHashResult(@NonNull android.view.displayhash.DisplayHash); field public static final int DISPLAY_HASH_ERROR_INVALID_BOUNDS = -2; // 0xfffffffe field public static final int DISPLAY_HASH_ERROR_MISSING_WINDOW = -3; // 0xfffffffd field public static final int DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN = -4; // 0xfffffffc field public static final int DISPLAY_HASH_ERROR_UNKNOWN = -1; // 0xffffffff } public final class VerifiedDisplayHash implements android.os.Parcelable { ctor public VerifiedDisplayHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[]); method public int describeContents(); method @NonNull public android.graphics.Rect getBoundsInWindow(); method @NonNull public String getHashAlgorithm(); method @NonNull public byte[] getImageHash(); method public long getTimeMillis(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.displayhash.VerifiedDisplayHash> CREATOR; } } package android.view.inputmethod { public class BaseInputConnection implements android.view.inputmethod.InputConnection {
core/api/system-current.txt +27 −24 Original line number Diff line number Diff line Loading @@ -9984,6 +9984,18 @@ package android.service.dataloader { } package android.service.displayhash { 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 @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"; } } package android.service.euicc { public final class DownloadSubscriptionResult implements android.os.Parcelable { Loading Loading @@ -10344,30 +10356,6 @@ package android.service.rotationresolver { } package android.service.screenshot { public final class ScreenshotHash implements android.os.Parcelable { ctor public ScreenshotHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[], @NonNull byte[]); method public int describeContents(); method @NonNull public android.graphics.Rect getBoundsInWindow(); method @NonNull public String getHashingAlgorithm(); method @NonNull public byte[] getHmac(); method @NonNull public byte[] getImageHash(); method public long getScreenshotTimeMillis(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.service.screenshot.ScreenshotHash> CREATOR; } public abstract class ScreenshotHasherService extends android.app.Service { ctor public ScreenshotHasherService(); method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method @Nullable public abstract android.service.screenshot.ScreenshotHash onGenerateScreenshotHash(@NonNull byte[], @NonNull android.hardware.HardwareBuffer, @NonNull android.graphics.Rect, @NonNull String); method public abstract boolean onVerifyScreenshotHash(@NonNull byte[], @NonNull android.service.screenshot.ScreenshotHash); field public static final String SERVICE_INTERFACE = "android.service.screenshot.ScreenshotHasherService"; } } package android.service.search { public abstract class SearchUiService extends android.app.Service { Loading Loading @@ -14399,6 +14387,21 @@ package android.view.contentcapture { } package android.view.displayhash { public final class DisplayHash implements android.os.Parcelable { ctor public DisplayHash(long, @NonNull android.graphics.Rect, @NonNull String, @NonNull byte[], @NonNull byte[]); method public int describeContents(); method @NonNull public android.graphics.Rect getBoundsInWindow(); method @NonNull public String getHashAlgorithm(); method @NonNull public byte[] getHmac(); method @NonNull public byte[] getImageHash(); method public long getTimeMillis(); method public void writeToParcel(@NonNull android.os.Parcel, int); } } package android.view.translation { public final class UiTranslationManager {
core/java/android/app/SystemServiceRegistry.java +8 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,7 @@ import android.view.autofill.AutofillManager; import android.view.autofill.IAutoFillManager; import android.view.contentcapture.ContentCaptureManager; import android.view.contentcapture.IContentCaptureManager; import android.view.displayhash.DisplayHashManager; import android.view.inputmethod.InputMethodManager; import android.view.textclassifier.TextClassificationManager; import android.view.textservice.TextServicesManager; Loading Loading @@ -1426,6 +1427,13 @@ public final class SystemServiceRegistry { } }); registerService(Context.DISPLAY_HASH_SERVICE, DisplayHashManager.class, new CachedServiceFetcher<DisplayHashManager>() { @Override public DisplayHashManager createService(ContextImpl ctx) { return new DisplayHashManager(); }}); sInitializing = true; try { // Note: the following functions need to be @SystemApis, once they become mainline Loading
core/java/android/content/Context.java +8 −0 Original line number Diff line number Diff line Loading @@ -5490,6 +5490,14 @@ public abstract class Context { @SystemApi public static final String DOMAIN_VERIFICATION_SERVICE = "domain_verification"; /** * Use with {@link #getSystemService(String)} to access * {@link android.view.displayhash.DisplayHashManager} to handle display hashes. * * @see #getSystemService(String) */ public static final String DISPLAY_HASH_SERVICE = "display_hash"; /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. Loading
core/java/android/service/screenshot/ScreenshotHasherService.java→core/java/android/service/displayhash/DisplayHasherService.java +168 −0 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ package android.service.screenshot; package android.service.displayhash; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; Loading @@ -30,24 +30,24 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteCallback; import android.view.displayhash.DisplayHash; import android.view.displayhash.DisplayHashResultCallback; import android.view.displayhash.VerifiedDisplayHash; /** * A service that handles generating and verify {@link ScreenshotHash}. * A service that handles generating and verify {@link DisplayHash}. * * The service will generate a ScreenshotHash based on arguments passed in. Then later that * same ScreenshotHash can be verified to determine that it was created by the system. * The service will generate a DisplayHash based on arguments passed in. Then later that * same DisplayHash can be verified to determine that it was created by the system. * * @hide */ @SystemApi public abstract class ScreenshotHasherService extends Service { /** @hide **/ public static final String EXTRA_SCREENSHOT_HASH = "android.service.screenshot.extra.SCREENSHOT_HASH"; public abstract class DisplayHasherService extends Service { /** @hide **/ public static final String EXTRA_VERIFICATION_STATUS = "android.service.screenshot.extra.VERIFICATION_STATUS"; 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 Loading @@ -56,28 +56,28 @@ public abstract class ScreenshotHasherService extends Service { * @hide */ public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.screenshot.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 ScreenshotHash providing service. * for the system to recognize it as a DisplayHash providing service. * * @hide */ @SystemApi public static final String SERVICE_INTERFACE = "android.service.screenshot.ScreenshotHasherService"; "android.service.displayhash.DisplayHasherService"; private ScreenshotHasherServiceWrapper mWrapper; private DisplayHasherServiceWrapper mWrapper; private Handler mHandler; public ScreenshotHasherService() { public DisplayHasherService() { } @Override public void onCreate() { super.onCreate(); mWrapper = new ScreenshotHasherServiceWrapper(); mWrapper = new DisplayHasherServiceWrapper(); mHandler = new Handler(Looper.getMainLooper(), null, true); } Loading @@ -88,73 +88,81 @@ public abstract class ScreenshotHasherService extends Service { } /** * Generates the ScreenshotHash that can be used to validate that the system generated the * Generates the DisplayHash that can be used to validate that the system generated the * token. * * @param salt The salt to use when generating the hmac. This should be unique to the * caller so the token cannot be verified by any other process. * @param screenshot The screenshot buffer for the content. * @param bounds The size and position of the content being screenshot in the window. * @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)}. * @return A ScreenshotHash that can be used to validate information about the content. * Returns null when the arguments sent are invalid. * @param callback The callback to invoke * {@link DisplayHashResultCallback#onDisplayHashResult(DisplayHash)} * if successfully generated a DisplayHash or {@link * DisplayHashResultCallback#onDisplayHashError(int)} if failed. */ @Nullable public abstract ScreenshotHash onGenerateScreenshotHash(@NonNull byte[] salt, @NonNull HardwareBuffer screenshot, @NonNull Rect bounds, @NonNull String hashAlgorithm); public abstract void onGenerateDisplayHash(@NonNull byte[] salt, @NonNull HardwareBuffer buffer, @NonNull Rect bounds, @NonNull String hashAlgorithm, @NonNull DisplayHashResultCallback callback); /** * Call to verify that the ScreenshotHash passed in was generated by the system. * Call to verify that the DisplayHash passed in was generated by the system. * * @param salt The salt value to use when verifying the hmac. This should be the * same value that was passed to * {@link #onGenerateScreenshotHash(byte[], * HardwareBuffer, Rect, String)} to * {@link #onGenerateDisplayHash(byte[], * HardwareBuffer, Rect, String, DisplayHashResultCallback)} to * generate the token. * @param screenshotHash The token to verify that it was generated by the system. * @return true if the token can be verified that it was generated by the system. * @param displayHash The token to verify that it was generated by the system. * @return a {@link VerifiedDisplayHash} if the token was generated by the system or null * if the token cannot be verified. */ public abstract boolean onVerifyScreenshotHash(@NonNull byte[] salt, @NonNull ScreenshotHash screenshotHash); private void generateScreenshotHash(byte[] salt, HardwareBuffer screenshot, Rect bounds, String hashAlgorithm, RemoteCallback callback) { ScreenshotHash screenshotHash = onGenerateScreenshotHash(salt, screenshot, bounds, hashAlgorithm); final Bundle data = new Bundle(); data.putParcelable(EXTRA_SCREENSHOT_HASH, screenshotHash); callback.sendResult(data); } @Nullable public abstract VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[] salt, @NonNull DisplayHash displayHash); private void verifyScreenshotHash(byte[] salt, ScreenshotHash screenshotHash, private void verifyDisplayHash(byte[] salt, DisplayHash displayHash, RemoteCallback callback) { boolean verificationStatus = onVerifyScreenshotHash(salt, screenshotHash); VerifiedDisplayHash verifiedDisplayHash = onVerifyDisplayHash(salt, displayHash); final Bundle data = new Bundle(); data.putBoolean(EXTRA_VERIFICATION_STATUS, verificationStatus); data.putParcelable(EXTRA_VERIFIED_DISPLAY_HASH, verifiedDisplayHash); callback.sendResult(data); } private final class ScreenshotHasherServiceWrapper extends IScreenshotHasherService.Stub { private final class DisplayHasherServiceWrapper extends IDisplayHasherService.Stub { @Override public void generateScreenshotHash(byte[] salt, HardwareBuffer screenshot, Rect bounds, public void generateDisplayHash(byte[] salt, HardwareBuffer buffer, Rect bounds, String hashAlgorithm, RemoteCallback callback) { mHandler.sendMessage( obtainMessage(ScreenshotHasherService::generateScreenshotHash, ScreenshotHasherService.this, salt, screenshot, bounds, hashAlgorithm, callback)); obtainMessage(DisplayHasherService::onGenerateDisplayHash, DisplayHasherService.this, salt, buffer, bounds, hashAlgorithm, new DisplayHashResultCallback() { @Override public void onDisplayHashResult( @NonNull DisplayHash displayHash) { Bundle result = new Bundle(); result.putParcelable(EXTRA_DISPLAY_HASH, displayHash); callback.sendResult(result); } @Override public void onDisplayHashError(int errorCode) { Bundle result = new Bundle(); result.putInt(EXTRA_DISPLAY_HASH_ERROR_CODE, errorCode); callback.sendResult(result); } })); } @Override public void verifyScreenshotHash(byte[] salt, ScreenshotHash screenshotHash, public void verifyDisplayHash(byte[] salt, DisplayHash displayHash, RemoteCallback callback) { mHandler.sendMessage( obtainMessage(ScreenshotHasherService::verifyScreenshotHash, ScreenshotHasherService.this, salt, screenshotHash, callback)); obtainMessage(DisplayHasherService::verifyDisplayHash, DisplayHasherService.this, salt, displayHash, callback)); } } }