Loading packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java +13 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)"; Loading Loading @@ -116,7 +117,7 @@ class ImageExporter { * * @return a listenable future result */ ListenableFuture<Result> export(Executor executor, String requestId, Bitmap bitmap) { ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap) { return export(executor, requestId, bitmap, ZonedDateTime.now()); } Loading @@ -128,7 +129,7 @@ class ImageExporter { * * @return a listenable future result */ ListenableFuture<Result> export(Executor executor, String requestId, Bitmap bitmap, ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime) { final Task task = new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat, mQuality); Loading @@ -147,7 +148,7 @@ class ImageExporter { } static class Result { String requestId; UUID requestId; String fileName; long timestamp; Uri uri; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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)); Loading packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java +2 −3 Original line number Diff line number Diff line Loading @@ -119,14 +119,13 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { 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<ImageExporter.Result> future = Loading packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +2 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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)); } Loading packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java +11 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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)); } Loading @@ -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<ImageExporter.Result> direct = Loading Loading @@ -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)); Loading Loading
packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java +13 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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)"; Loading Loading @@ -116,7 +117,7 @@ class ImageExporter { * * @return a listenable future result */ ListenableFuture<Result> export(Executor executor, String requestId, Bitmap bitmap) { ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap) { return export(executor, requestId, bitmap, ZonedDateTime.now()); } Loading @@ -128,7 +129,7 @@ class ImageExporter { * * @return a listenable future result */ ListenableFuture<Result> export(Executor executor, String requestId, Bitmap bitmap, ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime) { final Task task = new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat, mQuality); Loading @@ -147,7 +148,7 @@ class ImageExporter { } static class Result { String requestId; UUID requestId; String fileName; long timestamp; Uri uri; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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)); Loading
packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java +2 −3 Original line number Diff line number Diff line Loading @@ -119,14 +119,13 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { 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<ImageExporter.Result> future = Loading
packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +2 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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)); } Loading
packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java +11 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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)); } Loading @@ -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<ImageExporter.Result> direct = Loading Loading @@ -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)); Loading