From b10ab7ddf4f1347a108c59a2e5183482502871fa Mon Sep 17 00:00:00 2001 From: Mark Renouf Date: Wed, 20 Jan 2021 14:20:58 -0500 Subject: [PATCH] ImageExporter: Accept and store UUID as ImageUniqueId in output Write a provided UUID as the ImageUniqueId tag in the Exif metadata. Bug: 177996487 Test: atest ImageExporterTest Change-Id: I150af1bf80e6ead7e78d7d961168a64112994ede --- .../systemui/screenshot/ImageExporter.java | 23 +++++++++++-------- .../screenshot/SaveImageInBackgroundTask.java | 5 ++-- .../screenshot/ScreenshotController.java | 1 + .../screenshot/ScrollCaptureController.java | 4 ++-- .../screenshot/ImageExporterTest.java | 14 ++++++++--- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java index 87e236ceb8941..8fc2830aa4227 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java @@ -47,6 +47,7 @@ import java.time.Duration; import java.time.Instant; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.UUID; import java.util.concurrent.Executor; import javax.inject.Inject; @@ -74,7 +75,7 @@ class ImageExporter { private static final String EXIF_WRITE_EXCEPTION = "ExifInterface threw an exception writing to the file descriptor."; private static final String RESOLVER_UPDATE_ZERO_ROWS = - "Failed to publishEntry. ContentResolver#update reported no rows updated."; + "Failed to publish entry. ContentResolver#update reported no rows updated."; private static final String IMAGE_COMPRESS_RETURNED_FALSE = "Bitmap.compress returned false. (Failure unknown)"; @@ -116,7 +117,7 @@ class ImageExporter { * * @return a listenable future result */ - ListenableFuture export(Executor executor, String requestId, Bitmap bitmap) { + ListenableFuture export(Executor executor, UUID requestId, Bitmap bitmap) { return export(executor, requestId, bitmap, ZonedDateTime.now()); } @@ -128,7 +129,7 @@ class ImageExporter { * * @return a listenable future result */ - ListenableFuture export(Executor executor, String requestId, Bitmap bitmap, + ListenableFuture export(Executor executor, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime) { final Task task = new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat, mQuality); @@ -147,7 +148,7 @@ class ImageExporter { } static class Result { - String requestId; + UUID requestId; String fileName; long timestamp; Uri uri; @@ -156,14 +157,14 @@ class ImageExporter { private static class Task { private final ContentResolver mResolver; - private final String mRequestId; + private final UUID mRequestId; private final Bitmap mBitmap; private final ZonedDateTime mCaptureTime; private final CompressFormat mFormat; private final int mQuality; private final String mFileName; - Task(ContentResolver resolver, String requestId, Bitmap bitmap, ZonedDateTime captureTime, + Task(ContentResolver resolver, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime, CompressFormat format, int quality) { mResolver = resolver; mRequestId = requestId; @@ -191,7 +192,7 @@ class ImageExporter { writeImage(mBitmap, mFormat, mQuality, uri); throwIfInterrupted(); - writeExif(uri, mBitmap.getWidth(), mBitmap.getHeight(), mCaptureTime); + writeExif(uri, mRequestId, mBitmap.getWidth(), mBitmap.getHeight(), mCaptureTime); throwIfInterrupted(); publishEntry(uri); @@ -251,7 +252,7 @@ class ImageExporter { } } - void writeExif(Uri uri, int width, int height, ZonedDateTime captureTime) + void writeExif(Uri uri, UUID requestId, int width, int height, ZonedDateTime captureTime) throws ImageExportException { Trace.beginSection("ImageExporter_writeExif"); ParcelFileDescriptor pfd = null; @@ -267,7 +268,7 @@ class ImageExporter { throw new ImageExportException(EXIF_READ_EXCEPTION, e); } - updateExifAttributes(exif, width, height, captureTime); + updateExifAttributes(exif, requestId, width, height, captureTime); try { exif.saveAttributes(); } catch (IOException e) { @@ -321,8 +322,10 @@ class ImageExporter { return values; } - static void updateExifAttributes(ExifInterface exif, int width, int height, + static void updateExifAttributes(ExifInterface exif, UUID uniqueId, int width, int height, ZonedDateTime captureTime) { + exif.setAttribute(ExifInterface.TAG_IMAGE_UNIQUE_ID, uniqueId.toString()); + exif.setAttribute(ExifInterface.TAG_SOFTWARE, "Android " + Build.DISPLAY); exif.setAttribute(ExifInterface.TAG_IMAGE_WIDTH, Integer.toString(width)); exif.setAttribute(ExifInterface.TAG_IMAGE_LENGTH, Integer.toString(height)); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java index d42847d0afb5e..7f133975abcd0 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java @@ -119,14 +119,13 @@ class SaveImageInBackgroundTask extends AsyncTask { return null; } // TODO: move to constructor / from ScreenshotRequest - final UUID uuid = UUID.randomUUID(); + final UUID requestId = UUID.randomUUID(); final UserHandle user = getUserHandleOfForegroundApplication(mContext); Thread.currentThread().setPriority(Thread.MAX_PRIORITY); Bitmap image = mParams.image; - String requestId = uuid.toString(); - mScreenshotId = String.format(SCREENSHOT_ID_TEMPLATE, uuid); + mScreenshotId = String.format(SCREENSHOT_ID_TEMPLATE, requestId); try { // Call synchronously here since already on a background thread. ListenableFuture future = diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index 7d57799490741..f59c8f1323bca 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -55,6 +55,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.Settings; import android.util.DisplayMetrics; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java index 2ccb2ce0ec487..54b1b2c8c54c2 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java @@ -55,7 +55,7 @@ public class ScrollCaptureController { private final ImageTileSet mImageTileSet; private ZonedDateTime mCaptureTime; - private String mRequestId; + private UUID mRequestId; public ScrollCaptureController(Context context, Connection connection, Executor uiExecutor, Executor bgExecutor, ImageExporter exporter) { @@ -74,7 +74,7 @@ public class ScrollCaptureController { */ public void run(final Runnable after) { mCaptureTime = ZonedDateTime.now(); - mRequestId = UUID.randomUUID().toString(); + mRequestId = UUID.randomUUID(); mConnection.start((session) -> startCapture(session, after)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java index c2a08ba540878..b0f78ad703037 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java @@ -54,6 +54,7 @@ import java.io.InputStream; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -78,10 +79,13 @@ public class ImageExporterTest extends SysuiTestCase { public void testUpdateExifAttributes_timeZoneUTC() throws IOException { ExifInterface exifInterface = new ExifInterface(new ByteArrayInputStream(EXIF_FILE_TAG), ExifInterface.STREAM_TYPE_EXIF_DATA_ONLY); - - ImageExporter.updateExifAttributes(exifInterface, 100, 100, + ImageExporter.updateExifAttributes(exifInterface, + UUID.fromString("3c11da99-9284-4863-b1d5-6f3684976814"), 100, 100, ZonedDateTime.of(LocalDateTime.of(2020, 12, 15, 18, 15), ZoneId.of("UTC"))); + assertEquals("Exif " + ExifInterface.TAG_IMAGE_UNIQUE_ID, + "3c11da99-9284-4863-b1d5-6f3684976814", + exifInterface.getAttribute(ExifInterface.TAG_IMAGE_UNIQUE_ID)); assertEquals("Exif " + ExifInterface.TAG_OFFSET_TIME_ORIGINAL, "+00:00", exifInterface.getAttribute(ExifInterface.TAG_OFFSET_TIME_ORIGINAL)); } @@ -92,7 +96,7 @@ public class ImageExporterTest extends SysuiTestCase { ContentResolver contentResolver = context.getContentResolver(); ImageExporter exporter = new ImageExporter(contentResolver); - String requestId = "some_random_unique_id"; + UUID requestId = UUID.fromString("3c11da99-9284-4863-b1d5-6f3684976814"); Bitmap original = createCheckerBitmap(10, 10, 10); ListenableFuture direct = @@ -120,6 +124,10 @@ public class ImageExporterTest extends SysuiTestCase { assertNotNull(pfd); ExifInterface exifInterface = new ExifInterface(pfd.getFileDescriptor()); + assertEquals("Exif " + ExifInterface.TAG_IMAGE_UNIQUE_ID, + "3c11da99-9284-4863-b1d5-6f3684976814", + exifInterface.getAttribute(ExifInterface.TAG_IMAGE_UNIQUE_ID)); + assertEquals("Exif " + ExifInterface.TAG_SOFTWARE, "Android " + Build.DISPLAY, exifInterface.getAttribute(ExifInterface.TAG_SOFTWARE));