Merge "Manually recycling bitmap memory when rotating ss, resetting canvas bitmap, adding logging. (Bug 7974275)"
This commit is contained in:
@@ -45,6 +45,7 @@ import android.os.Environment;
|
|||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
@@ -86,6 +87,8 @@ class SaveImageInBackgroundData {
|
|||||||
*/
|
*/
|
||||||
class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
|
class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
|
||||||
SaveImageInBackgroundData> {
|
SaveImageInBackgroundData> {
|
||||||
|
private static final String TAG = "SaveImageInBackgroundTask";
|
||||||
|
|
||||||
private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
|
private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
|
||||||
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
|
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
|
||||||
private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
|
private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
|
||||||
@@ -138,6 +141,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
|
|||||||
(shortSide - mImageHeight) / 2);
|
(shortSide - mImageHeight) / 2);
|
||||||
c.drawBitmap(data.image, matrix, paint);
|
c.drawBitmap(data.image, matrix, paint);
|
||||||
c.drawColor(0x40FFFFFF);
|
c.drawColor(0x40FFFFFF);
|
||||||
|
c.setBitmap(null);
|
||||||
|
|
||||||
Bitmap croppedIcon = Bitmap.createScaledBitmap(preview, iconSize, iconSize, true);
|
Bitmap croppedIcon = Bitmap.createScaledBitmap(preview, iconSize, iconSize, true);
|
||||||
|
|
||||||
@@ -167,6 +171,8 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
|
|||||||
mNotificationBuilder.setLargeIcon(croppedIcon);
|
mNotificationBuilder.setLargeIcon(croppedIcon);
|
||||||
// But we still don't set it for the expanded view, allowing the smallIcon to show here.
|
// But we still don't set it for the expanded view, allowing the smallIcon to show here.
|
||||||
mNotificationStyle.bigLargeIcon(null);
|
mNotificationStyle.bigLargeIcon(null);
|
||||||
|
|
||||||
|
Log.d(TAG, "SaveImageInBackgroundTask constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -174,6 +180,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
|
|||||||
if (params.length != 1) return null;
|
if (params.length != 1) return null;
|
||||||
if (isCancelled()) {
|
if (isCancelled()) {
|
||||||
params[0].clearImage();
|
params[0].clearImage();
|
||||||
|
Log.d(TAG, "doInBackground cancelled");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,6 +245,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
|
|||||||
// mounted
|
// mounted
|
||||||
params[0].clearImage();
|
params[0].clearImage();
|
||||||
params[0].result = 1;
|
params[0].result = 1;
|
||||||
|
Log.d(TAG, "doInBackground failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recycle the bitmap data
|
// Recycle the bitmap data
|
||||||
@@ -245,6 +253,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
|
|||||||
image.recycle();
|
image.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "doInBackground complete");
|
||||||
return params[0];
|
return params[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,6 +262,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
|
|||||||
if (isCancelled()) {
|
if (isCancelled()) {
|
||||||
params.finisher.run();
|
params.finisher.run();
|
||||||
params.clearImage();
|
params.clearImage();
|
||||||
|
Log.d(TAG, "onPostExecute cancelled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,6 +290,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
|
|||||||
mNotificationManager.notify(mNotificationId, n);
|
mNotificationManager.notify(mNotificationId, n);
|
||||||
}
|
}
|
||||||
params.finisher.run();
|
params.finisher.run();
|
||||||
|
Log.d(TAG, "onPostExecute complete");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,6 +301,8 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
|
|||||||
* type of gallery?
|
* type of gallery?
|
||||||
*/
|
*/
|
||||||
class GlobalScreenshot {
|
class GlobalScreenshot {
|
||||||
|
private static final String TAG = "GlobalScreenshot";
|
||||||
|
|
||||||
private static final int SCREENSHOT_NOTIFICATION_ID = 789;
|
private static final int SCREENSHOT_NOTIFICATION_ID = 789;
|
||||||
private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
|
private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
|
||||||
private static final int SCREENSHOT_DROP_IN_DURATION = 430;
|
private static final int SCREENSHOT_DROP_IN_DURATION = 430;
|
||||||
@@ -381,12 +394,15 @@ class GlobalScreenshot {
|
|||||||
// Setup the Camera shutter sound
|
// Setup the Camera shutter sound
|
||||||
mCameraSound = new MediaActionSound();
|
mCameraSound = new MediaActionSound();
|
||||||
mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
|
mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
|
||||||
|
|
||||||
|
Log.d(TAG, "GlobalScreenshot constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new worker thread and saves the screenshot to the media store.
|
* Creates a new worker thread and saves the screenshot to the media store.
|
||||||
*/
|
*/
|
||||||
private void saveScreenshotInWorkerThread(Runnable finisher) {
|
private void saveScreenshotInWorkerThread(Runnable finisher) {
|
||||||
|
Log.d(TAG, "saveScreenshotInWorkerThread");
|
||||||
SaveImageInBackgroundData data = new SaveImageInBackgroundData();
|
SaveImageInBackgroundData data = new SaveImageInBackgroundData();
|
||||||
data.context = mContext;
|
data.context = mContext;
|
||||||
data.image = mScreenBitmap;
|
data.image = mScreenBitmap;
|
||||||
@@ -394,6 +410,7 @@ class GlobalScreenshot {
|
|||||||
data.finisher = finisher;
|
data.finisher = finisher;
|
||||||
if (mSaveInBgTask != null) {
|
if (mSaveInBgTask != null) {
|
||||||
mSaveInBgTask.cancel(false);
|
mSaveInBgTask.cancel(false);
|
||||||
|
Log.d(TAG, "saveScreenshotInWorkerThread cancel");
|
||||||
}
|
}
|
||||||
mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
|
mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
|
||||||
SCREENSHOT_NOTIFICATION_ID).execute(data);
|
SCREENSHOT_NOTIFICATION_ID).execute(data);
|
||||||
@@ -418,6 +435,8 @@ class GlobalScreenshot {
|
|||||||
* Takes a screenshot of the current display and shows an animation.
|
* Takes a screenshot of the current display and shows an animation.
|
||||||
*/
|
*/
|
||||||
void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
|
void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
|
||||||
|
Log.d(TAG, "takeScreenshot");
|
||||||
|
|
||||||
// We need to orient the screenshot correctly (and the Surface api seems to take screenshots
|
// We need to orient the screenshot correctly (and the Surface api seems to take screenshots
|
||||||
// only in the natural orientation of the device :!)
|
// only in the natural orientation of the device :!)
|
||||||
mDisplay.getRealMetrics(mDisplayMetrics);
|
mDisplay.getRealMetrics(mDisplayMetrics);
|
||||||
@@ -431,6 +450,8 @@ class GlobalScreenshot {
|
|||||||
mDisplayMatrix.mapPoints(dims);
|
mDisplayMatrix.mapPoints(dims);
|
||||||
dims[0] = Math.abs(dims[0]);
|
dims[0] = Math.abs(dims[0]);
|
||||||
dims[1] = Math.abs(dims[1]);
|
dims[1] = Math.abs(dims[1]);
|
||||||
|
|
||||||
|
Log.d(TAG, "takeScreenshot requiresRotation");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take the screenshot
|
// Take the screenshot
|
||||||
@@ -438,6 +459,7 @@ class GlobalScreenshot {
|
|||||||
if (mScreenBitmap == null) {
|
if (mScreenBitmap == null) {
|
||||||
notifyScreenshotError(mContext, mNotificationManager);
|
notifyScreenshotError(mContext, mNotificationManager);
|
||||||
finisher.run();
|
finisher.run();
|
||||||
|
Log.d(TAG, "takeScreenshot null bitmap");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +473,10 @@ class GlobalScreenshot {
|
|||||||
c.translate(-dims[0] / 2, -dims[1] / 2);
|
c.translate(-dims[0] / 2, -dims[1] / 2);
|
||||||
c.drawBitmap(mScreenBitmap, 0, 0, null);
|
c.drawBitmap(mScreenBitmap, 0, 0, null);
|
||||||
c.setBitmap(null);
|
c.setBitmap(null);
|
||||||
|
// Recycle the previous bitmap
|
||||||
|
mScreenBitmap.recycle();
|
||||||
mScreenBitmap = ss;
|
mScreenBitmap = ss;
|
||||||
|
Log.d(TAG, "takeScreenshot rotation bitmap created");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimizations
|
// Optimizations
|
||||||
@@ -461,6 +486,7 @@ class GlobalScreenshot {
|
|||||||
// Start the post-screenshot animation
|
// Start the post-screenshot animation
|
||||||
startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
|
startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
|
||||||
statusBarVisible, navBarVisible);
|
statusBarVisible, navBarVisible);
|
||||||
|
Log.d(TAG, "takeScreenshot startedAnimation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -469,6 +495,7 @@ class GlobalScreenshot {
|
|||||||
*/
|
*/
|
||||||
private void startAnimation(final Runnable finisher, int w, int h, boolean statusBarVisible,
|
private void startAnimation(final Runnable finisher, int w, int h, boolean statusBarVisible,
|
||||||
boolean navBarVisible) {
|
boolean navBarVisible) {
|
||||||
|
Log.d(TAG, "startAnimation");
|
||||||
// Add the view for the animation
|
// Add the view for the animation
|
||||||
mScreenshotView.setImageBitmap(mScreenBitmap);
|
mScreenshotView.setImageBitmap(mScreenBitmap);
|
||||||
mScreenshotLayout.requestFocus();
|
mScreenshotLayout.requestFocus();
|
||||||
@@ -477,9 +504,11 @@ class GlobalScreenshot {
|
|||||||
if (mScreenshotAnimation != null) {
|
if (mScreenshotAnimation != null) {
|
||||||
mScreenshotAnimation.end();
|
mScreenshotAnimation.end();
|
||||||
mScreenshotAnimation.removeAllListeners();
|
mScreenshotAnimation.removeAllListeners();
|
||||||
|
Log.d(TAG, "startAnimation reset previous animations");
|
||||||
}
|
}
|
||||||
|
|
||||||
mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
|
mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
|
||||||
|
Log.d(TAG, "startAnimation layout added to WM");
|
||||||
ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
|
ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
|
||||||
ValueAnimator screenshotFadeOutAnim = createScreenshotDropOutAnimation(w, h,
|
ValueAnimator screenshotFadeOutAnim = createScreenshotDropOutAnimation(w, h,
|
||||||
statusBarVisible, navBarVisible);
|
statusBarVisible, navBarVisible);
|
||||||
@@ -495,6 +524,7 @@ class GlobalScreenshot {
|
|||||||
// Clear any references to the bitmap
|
// Clear any references to the bitmap
|
||||||
mScreenBitmap = null;
|
mScreenBitmap = null;
|
||||||
mScreenshotView.setImageBitmap(null);
|
mScreenshotView.setImageBitmap(null);
|
||||||
|
Log.d(TAG, "startAnimation onAnimationEnd");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mScreenshotLayout.post(new Runnable() {
|
mScreenshotLayout.post(new Runnable() {
|
||||||
@@ -506,6 +536,7 @@ class GlobalScreenshot {
|
|||||||
mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||||
mScreenshotView.buildLayer();
|
mScreenshotView.buildLayer();
|
||||||
mScreenshotAnimation.start();
|
mScreenshotAnimation.start();
|
||||||
|
Log.d(TAG, "startAnimation post runnable");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -643,6 +674,7 @@ class GlobalScreenshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void notifyScreenshotError(Context context, NotificationManager nManager) {
|
static void notifyScreenshotError(Context context, NotificationManager nManager) {
|
||||||
|
Log.d(TAG, "notifyScreenshotError");
|
||||||
Resources r = context.getResources();
|
Resources r = context.getResources();
|
||||||
|
|
||||||
// Clear all existing notification, compose the new notification and show it
|
// Clear all existing notification, compose the new notification and show it
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.os.IBinder;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
public class TakeScreenshotService extends Service {
|
public class TakeScreenshotService extends Service {
|
||||||
private static final String TAG = "TakeScreenshotService";
|
private static final String TAG = "TakeScreenshotService";
|
||||||
@@ -37,12 +38,15 @@ public class TakeScreenshotService extends Service {
|
|||||||
final Messenger callback = msg.replyTo;
|
final Messenger callback = msg.replyTo;
|
||||||
if (mScreenshot == null) {
|
if (mScreenshot == null) {
|
||||||
mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
|
mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
|
||||||
|
Log.d(TAG, "Global screenshot initialized");
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "Global screenshot captured");
|
||||||
mScreenshot.takeScreenshot(new Runnable() {
|
mScreenshot.takeScreenshot(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
Message reply = Message.obtain(null, 1);
|
Message reply = Message.obtain(null, 1);
|
||||||
try {
|
try {
|
||||||
callback.send(reply);
|
callback.send(reply);
|
||||||
|
Log.d(TAG, "Global screenshot completed");
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user