diff options
-rw-r--r-- | AndroidManifest.xml | 7 | ||||
-rw-r--r-- | src/com/android/camera/Thumbnail.java | 62 | ||||
-rwxr-xr-x | src/com/android/camera/panorama/PanoramaActivity.java | 40 |
3 files changed, 75 insertions, 34 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1a64093..ee57c31 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -61,11 +61,16 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> + <!-- Suppose users enter panorama from launcher, turn off the screen, + turn on the screen, and enter the camera from the lock screen. + They can switch to panorama from there. Use singleTask so there + will be only one panorama activity. --> <activity android:name="com.android.camera.panorama.PanoramaActivity" android:label="@string/pano_dialog_title" android:configChanges="orientation|screenSize|keyboardHidden" android:clearTaskOnLaunch="true" - android:windowSoftInputMode="stateAlwaysHidden|adjustPan"> + android:windowSoftInputMode="stateAlwaysHidden|adjustPan" + android:launchMode="singleTask"> </activity> </application> </manifest> diff --git a/src/com/android/camera/Thumbnail.java b/src/com/android/camera/Thumbnail.java index 165614b..7775c37 100644 --- a/src/com/android/camera/Thumbnail.java +++ b/src/com/android/camera/Thumbnail.java @@ -52,6 +52,10 @@ public class Thumbnail { // whether this thumbnail is read from file private boolean mFromFile = false; + // Camera, VideoCamera, and Panorama share the same thumbnail. Use sLock + // to serialize the access. + private static Object sLock = new Object(); + public Thumbnail(Uri uri, Bitmap bitmap, int orientation) { mUri = uri; mBitmap = rotateImage(bitmap, orientation); @@ -100,19 +104,21 @@ public class Thumbnail { FileOutputStream f = null; BufferedOutputStream b = null; DataOutputStream d = null; - try { - f = new FileOutputStream(file); - b = new BufferedOutputStream(f, BUFSIZE); - d = new DataOutputStream(b); - d.writeUTF(mUri.toString()); - mBitmap.compress(Bitmap.CompressFormat.JPEG, 90, d); - d.close(); - } catch (IOException e) { - Log.e(TAG, "Fail to store bitmap. path=" + file.getPath(), e); - } finally { - Util.closeSilently(f); - Util.closeSilently(b); - Util.closeSilently(d); + synchronized (sLock) { + try { + f = new FileOutputStream(file); + b = new BufferedOutputStream(f, BUFSIZE); + d = new DataOutputStream(b); + d.writeUTF(mUri.toString()); + mBitmap.compress(Bitmap.CompressFormat.JPEG, 90, d); + d.close(); + } catch (IOException e) { + Log.e(TAG, "Fail to store bitmap. path=" + file.getPath(), e); + } finally { + Util.closeSilently(f); + Util.closeSilently(b); + Util.closeSilently(d); + } } } @@ -124,20 +130,22 @@ public class Thumbnail { FileInputStream f = null; BufferedInputStream b = null; DataInputStream d = null; - try { - f = new FileInputStream(file); - b = new BufferedInputStream(f, BUFSIZE); - d = new DataInputStream(b); - uri = Uri.parse(d.readUTF()); - bitmap = BitmapFactory.decodeStream(d); - d.close(); - } catch (IOException e) { - Log.i(TAG, "Fail to load bitmap. " + e); - return null; - } finally { - Util.closeSilently(f); - Util.closeSilently(b); - Util.closeSilently(d); + synchronized (sLock) { + try { + f = new FileInputStream(file); + b = new BufferedInputStream(f, BUFSIZE); + d = new DataInputStream(b); + uri = Uri.parse(d.readUTF()); + bitmap = BitmapFactory.decodeStream(d); + d.close(); + } catch (IOException e) { + Log.i(TAG, "Fail to load bitmap. " + e); + return null; + } finally { + Util.closeSilently(f); + Util.closeSilently(b); + Util.closeSilently(d); + } } Thumbnail thumbnail = createThumbnail(uri, bitmap, 0); if (thumbnail != null) thumbnail.setFromFile(true); diff --git a/src/com/android/camera/panorama/PanoramaActivity.java b/src/com/android/camera/panorama/PanoramaActivity.java index 02816f4..46f9e34 100755 --- a/src/com/android/camera/panorama/PanoramaActivity.java +++ b/src/com/android/camera/panorama/PanoramaActivity.java @@ -59,6 +59,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.ParcelFileDescriptor; +import android.os.PowerManager; import android.util.Log; import android.view.Gravity; import android.view.Menu; @@ -153,6 +154,7 @@ public class PanoramaActivity extends ActivityBase implements private int mCaptureState; private SensorManager mSensorManager; private Sensor mSensor; + private PowerManager.WakeLock mPartialWakeLock; private ModePicker mModePicker; private MosaicFrameProcessor mMosaicFrameProcessor; private long mTimeTaken; @@ -278,6 +280,8 @@ public class PanoramaActivity extends ActivityBase implements if (mSensor == null) { mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); } + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Panorama"); mOrientationEventListener = new PanoOrientationEventListener(this); @@ -302,6 +306,9 @@ public class PanoramaActivity extends ActivityBase implements break; case MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL: onBackgroundThreadFinished(); + // If the activity is paused, save the thumbnail to the file here. + // If not, it will be saved in onPause. + if (mPausing) saveThumbnailToFile(); // Set the thumbnail bitmap here because mThumbnailView must be accessed // from the UI thread. updateThumbnailButton(); @@ -454,7 +461,11 @@ public class PanoramaActivity extends ActivityBase implements runOnUiThread(new Runnable() { @Override public void run() { - if (!mPausing) { + // If panorama is generating low res or high res mosaic, it + // means users exit and come back to panorama. Do not start the + // preview. Preview will be started after final mosaic is + // generated. + if (!mPausing && !mThreadRunning) { startCameraPreview(); } } @@ -815,11 +826,23 @@ public class PanoramaActivity extends ActivityBase implements } } + private void saveThumbnailToFile() { + if (mThumbnail != null && !mThumbnail.fromFile()) { + mThumbnail.saveTo(new File(getFilesDir(), Thumbnail.LAST_THUMB_FILENAME)); + } + } + public void saveHighResMosaic() { runBackgroundThread(new Thread() { @Override public void run() { - MosaicJpeg jpeg = generateFinalMosaic(true); + mPartialWakeLock.acquire(); + MosaicJpeg jpeg; + try { + jpeg = generateFinalMosaic(true); + } finally { + mPartialWakeLock.release(); + } if (jpeg == null) { // Cancelled by user. mMainHandler.sendEmptyMessage(MSG_RESET_TO_PREVIEW); @@ -979,7 +1002,6 @@ public class PanoramaActivity extends ActivityBase implements super.onPause(); mPausing = true; - cancelHighResComputation(); // Stop the capturing first. if (mCaptureState == CAPTURE_STATE_MOSAIC) { stopCapture(true); @@ -987,9 +1009,7 @@ public class PanoramaActivity extends ActivityBase implements } if (mSharePopup != null) mSharePopup.dismiss(); - if (mThumbnail != null && !mThumbnail.fromFile()) { - mThumbnail.saveTo(new File(getFilesDir(), Thumbnail.LAST_THUMB_FILENAME)); - } + saveThumbnailToFile(); releaseCamera(); mMosaicView.onPause(); @@ -1120,6 +1140,14 @@ public class PanoramaActivity extends ActivityBase implements if (mCaptureState != CAPTURE_STATE_MOSAIC) keepScreenOnAwhile(); } + @Override + public void onBackPressed() { + // If panorama is generating low res or high res mosaic, ignore back + // key. So the activity will not be destroyed. + if (mThreadRunning) return; + super.onBackPressed(); + } + private void resetScreenOn() { mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); |