Loading packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +340 −335 Original line number Diff line number Diff line Loading @@ -21,9 +21,6 @@ import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_CORNER_FLOW; import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT; import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION; import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP; import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT; import android.animation.Animator; Loading Loading @@ -112,19 +109,25 @@ import javax.inject.Singleton; import dagger.Lazy; /** * Class for handling device screen shots */ @Singleton public class GlobalScreenshot { /** * POD used in the AsyncTask which saves an image in the background. */ class SaveImageInBackgroundData { Context context; Bitmap image; Uri imageUri; Runnable finisher; Function<PendingIntent, Void> onEditReady; int iconSize; int previewWidth; int previewheight; int errorMsgResId; private static class SaveImageInBackgroundData { public Context context; public Bitmap image; public Uri imageUri; public Runnable finisher; public Function<PendingIntent, Void> onEditReady; public int iconSize; public int previewWidth; public int previewheight; public int errorMsgResId; void clearImage() { image = null; Loading @@ -139,7 +142,7 @@ class SaveImageInBackgroundData { /** * An AsyncTask that saves an image to the media store in the background. */ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { private static class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { private static final String TAG = "SaveImageInBackgroundTask"; private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png"; Loading Loading @@ -178,9 +181,10 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { Matrix matrix = new Matrix(); int overlayColor = 0x40FFFFFF; matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2); Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight, matrix, paint, overlayColor); matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2); Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight, matrix, paint, overlayColor); // Note, we can't use the preview for the small icon, since it is non-square float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight); Loading Loading @@ -215,7 +219,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { .setSmallIcon(R.drawable.stat_notify_image) .setWhen(now) .setShowWhen(true) .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color)) .setColor(r.getColor( com.android.internal.R.color.system_notification_accent_color)) .setStyle(mNotificationStyle) .setPublicVersion(mPublicNotificationBuilder.build()); mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true); Loading @@ -225,21 +230,21 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { mNotificationBuilder.build()); /** * NOTE: The following code prepares the notification builder for updating the notification * after the screenshot has been written to disk. * NOTE: The following code prepares the notification builder for updating the * notification after the screenshot has been written to disk. */ // On the tablet, the large icon makes the notification appear as if it is clickable (and // on small devices, the large icon is not shown) so defer showing the large icon until // we compose the final post-save notification below. // On the tablet, the large icon makes the notification appear as if it is clickable // (and on small devices, the large icon is not shown) so defer showing the large icon // until we compose the final post-save notification below. mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap()); // But we still don't set it for the expanded view, allowing the smallIcon to show here. mNotificationStyle.bigLargeIcon((Bitmap) null); } /** * Generates a new hardware bitmap with specified values, copying the content from the passed * in bitmap. * Generates a new hardware bitmap with specified values, copying the content from the * passed in bitmap. */ private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix, Paint paint, int color) { Loading @@ -257,8 +262,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { return null; } // By default, AsyncTask sets the worker thread to have background thread priority, so bump // it back up so that we save a little quicker. // By default, AsyncTask sets the worker thread to have background thread priority, // so bump it back up so that we save a little quicker. Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); Context context = mParams.context; Loading Loading @@ -292,8 +297,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { // order to do some common work like dismissing the keyguard and sending // closeSystemWindows // Create a share intent, this will always go through the chooser activity first which // should not trigger auto-enter PiP // Create a share intent, this will always go through the chooser activity first // which should not trigger auto-enter PiP String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime)); String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate); Intent sharingIntent = new Intent(Intent.ACTION_SEND); Loading Loading @@ -332,8 +337,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { r.getString(com.android.internal.R.string.share), shareAction); mNotificationBuilder.addAction(shareActionBuilder.build()); // Create an edit intent, if a specific package is provided as the editor, then launch // that directly // Create an edit intent, if a specific package is provided as the editor, then // launch that directly String editorPackage = context.getString(R.string.config_screenshotEditor); Intent editIntent = new Intent(Intent.ACTION_EDIT); if (!TextUtils.isEmpty(editorPackage)) { Loading @@ -348,7 +353,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode, new Intent(context, GlobalScreenshot.ActionProxyReceiver.class) .putExtra(EXTRA_ACTION_INTENT, editIntent) .putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null) .putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null) .setAction(Intent.ACTION_EDIT), PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM); Notification.Action.Builder editActionBuilder = new Notification.Action.Builder( Loading @@ -373,8 +379,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { mParams.image = null; mParams.errorMsgResId = 0; } catch (Exception e) { // IOException/UnsupportedOperationException may be thrown if external storage is not // mounted // IOException/UnsupportedOperationException may be thrown if external storage is // not mounted Slog.e(TAG, "unable to save screenshot", e); mParams.clearImage(); mParams.errorMsgResId = R.string.screenshot_failed_to_save_text; Loading Loading @@ -424,7 +430,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { mNotificationBuilder .setContentTitle(r.getString(R.string.screenshot_saved_title)) .setContentText(r.getString(R.string.screenshot_saved_text)) .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0)) .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0)) .setWhen(now) .setAutoCancel(true) .setColor(context.getColor( Loading @@ -442,9 +449,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { @Override protected void onCancelled(Void params) { // If we are cancelled while the task is running in the background, we may get null params. // The finisher is expected to always be called back, so just use the baked-in params from // the ctor in any case. // If we are cancelled while the task is running in the background, we may get null // params. The finisher is expected to always be called back, so just use the baked-in // params from the ctor in any case. mParams.finisher.run(); mParams.clearImage(); mParams.clearContext(); Loading @@ -457,7 +464,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { /** * An AsyncTask that deletes an image from the media store in the background. */ class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> { private static class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> { private Context mContext; DeleteImageInBackgroundTask(Context context) { Loading @@ -475,8 +482,6 @@ class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> { } } @Singleton public class GlobalScreenshot { static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id"; static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent"; static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification"; Loading Loading
packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +340 −335 Original line number Diff line number Diff line Loading @@ -21,9 +21,6 @@ import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_CORNER_FLOW; import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT; import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION; import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP; import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT; import android.animation.Animator; Loading Loading @@ -112,19 +109,25 @@ import javax.inject.Singleton; import dagger.Lazy; /** * Class for handling device screen shots */ @Singleton public class GlobalScreenshot { /** * POD used in the AsyncTask which saves an image in the background. */ class SaveImageInBackgroundData { Context context; Bitmap image; Uri imageUri; Runnable finisher; Function<PendingIntent, Void> onEditReady; int iconSize; int previewWidth; int previewheight; int errorMsgResId; private static class SaveImageInBackgroundData { public Context context; public Bitmap image; public Uri imageUri; public Runnable finisher; public Function<PendingIntent, Void> onEditReady; public int iconSize; public int previewWidth; public int previewheight; public int errorMsgResId; void clearImage() { image = null; Loading @@ -139,7 +142,7 @@ class SaveImageInBackgroundData { /** * An AsyncTask that saves an image to the media store in the background. */ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { private static class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { private static final String TAG = "SaveImageInBackgroundTask"; private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png"; Loading Loading @@ -178,9 +181,10 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { Matrix matrix = new Matrix(); int overlayColor = 0x40FFFFFF; matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2); Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight, matrix, paint, overlayColor); matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2); Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight, matrix, paint, overlayColor); // Note, we can't use the preview for the small icon, since it is non-square float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight); Loading Loading @@ -215,7 +219,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { .setSmallIcon(R.drawable.stat_notify_image) .setWhen(now) .setShowWhen(true) .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color)) .setColor(r.getColor( com.android.internal.R.color.system_notification_accent_color)) .setStyle(mNotificationStyle) .setPublicVersion(mPublicNotificationBuilder.build()); mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true); Loading @@ -225,21 +230,21 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { mNotificationBuilder.build()); /** * NOTE: The following code prepares the notification builder for updating the notification * after the screenshot has been written to disk. * NOTE: The following code prepares the notification builder for updating the * notification after the screenshot has been written to disk. */ // On the tablet, the large icon makes the notification appear as if it is clickable (and // on small devices, the large icon is not shown) so defer showing the large icon until // we compose the final post-save notification below. // On the tablet, the large icon makes the notification appear as if it is clickable // (and on small devices, the large icon is not shown) so defer showing the large icon // until we compose the final post-save notification below. mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap()); // But we still don't set it for the expanded view, allowing the smallIcon to show here. mNotificationStyle.bigLargeIcon((Bitmap) null); } /** * Generates a new hardware bitmap with specified values, copying the content from the passed * in bitmap. * Generates a new hardware bitmap with specified values, copying the content from the * passed in bitmap. */ private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix, Paint paint, int color) { Loading @@ -257,8 +262,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { return null; } // By default, AsyncTask sets the worker thread to have background thread priority, so bump // it back up so that we save a little quicker. // By default, AsyncTask sets the worker thread to have background thread priority, // so bump it back up so that we save a little quicker. Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); Context context = mParams.context; Loading Loading @@ -292,8 +297,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { // order to do some common work like dismissing the keyguard and sending // closeSystemWindows // Create a share intent, this will always go through the chooser activity first which // should not trigger auto-enter PiP // Create a share intent, this will always go through the chooser activity first // which should not trigger auto-enter PiP String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime)); String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate); Intent sharingIntent = new Intent(Intent.ACTION_SEND); Loading Loading @@ -332,8 +337,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { r.getString(com.android.internal.R.string.share), shareAction); mNotificationBuilder.addAction(shareActionBuilder.build()); // Create an edit intent, if a specific package is provided as the editor, then launch // that directly // Create an edit intent, if a specific package is provided as the editor, then // launch that directly String editorPackage = context.getString(R.string.config_screenshotEditor); Intent editIntent = new Intent(Intent.ACTION_EDIT); if (!TextUtils.isEmpty(editorPackage)) { Loading @@ -348,7 +353,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode, new Intent(context, GlobalScreenshot.ActionProxyReceiver.class) .putExtra(EXTRA_ACTION_INTENT, editIntent) .putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null) .putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null) .setAction(Intent.ACTION_EDIT), PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM); Notification.Action.Builder editActionBuilder = new Notification.Action.Builder( Loading @@ -373,8 +379,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { mParams.image = null; mParams.errorMsgResId = 0; } catch (Exception e) { // IOException/UnsupportedOperationException may be thrown if external storage is not // mounted // IOException/UnsupportedOperationException may be thrown if external storage is // not mounted Slog.e(TAG, "unable to save screenshot", e); mParams.clearImage(); mParams.errorMsgResId = R.string.screenshot_failed_to_save_text; Loading Loading @@ -424,7 +430,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { mNotificationBuilder .setContentTitle(r.getString(R.string.screenshot_saved_title)) .setContentText(r.getString(R.string.screenshot_saved_text)) .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0)) .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0)) .setWhen(now) .setAutoCancel(true) .setColor(context.getColor( Loading @@ -442,9 +449,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { @Override protected void onCancelled(Void params) { // If we are cancelled while the task is running in the background, we may get null params. // The finisher is expected to always be called back, so just use the baked-in params from // the ctor in any case. // If we are cancelled while the task is running in the background, we may get null // params. The finisher is expected to always be called back, so just use the baked-in // params from the ctor in any case. mParams.finisher.run(); mParams.clearImage(); mParams.clearContext(); Loading @@ -457,7 +464,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { /** * An AsyncTask that deletes an image from the media store in the background. */ class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> { private static class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> { private Context mContext; DeleteImageInBackgroundTask(Context context) { Loading @@ -475,8 +482,6 @@ class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> { } } @Singleton public class GlobalScreenshot { static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id"; static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent"; static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification"; Loading