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