summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera
diff options
context:
space:
mode:
authorWei-Ta Chen <weita@google.com>2011-07-29 10:06:41 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-07-29 10:06:41 -0700
commit8f530f57261b42080bbda7a57459f1eef8cbaa3d (patch)
treebb52e8acb0d14d2129cae2cfd2172562ce2bf99a /src/com/android/camera
parent766d62f188e324f075583b57f69208614a8eec88 (diff)
parent94f592fc405ca45b8794007cd9083c3250924b50 (diff)
downloadLegacyCamera-8f530f57261b42080bbda7a57459f1eef8cbaa3d.zip
LegacyCamera-8f530f57261b42080bbda7a57459f1eef8cbaa3d.tar.gz
LegacyCamera-8f530f57261b42080bbda7a57459f1eef8cbaa3d.tar.bz2
Merge "Fix memory leaks both in the native and Java side."
Diffstat (limited to 'src/com/android/camera')
-rw-r--r--src/com/android/camera/panorama/CaptureView.java17
-rw-r--r--src/com/android/camera/panorama/MosaicFrameProcessor.java66
-rw-r--r--src/com/android/camera/panorama/PanoramaActivity.java92
-rw-r--r--src/com/android/camera/panorama/Preview.java1
4 files changed, 123 insertions, 53 deletions
diff --git a/src/com/android/camera/panorama/CaptureView.java b/src/com/android/camera/panorama/CaptureView.java
index 3351527..005c2a0 100644
--- a/src/com/android/camera/panorama/CaptureView.java
+++ b/src/com/android/camera/panorama/CaptureView.java
@@ -68,18 +68,29 @@ class CaptureView extends View {
mCanvasBitmap.recycle();
}
Log.v(TAG, "onSizeChanged: W = " + w + ", H = " + h);
- // TODO: 2000x2000 is a temporary setting from SRI's code. Should be fixed once the code is
+ // TODO: 2000x1000 is a temporary setting from SRI's code. Should be fixed once the code is
// refactored.
- mCanvasBitmap = Bitmap.createBitmap(2000, 2000, Bitmap.Config.ARGB_8888);
+ mCanvasBitmap = Bitmap.createBitmap(2000, 1000, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas();
mCanvas.setBitmap(mCanvasBitmap);
mAlphaOriginX = mCanvasBitmap.getWidth() * 0.4f;
mAlphaOriginY = mCanvasBitmap.getHeight() * 0.4f;
}
- public void destroy() {
+ public void onResume() {
+ if (mCanvasBitmap == null) {
+ mCanvasBitmap = Bitmap.createBitmap(2000, 1000, Bitmap.Config.ARGB_8888);
+ mCanvas = new Canvas();
+ mCanvas.setBitmap(mCanvasBitmap);
+ mAlphaOriginX = mCanvasBitmap.getWidth() * 0.4f;
+ mAlphaOriginY = mCanvasBitmap.getHeight() * 0.4f;
+ }
+ }
+
+ public void onPause() {
if (mCanvasBitmap != null) {
mCanvasBitmap.recycle();
+ mCanvasBitmap = null;
}
}
diff --git a/src/com/android/camera/panorama/MosaicFrameProcessor.java b/src/com/android/camera/panorama/MosaicFrameProcessor.java
index 97f5c6f..bbde47e 100644
--- a/src/com/android/camera/panorama/MosaicFrameProcessor.java
+++ b/src/com/android/camera/panorama/MosaicFrameProcessor.java
@@ -58,6 +58,10 @@ public class MosaicFrameProcessor {
private int mTraversedAngleY;
private float mTranslationRate;
+ private int mPreviewWidth;
+ private int mPreviewHeight;
+ private int mPreviewBufferSize;
+
public interface ProgressListener {
public void onProgress(boolean isFinished, float translationRate,
@@ -67,31 +71,62 @@ public class MosaicFrameProcessor {
public MosaicFrameProcessor(int sweepAngle, int previewWidth, int previewHeight, int bufSize) {
mMosaicer = new Mosaic();
- setupMosaicer(previewWidth, previewHeight, bufSize);
- reset();
-
mCompassThreshold = sweepAngle;
-
- int downSizedW = previewWidth / DOWN_SAMPLE_FACTOR;
- int downSizedH = previewHeight / DOWN_SAMPLE_FACTOR;
-
- mColors = new int[downSizedW * downSizedH];
- mLRBitmapAlpha = Bitmap.createBitmap(downSizedW, downSizedH, Config.ARGB_8888);
+ mPreviewWidth = previewWidth;
+ mPreviewHeight = previewHeight;
+ mPreviewBufferSize = bufSize;
}
public void setProgressListener(ProgressListener listener) {
mProgressListener = listener;
}
+ public void onResume() {
+ setupMosaicer(mPreviewWidth, mPreviewHeight, mPreviewBufferSize);
+ setupAlphaBlendBitmap(mPreviewWidth, mPreviewHeight);
+ }
+
+ public void onPause() {
+ releaseMosaicer();
+ releaseAlphaBlendBitmap();
+ }
+
private void setupMosaicer(int previewWidth, int previewHeight, int bufSize) {
Log.v(TAG, "setupMosaicer w, h=" + previewWidth + ',' + previewHeight + ',' + bufSize);
- mMosaicer.setSourceImageDimensions(previewWidth, previewHeight);
-
- mTransformationMatrix = new Matrix();
+ mMosaicer.allocateMosaicMemory(previewWidth, previewHeight);
for (int i = 0; i < NUM_FRAMES_IN_BUFFER; i++) {
mFrames[i] = new byte[bufSize];
}
+
+ mFillIn = 0;
+ if (mMosaicer != null) {
+ mMosaicer.reset();
+ }
+ }
+
+ private void releaseMosaicer() {
+ mMosaicer.freeMosaicMemory();
+
+ for (int i = 0; i < NUM_FRAMES_IN_BUFFER; i++) {
+ mFrames[i] = null;
+ }
+ }
+
+ private void setupAlphaBlendBitmap(int width, int height) {
+ int downSizedW = width / DOWN_SAMPLE_FACTOR;
+ int downSizedH = height / DOWN_SAMPLE_FACTOR;
+ mColors = new int[downSizedW * downSizedH];
+ mLRBitmapAlpha = Bitmap.createBitmap(downSizedW, downSizedH, Config.ARGB_8888);
+ mTransformationMatrix = new Matrix();
+ }
+
+ private void releaseAlphaBlendBitmap() {
+ mColors = null;
+ if (mLRBitmapAlpha != null) {
+ mLRBitmapAlpha.recycle();
+ mLRBitmapAlpha = null;
+ }
}
public void createMosaic(boolean highRes) {
@@ -102,13 +137,6 @@ public class MosaicFrameProcessor {
return mMosaicer.getFinalMosaicNV21();
}
- public void reset() {
- mFillIn = 0;
- if (mMosaicer != null) {
- mMosaicer.reset();
- }
- }
-
// Processes the last filled image frame through the mosaicer and
// updates the UI to show progress.
// When done, processes and displays the final mosaic.
diff --git a/src/com/android/camera/panorama/PanoramaActivity.java b/src/com/android/camera/panorama/PanoramaActivity.java
index 336533f..2619286 100644
--- a/src/com/android/camera/panorama/PanoramaActivity.java
+++ b/src/com/android/camera/panorama/PanoramaActivity.java
@@ -56,44 +56,60 @@ import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
-public class PanoramaActivity extends Activity implements
- ModePicker.OnModeChangeListener {
+public class PanoramaActivity extends Activity implements ModePicker.OnModeChangeListener {
public static final int DEFAULT_SWEEP_ANGLE = 60;
+
public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL;
+
public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720;
private static final String TAG = "PanoramaActivity";
- private static final float NS2S = 1.0f / 1000000000.0f; // TODO: commit for this constant.
+
+ private static final float NS2S = 1.0f / 1000000000.0f; // TODO: commit for
+ // this constant.
private Preview mPreview;
+
private ImageView mReview;
+
private CaptureView mCaptureView;
+
private ShutterButton mShutterButton;
+
private int mPreviewWidth;
+
private int mPreviewHeight;
private Camera mCameraDevice;
+
private SensorManager mSensorManager;
+
private Sensor mSensor;
+
private ModePicker mModePicker;
private MosaicFrameProcessor mMosaicFrameProcessor;
+
private ScannerClient mScannerClient;
private String mCurrentImagePath = null;
+
private long mTimeTaken;
// Need handler for callbacks to the UI thread
private final Handler mHandler = new Handler();
/**
- * Inner class to tell the gallery app to scan the newly created mosaic images.
- * TODO: insert the image to media store.
+ * Inner class to tell the gallery app to scan the newly created mosaic
+ * images. TODO: insert the image to media store.
*/
private static final class ScannerClient implements MediaScannerConnectionClient {
ArrayList<String> mPaths = new ArrayList<String>();
+
MediaScannerConnection mScannerConnection;
+
boolean mConnected;
+
Object mLock = new Object();
public ScannerClient(Context context) {
@@ -184,7 +200,7 @@ public class PanoramaActivity extends Activity implements
int w = size.width;
// we only want 4:3 format.
int d = DEFAULT_CAPTURE_PIXELS - h * w;
- if (needSmaller && d < 0) { // no bigger preview than 960x720.
+ if (needSmaller && d < 0) { // no bigger preview than 960x720.
continue;
}
if (need4To3 && (h * 4 != w * 3)) {
@@ -231,9 +247,8 @@ public class PanoramaActivity extends Activity implements
private void configureCamera(Parameters parameters) {
mCameraDevice.setParameters(parameters);
- Util.setCameraDisplayOrientation(
- Util.getDisplayRotation(this),
- CameraHolder.instance().getBackCameraId(), mCameraDevice);
+ Util.setCameraDisplayOrientation(Util.getDisplayRotation(this), CameraHolder.instance()
+ .getBackCameraId(), mCameraDevice);
int bufSize = getPreviewBufSize();
Log.v(TAG, "BufSize = " + bufSize);
@@ -248,7 +263,8 @@ public class PanoramaActivity extends Activity implements
}
private boolean switchToOtherMode(int mode) {
- if (isFinishing()) return false;
+ if (isFinishing())
+ return false;
MenuHelper.gotoMode(mode, this);
finish();
return true;
@@ -262,11 +278,9 @@ public class PanoramaActivity extends Activity implements
}
}
- public void setCaptureStarted(int sweepAngle, int blendType) {
+ public void setCaptureStarted() {
// Reset values so we can do this again.
mTimeTaken = System.currentTimeMillis();
- mMosaicFrameProcessor = new MosaicFrameProcessor(sweepAngle - 5, mPreviewWidth,
- mPreviewHeight, getPreviewBufSize());
mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() {
@Override
@@ -286,7 +300,8 @@ public class PanoramaActivity extends Activity implements
@Override
public void onPreviewFrame(final byte[] data, Camera camera) {
mMosaicFrameProcessor.processFrame(data, mPreviewWidth, mPreviewHeight);
- // The returned buffer needs be added back to callback buffer again.
+ // The returned buffer needs be added back to callback buffer
+ // again.
camera.addCallbackBuffer(data);
}
});
@@ -317,15 +332,14 @@ public class PanoramaActivity extends Activity implements
Bitmap lowResBitmapAlpha, Matrix transformationMatrix) {
mCaptureView.setBitmap(lowResBitmapAlpha, transformationMatrix);
if (translationRate > 150) {
- // TODO: remove the text and draw implications according to the UI spec.
+ // TODO: remove the text and draw implications according to the UI
+ // spec.
mCaptureView.setStatusText("S L O W D O W N");
- mCaptureView.setSweepAngle(
- Math.max(traversedAngleX, traversedAngleY) + 1);
+ mCaptureView.setSweepAngle(Math.max(traversedAngleX, traversedAngleY) + 1);
mCaptureView.invalidate();
} else {
mCaptureView.setStatusText("");
- mCaptureView.setSweepAngle(
- Math.max(traversedAngleX, traversedAngleY) + 1);
+ mCaptureView.setSweepAngle(Math.max(traversedAngleX, traversedAngleY) + 1);
mCaptureView.invalidate();
}
}
@@ -345,7 +359,7 @@ public class PanoramaActivity extends Activity implements
mShutterButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- setCaptureStarted(DEFAULT_SWEEP_ANGLE, DEFAULT_BLEND_MODE);
+ setCaptureStarted();
}
});
mModePicker = (ModePicker) findViewById(R.id.mode_picker);
@@ -365,8 +379,11 @@ public class PanoramaActivity extends Activity implements
@Override
protected void onPause() {
super.onPause();
- mSensorManager.unregisterListener(mListener);
releaseCamera();
+ mMosaicFrameProcessor.onPause();
+ mCaptureView.onPause();
+ mSensorManager.unregisterListener(mListener);
+ System.gc();
}
@Override
@@ -374,21 +391,32 @@ public class PanoramaActivity extends Activity implements
super.onResume();
/*
- * It is not necessary to get accelerometer events at a very high
- * rate, by using a slower rate (SENSOR_DELAY_UI), we get an
- * automatic low-pass filter, which "extracts" the gravity component
- * of the acceleration. As an added benefit, we use less power and
- * CPU resources.
+ * It is not necessary to get accelerometer events at a very high rate,
+ * by using a slower rate (SENSOR_DELAY_UI), we get an automatic
+ * low-pass filter, which "extracts" the gravity component of the
+ * acceleration. As an added benefit, we use less power and CPU
+ * resources.
*/
mSensorManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_UI);
setupCamera();
mPreview.setCameraDevice(mCameraDevice);
mCameraDevice.startPreview();
+
+ if (mMosaicFrameProcessor == null) {
+ // Start the activity for the first time.
+ mMosaicFrameProcessor = new MosaicFrameProcessor(DEFAULT_SWEEP_ANGLE - 5,
+ mPreviewWidth, mPreviewHeight, getPreviewBufSize());
+ mMosaicFrameProcessor.onResume();
+ } else {
+ mMosaicFrameProcessor.onResume();
+ }
+ mCaptureView.onResume();
}
private void releaseCamera() {
- if (mCameraDevice != null){
+ if (mCameraDevice != null) {
+ mCameraDevice.stopPreview();
CameraHolder.instance().release();
mCameraDevice = null;
}
@@ -396,7 +424,9 @@ public class PanoramaActivity extends Activity implements
private final SensorEventListener mListener = new SensorEventListener() {
private float mCompassCurrX; // degrees
+
private float mCompassCurrY; // degrees
+
private float mTimestamp;
public void onSensorChanged(SensorEvent event) {
@@ -427,8 +457,10 @@ public class PanoramaActivity extends Activity implements
public void generateAndStoreFinalMosaic(boolean highRes) {
mMosaicFrameProcessor.createMosaic(highRes);
- mCurrentImagePath = Storage.DIRECTORY + "/" + PanoUtil.createName(
- getResources().getString(R.string.pano_file_name_format), mTimeTaken);
+ mCurrentImagePath = Storage.DIRECTORY
+ + "/"
+ + PanoUtil.createName(getResources().getString(R.string.pano_file_name_format),
+ mTimeTaken);
if (highRes) {
mCurrentImagePath += "_HR.jpg";
@@ -455,7 +487,7 @@ public class PanoramaActivity extends Activity implements
yuvimage.compressToJpeg(new Rect(0, 0, width, height), 100, out);
out.close();
- // Now's a good time to run the GC. Since we won't do any explicit
+ // Now's a good time to run the GC. Since we won't do any explicit
// allocation during the test, the GC should stay dormant and not
// influence our results.
System.runFinalization();
diff --git a/src/com/android/camera/panorama/Preview.java b/src/com/android/camera/panorama/Preview.java
index 5a6cf9f..4063e67 100644
--- a/src/com/android/camera/panorama/Preview.java
+++ b/src/com/android/camera/panorama/Preview.java
@@ -24,7 +24,6 @@ import android.view.SurfaceView;
class Preview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "Preview";
-
private android.hardware.Camera mCameraDevice;
public Preview(Context context, AttributeSet attrs) {