diff options
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/camera/Camera.java | 51 | ||||
-rw-r--r-- | src/com/android/camera/CameraButtonIntentReceiver.java | 10 | ||||
-rw-r--r-- | src/com/android/camera/CameraHardwareException.java | 5 | ||||
-rw-r--r-- | src/com/android/camera/CameraHolder.java | 16 | ||||
-rw-r--r-- | src/com/android/camera/CameraSettings.java | 12 | ||||
-rw-r--r-- | src/com/android/camera/Util.java | 24 | ||||
-rw-r--r-- | src/com/android/camera/VideoCamera.java | 49 |
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; } |