summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/camera/Camera.java203
1 files changed, 111 insertions, 92 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 9cb30c9..46620f4 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -120,8 +120,6 @@ public class Camera extends Activity implements View.OnClickListener,
private int mOriginalViewFinderWidth, mOriginalViewFinderHeight;
private int mViewFinderWidth, mViewFinderHeight;
private boolean mPreviewing = false;
- private final Object mCameraLock = new Object();
- private Thread mStartPreviewThread = null;
private Capturer mCaptureObject;
private ImageCapture mImageCapture = null;
@@ -507,8 +505,13 @@ public class Camera extends Activity implements View.OnClickListener,
* Initiate the capture of an image.
*/
public void initiate(boolean captureOnly) {
+ if (mCameraDevice == null) {
+ return;
+ }
+
mCancel = false;
mCapturing = true;
+
capture(captureOnly);
}
@@ -649,6 +652,15 @@ public class Camera extends Activity implements View.OnClickListener,
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ // To reduce startup time, we open camera device in another thread.
+ // We make sure the camera is opened at the end of onCreate.
+ Thread openCameraThread = new Thread(new Runnable() {
+ public void run() {
+ mCameraDevice = android.hardware.Camera.open();
+ }
+ });
+ openCameraThread.start();
+
// To reduce startup time, we run some service creation code in another thread.
// We make sure the services are loaded at the end of onCreate().
Thread loadServiceThread = new Thread(new Runnable() {
@@ -713,6 +725,7 @@ public class Camera extends Activity implements View.OnClickListener,
// Make sure the services are loaded.
try {
+ openCameraThread.join();
loadServiceThread.join();
} catch (InterruptedException ex) {
}
@@ -865,7 +878,7 @@ public class Camera extends Activity implements View.OnClickListener,
}
public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
- if (!mPreviewing || mPausing) {
+ if (mPausing) {
return;
}
switch (button.getId()) {
@@ -876,7 +889,7 @@ public class Camera extends Activity implements View.OnClickListener,
}
public void onShutterButtonClick(ShutterButton button) {
- if (!mPreviewing || mPausing) {
+ if (mPausing) {
return;
}
switch (button.getId()) {
@@ -1081,16 +1094,12 @@ public class Camera extends Activity implements View.OnClickListener,
break;
case KeyEvent.KEYCODE_FOCUS:
if (event.getRepeatCount() == 0) {
- if (mPreviewing) {
- doFocus(true);
- }
+ doFocus(true);
}
return true;
case KeyEvent.KEYCODE_CAMERA:
if (event.getRepeatCount() == 0) {
- if (mPreviewing) {
- doSnap();
- }
+ doSnap();
}
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
@@ -1099,15 +1108,13 @@ public class Camera extends Activity implements View.OnClickListener,
if (event.getRepeatCount() == 0) {
// Start auto-focus immediately to reduce shutter lag. After the shutter button
// gets the focus, doFocus() will be called again but it is fine.
- if (mPreviewing) {
- doFocus(true);
- if (mShutterButton.isInTouchMode()) {
- mShutterButton.requestFocusFromTouch();
- } else {
- mShutterButton.requestFocus();
- }
- mShutterButton.setPressed(true);
+ doFocus(true);
+ if (mShutterButton.isInTouchMode()) {
+ mShutterButton.requestFocusFromTouch();
+ } else {
+ mShutterButton.requestFocus();
}
+ mShutterButton.setPressed(true);
}
return true;
}
@@ -1180,7 +1187,6 @@ public class Camera extends Activity implements View.OnClickListener,
mSurfaceHolder = null;
}
- // always call stopPreview before calling closeCamera
private void closeCamera() {
if (mCameraDevice != null) {
mCameraDevice.release();
@@ -1189,6 +1195,13 @@ public class Camera extends Activity implements View.OnClickListener,
}
}
+ private boolean ensureCameraDevice() {
+ if (mCameraDevice == null) {
+ mCameraDevice = android.hardware.Camera.open();
+ }
+ return mCameraDevice != null;
+ }
+
private void updateLastImage() {
ImageManager.IImageList list = ImageManager.instance().allImages(
this,
@@ -1242,6 +1255,9 @@ public class Camera extends Activity implements View.OnClickListener,
return;
}
+ if (!ensureCameraDevice())
+ return;
+
if (mSurfaceHolder == null)
return;
@@ -1263,98 +1279,101 @@ public class Camera extends Activity implements View.OnClickListener,
return;
/*
- * start preview on a separate thread
+ * start the preview if we're asked to...
*/
- // start camera preview
- synchronized(mCameraLock) {
- if (mStartPreviewThread == null) {
- mStartPreviewThread = new Thread(new Runnable() {
- public void run() {
-
- // create camera object
- synchronized(mCameraLock) {
- if (mCameraDevice == null) {
- mCameraDevice = android.hardware.Camera.open();
- }
- }
- // we want to start the preview and we're previewing already,
- // stop the preview first (this will blank the screen).
- if (mPreviewing)
- stopPreview();
+ // we want to start the preview and we're previewing already,
+ // stop the preview first (this will blank the screen).
+ if (mPreviewing)
+ stopPreview();
- // this blanks the screen if the surface changed, no-op otherwise
- try {
- mCameraDevice.setPreviewDisplay(mSurfaceHolder);
- } catch (IOException exception) {
- mCameraDevice.release();
- mCameraDevice = null;
- // TODO: add more exception handling logic here
- return;
- }
+ // this blanks the screen if the surface changed, no-op otherwise
+ try {
+ mCameraDevice.setPreviewDisplay(mSurfaceHolder);
+ } catch (IOException exception) {
+ mCameraDevice.release();
+ mCameraDevice = null;
+ // TODO: add more exception handling logic here
+ return;
+ }
- // request the preview size, the hardware may not honor it,
- // if we depended on it we would have to query the size again
- mParameters = mCameraDevice.getParameters();
- mParameters.setPreviewSize(mViewFinderWidth, mViewFinderHeight);
- try {
- mCameraDevice.setParameters(mParameters);
- } catch (IllegalArgumentException e) {
- // Ignore this error, it happens in the simulator.
- }
+ // request the preview size, the hardware may not honor it,
+ // if we depended on it we would have to query the size again
+ mParameters = mCameraDevice.getParameters();
+ mParameters.setPreviewSize(w, h);
+ try {
+ mCameraDevice.setParameters(mParameters);
+ } catch (IllegalArgumentException e) {
+ // Ignore this error, it happens in the simulator.
+ }
- final long wallTimeStart = SystemClock.elapsedRealtime();
- final long threadTimeStart = Debug.threadCpuTimeNanos();
- if (Config.LOGV) Log.v(TAG, "calling mCameraDevice.startPreview");
- try {
- mCameraDevice.startPreview();
- } catch (Throwable e) {
- // TODO: change Throwable to IOException once android.hardware.Camera.startPreview
- // properly declares that it throws IOException.
- }
- synchronized(mCameraLock) {
- mPreviewing = true;
- mStartPreviewThread = null;
- }
+ final long wallTimeStart = SystemClock.elapsedRealtime();
+ final long threadTimeStart = Debug.threadCpuTimeNanos();
- long threadTimeEnd = Debug.threadCpuTimeNanos();
- long wallTimeEnd = SystemClock.elapsedRealtime();
- if ((wallTimeEnd - wallTimeStart) > 3000) {
- Log.w(TAG, "startPreview() to " + (wallTimeEnd - wallTimeStart) + " ms. Thread time was"
- + (threadTimeEnd - threadTimeStart) / 1000000 + " ms.");
+ final Object watchDogSync = new Object();
+ Thread watchDog = new Thread(new Runnable() {
+ public void run() {
+ int next_warning = 1;
+ while (true) {
+ try {
+ synchronized (watchDogSync) {
+ watchDogSync.wait(1000);
}
+ } catch (InterruptedException ex) {
+ //
}
- });
+ if (mPreviewing) break;
- mStartPreviewThread.start();
+ int delay = (int) (SystemClock.elapsedRealtime() - wallTimeStart) / 1000;
+ if (delay >= next_warning) {
+ if (delay < 120) {
+ Log.e(TAG, "preview hasn't started yet in " + delay + " seconds");
+ } else {
+ Log.e(TAG, "preview hasn't started yet in " + (delay / 60) + " minutes");
+ }
+ if (next_warning < 60) {
+ next_warning <<= 1;
+ if (next_warning == 16) {
+ next_warning = 15;
+ }
+ } else {
+ next_warning += 60;
+ }
+ }
+ }
}
+ });
+
+ watchDog.start();
+
+ if (Config.LOGV)
+ Log.v(TAG, "calling mCameraDevice.startPreview");
+ try {
+ mCameraDevice.startPreview();
+ } catch (Throwable e) {
+ // TODO: change Throwable to IOException once android.hardware.Camera.startPreview
+ // properly declares that it throws IOException.
}
- }
+ mPreviewing = true;
- // wait for preview thread if it is running
- private void joinPreviewThread() {
- Thread startPreviewThread;
- synchronized(mCameraLock) {
- startPreviewThread = mStartPreviewThread;
+ synchronized (watchDogSync) {
+ watchDogSync.notify();
}
- if (startPreviewThread != null) {
- try {
- startPreviewThread.join();
- } catch (InterruptedException ex) {
- }
+
+ long threadTimeEnd = Debug.threadCpuTimeNanos();
+ long wallTimeEnd = SystemClock.elapsedRealtime();
+ if ((wallTimeEnd - wallTimeStart) > 3000) {
+ Log.w(TAG, "startPreview() to " + (wallTimeEnd - wallTimeStart) + " ms. Thread time was"
+ + (threadTimeEnd - threadTimeStart) / 1000000 + " ms.");
}
}
private void stopPreview() {
- joinPreviewThread();
- synchronized(mCameraLock) {
- if (mCameraDevice != null && mPreviewing) {
- mCameraDevice.stopPreview();
- }
- mPreviewing = false;
+ if (mCameraDevice != null && mPreviewing) {
+ mCameraDevice.stopPreview();
}
-
+ mPreviewing = false;
// If auto focus was in progress, it would have been canceled.
clearFocusState();
}