summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOwen Lin <owenlin@google.com>2009-08-18 13:33:49 +0800
committerOwen Lin <owenlin@google.com>2009-08-31 13:34:59 +0800
commit3f3c857e3f34650c15d764810335024654b0fcc3 (patch)
treecefd6d499cf53cc71e1f2307d9161df9c4f8840c /src
parent0cc79e160dded70c5986d63fc137badbd329e87e (diff)
downloadLegacyCamera-3f3c857e3f34650c15d764810335024654b0fcc3.zip
LegacyCamera-3f3c857e3f34650c15d764810335024654b0fcc3.tar.gz
LegacyCamera-3f3c857e3f34650c15d764810335024654b0fcc3.tar.bz2
Show error dialog when the camera hardware is busy (Eg: hijack by other
activity). We also change the behavior of the "Camera button", if the camera is being used by others. We just ignore the request and won't start the camera. Change-Id: Icf3b00113aba61c9aa3f43ba07cf6944085d5d52
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/Camera.java51
-rw-r--r--src/com/android/camera/CameraButtonIntentReceiver.java10
-rw-r--r--src/com/android/camera/CameraHardwareException.java5
-rw-r--r--src/com/android/camera/CameraHolder.java16
-rw-r--r--src/com/android/camera/CameraSettings.java12
-rw-r--r--src/com/android/camera/Util.java24
-rw-r--r--src/com/android/camera/VideoCamera.java49
7 files changed, 138 insertions, 29 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index fb2e76d..5ee9128 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
@@ -143,6 +144,7 @@ public class Camera extends Activity implements View.OnClickListener,
private ToneGenerator mFocusToneGenerator;
private ZoomButtonsController mZoomButtons;
private Switcher mSwitcher;
+ private boolean mStartPreviewFail = false;
// mPostCaptureAlert, mLastPictureButton, mThumbController
// are non-null only if isImageCaptureIntent() is true.
@@ -734,7 +736,12 @@ public class Camera extends Activity implements View.OnClickListener,
*/
Thread startPreviewThread = new Thread(new Runnable() {
public void run() {
- startPreview();
+ try {
+ mStartPreviewFail = false;
+ startPreview();
+ } catch (CameraHardwareException e) {
+ mStartPreviewFail = true;
+ }
}
});
startPreviewThread.start();
@@ -766,6 +773,7 @@ public class Camera extends Activity implements View.OnClickListener,
// Make sure preview is started.
try {
startPreviewThread.join();
+ if (mStartPreviewFail) showCameraErrorAndFinish();
} catch (InterruptedException ex) {
// ignore
}
@@ -1009,8 +1017,13 @@ public class Camera extends Activity implements View.OnClickListener,
mImageCapture = new ImageCapture();
// Start the preview if it is not started.
- if (!mPreviewing) {
- startPreview();
+ if (!mPreviewing && !mStartPreviewFail) {
+ try {
+ startPreview();
+ } catch (CameraHardwareException e) {
+ showCameraErrorAndFinish();
+ return;
+ }
}
if (mSurfaceHolder != null) {
@@ -1254,12 +1267,17 @@ public class Camera extends Activity implements View.OnClickListener,
return;
}
+ // The mCameraDevice will be null if it is fail to connect to the
+ // camera hardware. In this case we will show a dialog and then
+ // finish the activity, so it's OK to ignore it.
+ if (mCameraDevice == null) return;
+
mSurfaceHolder = holder;
mViewFinderWidth = w;
mViewFinderHeight = h;
// Sometimes surfaceChanged is called after onPause. Ignore it.
- if (mPausing) return;
+ if (mPausing || isFinishing()) return;
// Set preview display if the surface is being created. Preview was
// already started.
@@ -1293,11 +1311,10 @@ public class Camera extends Activity implements View.OnClickListener,
}
}
- private boolean ensureCameraDevice() {
+ private void ensureCameraDevice() throws CameraHardwareException {
if (mCameraDevice == null) {
mCameraDevice = CameraHolder.instance().open();
}
- return mCameraDevice != null;
}
private void updateLastImage() {
@@ -1318,10 +1335,22 @@ public class Camera extends Activity implements View.OnClickListener,
list.close();
}
+ private void showCameraErrorAndFinish() {
+ Resources ress = getResources();
+ Util.showFatalErrorAndFinish(Camera.this,
+ ress.getString(R.string.camera_error_title),
+ ress.getString(R.string.cannot_connect_camera));
+ }
+
private void restartPreview() {
// make sure the surfaceview fills the whole screen when previewing
mSurfaceView.setAspectRatio(VideoPreview.DONT_CARE);
- startPreview();
+ try {
+ startPreview();
+ } catch (CameraHardwareException e) {
+ showCameraErrorAndFinish();
+ return;
+ }
// Calculate this in advance of each shot so we don't add to shutter
// latency. It's true that someone else could write to the SD card in
@@ -1339,12 +1368,10 @@ public class Camera extends Activity implements View.OnClickListener,
}
}
- private void startPreview() {
- if (mPausing) return;
-
- if (!ensureCameraDevice()) return;
+ private void startPreview() throws CameraHardwareException {
+ if (mPausing || isFinishing()) return;
- if (isFinishing()) return;
+ ensureCameraDevice();
// If we're previewing already, stop the preview first (this will blank
// the screen).
diff --git a/src/com/android/camera/CameraButtonIntentReceiver.java b/src/com/android/camera/CameraButtonIntentReceiver.java
index 3eae965..5926709 100644
--- a/src/com/android/camera/CameraButtonIntentReceiver.java
+++ b/src/com/android/camera/CameraButtonIntentReceiver.java
@@ -26,6 +26,16 @@ public class CameraButtonIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ // Try to get the camera hardware
+ try {
+ CameraHolder holder = CameraHolder.instance();
+ android.hardware.Camera device = holder.open();
+ holder.keep();
+ holder.release();
+ } catch (CameraHardwareException e) {
+ // ignore the event if camera hardware cannot be connected
+ return;
+ }
Intent i = new Intent(Intent.ACTION_MAIN);
i.setClass(context, Camera.class);
i.addCategory("android.intent.category.LAUNCHER");
diff --git a/src/com/android/camera/CameraHardwareException.java b/src/com/android/camera/CameraHardwareException.java
new file mode 100644
index 0000000..f746f48
--- /dev/null
+++ b/src/com/android/camera/CameraHardwareException.java
@@ -0,0 +1,5 @@
+package com.android.camera;
+
+public class CameraHardwareException extends Exception {
+
+}
diff --git a/src/com/android/camera/CameraHolder.java b/src/com/android/camera/CameraHolder.java
index 89f02e7..98f2797 100644
--- a/src/com/android/camera/CameraHolder.java
+++ b/src/com/android/camera/CameraHolder.java
@@ -16,6 +16,8 @@
package com.android.camera;
+import static com.android.camera.Util.Assert;
+
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -24,8 +26,6 @@ import android.util.Log;
import java.io.IOException;
-import static com.android.camera.Util.Assert;
-
//
// CameraHolder is used to hold an android.hardware.Camera instance.
//
@@ -41,7 +41,7 @@ public class CameraHolder {
private static final String TAG = "CameraHolder";
private android.hardware.Camera mCameraDevice;
private long mKeepBeforeTime = 0; // Keep the Camera before this time.
- private Handler mHandler;
+ private final Handler mHandler;
private int mUsers = 0; // number of open() - number of release()
// Use a singleton.
@@ -75,10 +75,16 @@ public class CameraHolder {
mHandler = new MyHandler(ht.getLooper());
}
- public synchronized android.hardware.Camera open() {
+ public synchronized android.hardware.Camera open()
+ throws CameraHardwareException {
Assert(mUsers == 0);
if (mCameraDevice == null) {
- mCameraDevice = android.hardware.Camera.open();
+ try {
+ mCameraDevice = android.hardware.Camera.open();
+ } catch (RuntimeException e) {
+ Log.e(TAG, "fail to connect Camera", e);
+ throw new CameraHardwareException();
+ }
} else {
try {
mCameraDevice.reconnect();
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 7ff3310..78e0724 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -18,6 +18,7 @@ package com.android.camera;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
import android.hardware.Camera.Parameters;
import android.os.Bundle;
import android.preference.ListPreference;
@@ -80,7 +81,16 @@ public class CameraSettings extends PreferenceActivity implements
registerOnSharedPreferenceChangeListener(this);
// Get parameters.
- android.hardware.Camera device = CameraHolder.instance().open();
+ android.hardware.Camera device;
+ try {
+ device = CameraHolder.instance().open();
+ } catch (CameraHardwareException e) {
+ Resources ress = getResources();
+ Util.showFatalErrorAndFinish(this,
+ ress.getString(R.string.camera_error_title),
+ ress.getString(R.string.cannot_connect_camera));
+ return;
+ }
mParameters = device.getParameters();
CameraHolder.instance().release();
diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java
index 2742247..b1ad8d2 100644
--- a/src/com/android/camera/Util.java
+++ b/src/com/android/camera/Util.java
@@ -16,10 +16,11 @@
package com.android.camera;
-import com.android.camera.gallery.IImage;
-
+import android.app.Activity;
+import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentResolver;
+import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -34,6 +35,8 @@ import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
+import com.android.camera.gallery.IImage;
+
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.FileDescriptor;
@@ -512,4 +515,21 @@ public class Util {
options.inNativeAlloc = true;
return options;
}
+
+ public static void showFatalErrorAndFinish(
+ final Activity activity, String title, String message) {
+ DialogInterface.OnClickListener buttonListener =
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ activity.finish();
+ }
+ };
+ new AlertDialog.Builder(activity)
+ .setCancelable(false)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle(title)
+ .setMessage(message)
+ .setNeutralButton(R.string.details_ok, buttonListener)
+ .show();
+ }
}
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index d596b6f..c5befa6 100644
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -25,6 +25,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.media.MediaRecorder;
@@ -115,6 +116,7 @@ public class VideoCamera extends Activity implements View.OnClickListener,
// are non-null only if mIsVideoCaptureIntent is true.
private ImageView mLastPictureButton;
private ThumbnailController mThumbController;
+ private boolean mStartPreviewFail = false;
private int mStorageStatus = STORAGE_STATUS_OK;
@@ -181,7 +183,9 @@ public class VideoCamera extends Activity implements View.OnClickListener,
}
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mReceiver = null;
+
+ private class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -202,12 +206,19 @@ public class VideoCamera extends Activity implements View.OnClickListener,
updateAndShowStorageHint(true);
}
}
- };
+ }
private static String createName(long dateTaken) {
return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
}
+ private void showCameraBusyAndFinish() {
+ Resources ress = getResources();
+ Util.showFatalErrorAndFinish(VideoCamera.this,
+ ress.getString(R.string.camera_error_title),
+ ress.getString(R.string.cannot_connect_camera));
+ }
+
/** Called with the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
@@ -222,7 +233,12 @@ public class VideoCamera extends Activity implements View.OnClickListener,
*/
Thread startPreviewThread = new Thread(new Runnable() {
public void run() {
- startPreview();
+ try {
+ mStartPreviewFail = false;
+ startPreview();
+ } catch (CameraHardwareException e) {
+ mStartPreviewFail = true;
+ }
}
});
startPreviewThread.start();
@@ -280,6 +296,7 @@ public class VideoCamera extends Activity implements View.OnClickListener,
// Make sure preview is started.
try {
startPreviewThread.join();
+ if (mStartPreviewFail) showCameraBusyAndFinish();
} catch (InterruptedException ex) {
// ignore
}
@@ -480,10 +497,14 @@ public class VideoCamera extends Activity implements View.OnClickListener,
mPausing = false;
readVideoSizePreference();
- if (!mPreviewing) {
- startPreview();
+ if (!mPreviewing && !mStartPreviewFail) {
+ try {
+ startPreview();
+ } catch (CameraHardwareException e) {
+ showCameraBusyAndFinish();
+ return;
+ }
}
-
setScreenTimeoutLong();
// install an intent filter to receive SD card related events.
@@ -494,6 +515,7 @@ public class VideoCamera extends Activity implements View.OnClickListener,
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
intentFilter.addDataScheme("file");
+ mReceiver = new MyBroadcastReceiver();
registerReceiver(mReceiver, intentFilter);
mStorageStatus = getStorageStatus(true);
@@ -525,7 +547,7 @@ public class VideoCamera extends Activity implements View.OnClickListener,
}
}
- private void startPreview() {
+ private void startPreview() throws CameraHardwareException {
Log.v(TAG, "startPreview");
if (mPreviewing) {
// After recording a video, preview is not stopped. So just return.
@@ -597,7 +619,10 @@ public class VideoCamera extends Activity implements View.OnClickListener,
}
closeCamera();
- unregisterReceiver(mReceiver);
+ if (mReceiver != null) {
+ unregisterReceiver(mReceiver);
+ mReceiver = null;
+ }
setScreenTimeoutSystemDefault();
if (!mIsVideoCaptureIntent) {
@@ -678,6 +703,11 @@ public class VideoCamera extends Activity implements View.OnClickListener,
return;
}
+ // The mCameraDevice will be null if it is fail to connect to the
+ // camera hardware. In this case we will show a dialog and then
+ // finish the activity, so it's OK to ignore it.
+ if (mCameraDevice == null) return;
+
if (mMediaRecorderRecording) {
stopVideoRecording();
}
@@ -791,7 +821,8 @@ public class VideoCamera extends Activity implements View.OnClickListener,
if (mRecorderInitialized) return true;
// We will call initializeRecorder() again when the alert is hidden.
- if (isAlertVisible()) {
+ // If the mCameraDevice is null, then this activity is going to finish
+ if (isAlertVisible() || mCameraDevice == null) {
return false;
}